blob: b722917e8f890d2be902e677726e62715745e821 [file] [log] [blame]
[email protected]a1595312012-01-22 03:25:041// Copyright (c) 2012 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]5a76b812011-12-21 20:52:006#include "net/base/completion_callback.h"
[email protected]4f386422010-07-20 04:19:497#include "net/spdy/spdy_stream.h"
[email protected]9e1bdd32011-02-03 21:48:348#include "net/spdy/spdy_http_utils.h"
[email protected]4f386422010-07-20 04:19:499#include "net/spdy/spdy_session.h"
[email protected]4f386422010-07-20 04:19:4910#include "net/spdy/spdy_test_util.h"
11#include "testing/gtest/include/gtest/gtest.h"
12
[email protected]4f386422010-07-20 04:19:4913// TODO(ukai): factor out common part with spdy_http_stream_unittest.cc
[email protected]b9ec6882011-07-01 07:40:2614//
15namespace net {
[email protected]4f386422010-07-20 04:19:4916
17namespace {
18
[email protected]4f386422010-07-20 04:19:4919class TestSpdyStreamDelegate : public SpdyStream::Delegate {
20 public:
21 TestSpdyStreamDelegate(SpdyStream* stream,
22 IOBufferWithSize* buf,
[email protected]5a76b812011-12-21 20:52:0023 const CompletionCallback& callback)
[email protected]4f386422010-07-20 04:19:4924 : stream_(stream),
25 buf_(buf),
26 callback_(callback),
27 send_headers_completed_(false),
28 response_(new spdy::SpdyHeaderBlock),
29 data_sent_(0),
30 closed_(false) {}
31 virtual ~TestSpdyStreamDelegate() {}
32
33 virtual bool OnSendHeadersComplete(int status) {
34 send_headers_completed_ = true;
35 return true;
36 }
37 virtual int OnSendBody() {
38 ADD_FAILURE() << "OnSendBody should not be called";
39 return ERR_UNEXPECTED;
40 }
[email protected]0c9bf872011-03-04 17:53:2241 virtual int OnSendBodyComplete(int /*status*/, bool* /*eof*/) {
[email protected]4f386422010-07-20 04:19:4942 ADD_FAILURE() << "OnSendBodyComplete should not be called";
[email protected]0c9bf872011-03-04 17:53:2243 return ERR_UNEXPECTED;
[email protected]4f386422010-07-20 04:19:4944 }
[email protected]310240592010-08-05 21:04:1945
[email protected]4f386422010-07-20 04:19:4946 virtual int OnResponseReceived(const spdy::SpdyHeaderBlock& response,
47 base::Time response_time,
48 int status) {
49 EXPECT_TRUE(send_headers_completed_);
50 *response_ = response;
51 if (buf_) {
52 EXPECT_EQ(ERR_IO_PENDING,
53 stream_->WriteStreamData(buf_.get(), buf_->size(),
54 spdy::DATA_FLAG_NONE));
55 }
56 return status;
57 }
58 virtual void OnDataReceived(const char* buffer, int bytes) {
59 received_data_ += std::string(buffer, bytes);
60 }
61 virtual void OnDataSent(int length) {
62 data_sent_ += length;
63 }
64 virtual void OnClose(int status) {
65 closed_ = true;
[email protected]5a76b812011-12-21 20:52:0066 CompletionCallback callback = callback_;
67 callback_.Reset();
68 callback.Run(OK);
[email protected]4f386422010-07-20 04:19:4969 }
[email protected]0c9bf872011-03-04 17:53:2270 virtual void set_chunk_callback(net::ChunkCallback *) {}
[email protected]4f386422010-07-20 04:19:4971
72 bool send_headers_completed() const { return send_headers_completed_; }
73 const linked_ptr<spdy::SpdyHeaderBlock>& response() const {
74 return response_;
75 }
76 const std::string& received_data() const { return received_data_; }
77 int data_sent() const { return data_sent_; }
78 bool closed() const { return closed_; }
79
80 private:
81 SpdyStream* stream_;
82 scoped_refptr<IOBufferWithSize> buf_;
[email protected]5a76b812011-12-21 20:52:0083 CompletionCallback callback_;
[email protected]4f386422010-07-20 04:19:4984 bool send_headers_completed_;
85 linked_ptr<spdy::SpdyHeaderBlock> response_;
86 std::string received_data_;
87 int data_sent_;
88 bool closed_;
89};
90
91spdy::SpdyFrame* ConstructSpdyBodyFrame(const char* data, int length) {
92 spdy::SpdyFramer framer;
93 return framer.CreateDataFrame(1, data, length, spdy::DATA_FLAG_NONE);
94}
95
96} // anonymous namespace
97
98class SpdyStreamTest : public testing::Test {
99 protected:
100 SpdyStreamTest() {
101 }
102
103 scoped_refptr<SpdySession> CreateSpdySession() {
104 spdy::SpdyFramer::set_enable_compression_default(false);
105 HostPortPair host_port_pair("www.google.com", 80);
[email protected]31e68d72010-08-25 06:36:58106 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]4f386422010-07-20 04:19:49107 scoped_refptr<SpdySession> session(
[email protected]102e27c2011-02-23 01:01:31108 session_->spdy_session_pool()->Get(pair, BoundNetLog()));
[email protected]4f386422010-07-20 04:19:49109 return session;
110 }
111
112 virtual void TearDown() {
113 MessageLoop::current()->RunAllPending();
114 }
115
116 scoped_refptr<HttpNetworkSession> session_;
117};
118
119TEST_F(SpdyStreamTest, SendDataAfterOpen) {
[email protected]30c942b2010-07-21 16:59:59120 SpdySessionDependencies session_deps;
[email protected]4f386422010-07-20 04:19:49121
[email protected]30c942b2010-07-21 16:59:59122 session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps);
[email protected]4f386422010-07-20 04:19:49123 SpdySessionPoolPeer pool_peer_(session_->spdy_session_pool());
124
125 const SpdyHeaderInfo kSynStartHeader = {
126 spdy::SYN_STREAM,
127 1,
128 0,
[email protected]c9c6f5c2010-07-31 01:30:03129 net::ConvertRequestPriorityToSpdyPriority(LOWEST),
[email protected]4f386422010-07-20 04:19:49130 spdy::CONTROL_FLAG_NONE,
131 false,
132 spdy::INVALID,
133 NULL,
134 0,
135 spdy::DATA_FLAG_NONE
136 };
137 static const char* const kGetHeaders[] = {
138 "method",
139 "GET",
[email protected]a7a265ef2010-12-08 18:05:57140 "scheme",
141 "http",
142 "host",
143 "www.google.com",
144 "path",
145 "/",
[email protected]4f386422010-07-20 04:19:49146 "version",
147 "HTTP/1.1",
148 };
149 scoped_ptr<spdy::SpdyFrame> req(
150 ConstructSpdyPacket(
151 kSynStartHeader, NULL, 0, kGetHeaders, arraysize(kGetHeaders) / 2));
152 scoped_ptr<spdy::SpdyFrame> msg(
153 ConstructSpdyBodyFrame("\0hello!\xff", 8));
154 MockWrite writes[] = {
155 CreateMockWrite(*req),
156 CreateMockWrite(*msg),
157 };
158 writes[0].sequence_number = 0;
159 writes[1].sequence_number = 2;
160
161 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
162 scoped_ptr<spdy::SpdyFrame> echo(
163 ConstructSpdyBodyFrame("\0hello!\xff", 8));
164 MockRead reads[] = {
165 CreateMockRead(*resp),
166 CreateMockRead(*echo),
[email protected]8ddf8322012-02-23 18:08:06167 MockRead(ASYNC, 0, 0), // EOF
[email protected]4f386422010-07-20 04:19:49168 };
169 reads[0].sequence_number = 1;
170 reads[1].sequence_number = 3;
171 reads[2].sequence_number = 4;
172
[email protected]a1595312012-01-22 03:25:04173 scoped_ptr<OrderedSocketData> data(
[email protected]4f386422010-07-20 04:19:49174 new OrderedSocketData(reads, arraysize(reads),
175 writes, arraysize(writes)));
[email protected]d973e99a2012-02-17 21:02:36176 MockConnect connect_data(SYNCHRONOUS, OK);
[email protected]1442b29a2010-07-20 11:14:54177 data->set_connect_data(connect_data);
[email protected]4f386422010-07-20 04:19:49178
[email protected]3b7828432010-08-18 18:33:27179 session_deps.socket_factory->AddSocketDataProvider(data.get());
[email protected]4f386422010-07-20 04:19:49180 SpdySession::SetSSLMode(false);
181
182 scoped_refptr<SpdySession> session(CreateSpdySession());
[email protected]a7a265ef2010-12-08 18:05:57183 const char* kStreamUrl = "http://www.google.com/";
184 GURL url(kStreamUrl);
[email protected]4f386422010-07-20 04:19:49185
186 HostPortPair host_port_pair("www.google.com", 80);
[email protected]ab739042011-04-07 15:22:28187 scoped_refptr<TransportSocketParams> transport_params(
[email protected]acdda412011-11-15 21:21:29188 new TransportSocketParams(host_port_pair, LOWEST, false, false));
[email protected]02b0c342010-09-25 21:09:38189
190 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
[email protected]6ecf2b92011-12-15 01:14:52191 EXPECT_EQ(OK, connection->Init(host_port_pair.ToString(), transport_params,
192 LOWEST, CompletionCallback(),
193 session_->GetTransportSocketPool(),
194 BoundNetLog()));
[email protected]02b0c342010-09-25 21:09:38195 session->InitializeWithSocket(connection.release(), false, OK);
[email protected]4f386422010-07-20 04:19:49196
197 scoped_refptr<SpdyStream> stream;
198 ASSERT_EQ(
199 OK,
[email protected]49639fa2011-12-20 23:22:41200 session->CreateStream(url, LOWEST, &stream, BoundNetLog(),
201 CompletionCallback()));
[email protected]4f386422010-07-20 04:19:49202 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(8));
203 memcpy(buf->data(), "\0hello!\xff", 8);
[email protected]5a76b812011-12-21 20:52:00204 TestCompletionCallback callback;
[email protected]4f386422010-07-20 04:19:49205
206 scoped_ptr<TestSpdyStreamDelegate> delegate(
[email protected]5a76b812011-12-21 20:52:00207 new TestSpdyStreamDelegate(stream.get(), buf.get(), callback.callback()));
[email protected]4f386422010-07-20 04:19:49208 stream->SetDelegate(delegate.get());
209
[email protected]a7a265ef2010-12-08 18:05:57210 EXPECT_FALSE(stream->HasUrl());
211
[email protected]4f386422010-07-20 04:19:49212 linked_ptr<spdy::SpdyHeaderBlock> headers(new spdy::SpdyHeaderBlock);
213 (*headers)["method"] = "GET";
[email protected]a7a265ef2010-12-08 18:05:57214 (*headers)["scheme"] = url.scheme();
215 (*headers)["host"] = url.host();
216 (*headers)["path"] = url.path();
[email protected]4f386422010-07-20 04:19:49217 (*headers)["version"] = "HTTP/1.1";
218 stream->set_spdy_headers(headers);
[email protected]a7a265ef2010-12-08 18:05:57219 EXPECT_TRUE(stream->HasUrl());
220 EXPECT_EQ(kStreamUrl, stream->GetUrl().spec());
[email protected]4f386422010-07-20 04:19:49221
[email protected]a5c493b92010-08-06 23:04:29222 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequest(true));
[email protected]4f386422010-07-20 04:19:49223
224 EXPECT_EQ(OK, callback.WaitForResult());
225
226 EXPECT_TRUE(delegate->send_headers_completed());
227 EXPECT_EQ("200", (*delegate->response())["status"]);
228 EXPECT_EQ("HTTP/1.1", (*delegate->response())["version"]);
229 EXPECT_EQ(std::string("\0hello!\xff", 8), delegate->received_data());
230 EXPECT_EQ(8, delegate->data_sent());
231 EXPECT_TRUE(delegate->closed());
232}
233
[email protected]a7a265ef2010-12-08 18:05:57234TEST_F(SpdyStreamTest, PushedStream) {
235 const char kStreamUrl[] = "http://www.google.com/";
236
237 SpdySessionDependencies session_deps;
238 session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps);
239 SpdySessionPoolPeer pool_peer_(session_->spdy_session_pool());
240 scoped_refptr<SpdySession> spdy_session(CreateSpdySession());
241 BoundNetLog net_log;
242
243 // Conjure up a stream.
244 scoped_refptr<SpdyStream> stream = new SpdyStream(spdy_session,
245 2,
246 true,
247 net_log);
248 EXPECT_FALSE(stream->response_received());
249 EXPECT_FALSE(stream->HasUrl());
250
251 // Set a couple of headers.
252 spdy::SpdyHeaderBlock response;
253 response["url"] = kStreamUrl;
254 stream->OnResponseReceived(response);
255
256 // Send some basic headers.
257 spdy::SpdyHeaderBlock headers;
258 response["status"] = "200";
259 response["version"] = "OK";
260 stream->OnHeaders(headers);
261
262 stream->set_response_received();
263 EXPECT_TRUE(stream->response_received());
264 EXPECT_TRUE(stream->HasUrl());
265 EXPECT_EQ(kStreamUrl, stream->GetUrl().spec());
266}
267
268
[email protected]4f386422010-07-20 04:19:49269} // namespace net