blob: 327d1974bfe7bd3df54ccb362b123870beccbcf3 [file] [log] [blame]
[email protected]3b63f8f42011-03-28 01:54:151// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]4f386422010-07-20 04:19:492// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]3b63f8f42011-03-28 01:54:155#include "base/memory/ref_counted.h"
[email protected]4f386422010-07-20 04:19:496#include "net/spdy/spdy_stream.h"
[email protected]9e1bdd32011-02-03 21:48:347#include "net/spdy/spdy_http_utils.h"
[email protected]4f386422010-07-20 04:19:498#include "net/spdy/spdy_session.h"
[email protected]4f386422010-07-20 04:19:499#include "net/spdy/spdy_test_util.h"
10#include "testing/gtest/include/gtest/gtest.h"
11
12namespace net {
13
14// TODO(ukai): factor out common part with spdy_http_stream_unittest.cc
15class SpdySessionPoolPeer {
16 public:
[email protected]87bfa3f2010-09-30 14:54:5617 explicit SpdySessionPoolPeer(SpdySessionPool* pool)
[email protected]4f386422010-07-20 04:19:4918 : pool_(pool) {}
19
20 void RemoveSpdySession(const scoped_refptr<SpdySession>& session) {
21 pool_->Remove(session);
22 }
23
24 private:
[email protected]87bfa3f2010-09-30 14:54:5625 SpdySessionPool* const pool_;
[email protected]4f386422010-07-20 04:19:4926
27 DISALLOW_COPY_AND_ASSIGN(SpdySessionPoolPeer);
28};
29
30namespace {
31
[email protected]4f386422010-07-20 04:19:4932class TestSpdyStreamDelegate : public SpdyStream::Delegate {
33 public:
34 TestSpdyStreamDelegate(SpdyStream* stream,
35 IOBufferWithSize* buf,
36 CompletionCallback* callback)
37 : stream_(stream),
38 buf_(buf),
39 callback_(callback),
40 send_headers_completed_(false),
41 response_(new spdy::SpdyHeaderBlock),
42 data_sent_(0),
43 closed_(false) {}
44 virtual ~TestSpdyStreamDelegate() {}
45
46 virtual bool OnSendHeadersComplete(int status) {
47 send_headers_completed_ = true;
48 return true;
49 }
50 virtual int OnSendBody() {
51 ADD_FAILURE() << "OnSendBody should not be called";
52 return ERR_UNEXPECTED;
53 }
[email protected]0c9bf872011-03-04 17:53:2254 virtual int OnSendBodyComplete(int /*status*/, bool* /*eof*/) {
[email protected]4f386422010-07-20 04:19:4955 ADD_FAILURE() << "OnSendBodyComplete should not be called";
[email protected]0c9bf872011-03-04 17:53:2256 return ERR_UNEXPECTED;
[email protected]4f386422010-07-20 04:19:4957 }
[email protected]310240592010-08-05 21:04:1958
[email protected]4f386422010-07-20 04:19:4959 virtual int OnResponseReceived(const spdy::SpdyHeaderBlock& response,
60 base::Time response_time,
61 int status) {
62 EXPECT_TRUE(send_headers_completed_);
63 *response_ = response;
64 if (buf_) {
65 EXPECT_EQ(ERR_IO_PENDING,
66 stream_->WriteStreamData(buf_.get(), buf_->size(),
67 spdy::DATA_FLAG_NONE));
68 }
69 return status;
70 }
71 virtual void OnDataReceived(const char* buffer, int bytes) {
72 received_data_ += std::string(buffer, bytes);
73 }
74 virtual void OnDataSent(int length) {
75 data_sent_ += length;
76 }
77 virtual void OnClose(int status) {
78 closed_ = true;
79 CompletionCallback* callback = callback_;
80 callback_ = NULL;
81 callback->Run(OK);
82 }
[email protected]0c9bf872011-03-04 17:53:2283 virtual void set_chunk_callback(net::ChunkCallback *) {}
[email protected]4f386422010-07-20 04:19:4984
85 bool send_headers_completed() const { return send_headers_completed_; }
86 const linked_ptr<spdy::SpdyHeaderBlock>& response() const {
87 return response_;
88 }
89 const std::string& received_data() const { return received_data_; }
90 int data_sent() const { return data_sent_; }
91 bool closed() const { return closed_; }
92
93 private:
94 SpdyStream* stream_;
95 scoped_refptr<IOBufferWithSize> buf_;
96 CompletionCallback* callback_;
97 bool send_headers_completed_;
98 linked_ptr<spdy::SpdyHeaderBlock> response_;
99 std::string received_data_;
100 int data_sent_;
101 bool closed_;
102};
103
104spdy::SpdyFrame* ConstructSpdyBodyFrame(const char* data, int length) {
105 spdy::SpdyFramer framer;
106 return framer.CreateDataFrame(1, data, length, spdy::DATA_FLAG_NONE);
107}
108
109} // anonymous namespace
110
111class SpdyStreamTest : public testing::Test {
112 protected:
113 SpdyStreamTest() {
114 }
115
116 scoped_refptr<SpdySession> CreateSpdySession() {
117 spdy::SpdyFramer::set_enable_compression_default(false);
118 HostPortPair host_port_pair("www.google.com", 80);
[email protected]31e68d72010-08-25 06:36:58119 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]4f386422010-07-20 04:19:49120 scoped_refptr<SpdySession> session(
[email protected]102e27c2011-02-23 01:01:31121 session_->spdy_session_pool()->Get(pair, BoundNetLog()));
[email protected]4f386422010-07-20 04:19:49122 return session;
123 }
124
125 virtual void TearDown() {
126 MessageLoop::current()->RunAllPending();
127 }
128
129 scoped_refptr<HttpNetworkSession> session_;
130};
131
132TEST_F(SpdyStreamTest, SendDataAfterOpen) {
[email protected]30c942b2010-07-21 16:59:59133 SpdySessionDependencies session_deps;
[email protected]4f386422010-07-20 04:19:49134
[email protected]30c942b2010-07-21 16:59:59135 session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps);
[email protected]4f386422010-07-20 04:19:49136 SpdySessionPoolPeer pool_peer_(session_->spdy_session_pool());
137
138 const SpdyHeaderInfo kSynStartHeader = {
139 spdy::SYN_STREAM,
140 1,
141 0,
[email protected]c9c6f5c2010-07-31 01:30:03142 net::ConvertRequestPriorityToSpdyPriority(LOWEST),
[email protected]4f386422010-07-20 04:19:49143 spdy::CONTROL_FLAG_NONE,
144 false,
145 spdy::INVALID,
146 NULL,
147 0,
148 spdy::DATA_FLAG_NONE
149 };
150 static const char* const kGetHeaders[] = {
151 "method",
152 "GET",
[email protected]a7a265ef2010-12-08 18:05:57153 "scheme",
154 "http",
155 "host",
156 "www.google.com",
157 "path",
158 "/",
[email protected]4f386422010-07-20 04:19:49159 "version",
160 "HTTP/1.1",
161 };
162 scoped_ptr<spdy::SpdyFrame> req(
163 ConstructSpdyPacket(
164 kSynStartHeader, NULL, 0, kGetHeaders, arraysize(kGetHeaders) / 2));
165 scoped_ptr<spdy::SpdyFrame> msg(
166 ConstructSpdyBodyFrame("\0hello!\xff", 8));
167 MockWrite writes[] = {
168 CreateMockWrite(*req),
169 CreateMockWrite(*msg),
170 };
171 writes[0].sequence_number = 0;
172 writes[1].sequence_number = 2;
173
174 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
175 scoped_ptr<spdy::SpdyFrame> echo(
176 ConstructSpdyBodyFrame("\0hello!\xff", 8));
177 MockRead reads[] = {
178 CreateMockRead(*resp),
179 CreateMockRead(*echo),
180 MockRead(true, 0, 0), // EOF
181 };
182 reads[0].sequence_number = 1;
183 reads[1].sequence_number = 3;
184 reads[2].sequence_number = 4;
185
186 scoped_refptr<OrderedSocketData> data(
187 new OrderedSocketData(reads, arraysize(reads),
188 writes, arraysize(writes)));
[email protected]1442b29a2010-07-20 11:14:54189 MockConnect connect_data(false, OK);
190 data->set_connect_data(connect_data);
[email protected]4f386422010-07-20 04:19:49191
[email protected]3b7828432010-08-18 18:33:27192 session_deps.socket_factory->AddSocketDataProvider(data.get());
[email protected]4f386422010-07-20 04:19:49193 SpdySession::SetSSLMode(false);
194
195 scoped_refptr<SpdySession> session(CreateSpdySession());
[email protected]a7a265ef2010-12-08 18:05:57196 const char* kStreamUrl = "http://www.google.com/";
197 GURL url(kStreamUrl);
[email protected]4f386422010-07-20 04:19:49198
199 HostPortPair host_port_pair("www.google.com", 80);
[email protected]ad8e04a2010-11-01 04:16:27200 scoped_refptr<TCPSocketParams> tcp_params(
201 new TCPSocketParams(host_port_pair, LOWEST, GURL(), false));
[email protected]02b0c342010-09-25 21:09:38202
203 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
204 EXPECT_EQ(OK,
205 connection->Init(host_port_pair.ToString(), tcp_params, LOWEST,
206 NULL, session_->tcp_socket_pool(), BoundNetLog()));
207 session->InitializeWithSocket(connection.release(), false, OK);
[email protected]4f386422010-07-20 04:19:49208
209 scoped_refptr<SpdyStream> stream;
210 ASSERT_EQ(
211 OK,
[email protected]971746e2010-07-21 03:02:23212 session->CreateStream(url, LOWEST, &stream, BoundNetLog(), NULL));
[email protected]4f386422010-07-20 04:19:49213 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(8));
214 memcpy(buf->data(), "\0hello!\xff", 8);
215 TestCompletionCallback callback;
216
217 scoped_ptr<TestSpdyStreamDelegate> delegate(
218 new TestSpdyStreamDelegate(stream.get(), buf.get(), &callback));
219 stream->SetDelegate(delegate.get());
220
[email protected]a7a265ef2010-12-08 18:05:57221 EXPECT_FALSE(stream->HasUrl());
222
[email protected]4f386422010-07-20 04:19:49223 linked_ptr<spdy::SpdyHeaderBlock> headers(new spdy::SpdyHeaderBlock);
224 (*headers)["method"] = "GET";
[email protected]a7a265ef2010-12-08 18:05:57225 (*headers)["scheme"] = url.scheme();
226 (*headers)["host"] = url.host();
227 (*headers)["path"] = url.path();
[email protected]4f386422010-07-20 04:19:49228 (*headers)["version"] = "HTTP/1.1";
229 stream->set_spdy_headers(headers);
[email protected]a7a265ef2010-12-08 18:05:57230 EXPECT_TRUE(stream->HasUrl());
231 EXPECT_EQ(kStreamUrl, stream->GetUrl().spec());
[email protected]4f386422010-07-20 04:19:49232
[email protected]a5c493b92010-08-06 23:04:29233 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequest(true));
[email protected]4f386422010-07-20 04:19:49234
235 EXPECT_EQ(OK, callback.WaitForResult());
236
237 EXPECT_TRUE(delegate->send_headers_completed());
238 EXPECT_EQ("200", (*delegate->response())["status"]);
239 EXPECT_EQ("HTTP/1.1", (*delegate->response())["version"]);
240 EXPECT_EQ(std::string("\0hello!\xff", 8), delegate->received_data());
241 EXPECT_EQ(8, delegate->data_sent());
242 EXPECT_TRUE(delegate->closed());
243}
244
[email protected]a7a265ef2010-12-08 18:05:57245TEST_F(SpdyStreamTest, PushedStream) {
246 const char kStreamUrl[] = "http://www.google.com/";
247
248 SpdySessionDependencies session_deps;
249 session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps);
250 SpdySessionPoolPeer pool_peer_(session_->spdy_session_pool());
251 scoped_refptr<SpdySession> spdy_session(CreateSpdySession());
252 BoundNetLog net_log;
253
254 // Conjure up a stream.
255 scoped_refptr<SpdyStream> stream = new SpdyStream(spdy_session,
256 2,
257 true,
258 net_log);
259 EXPECT_FALSE(stream->response_received());
260 EXPECT_FALSE(stream->HasUrl());
261
262 // Set a couple of headers.
263 spdy::SpdyHeaderBlock response;
264 response["url"] = kStreamUrl;
265 stream->OnResponseReceived(response);
266
267 // Send some basic headers.
268 spdy::SpdyHeaderBlock headers;
269 response["status"] = "200";
270 response["version"] = "OK";
271 stream->OnHeaders(headers);
272
273 stream->set_response_received();
274 EXPECT_TRUE(stream->response_received());
275 EXPECT_TRUE(stream->HasUrl());
276 EXPECT_EQ(kStreamUrl, stream->GetUrl().spec());
277}
278
279
[email protected]4f386422010-07-20 04:19:49280} // namespace net