[email protected] | a159531 | 2012-01-22 03:25:04 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | 3b63f8f4 | 2011-03-28 01:54:15 | [diff] [blame] | 5 | #include "base/memory/ref_counted.h" |
[email protected] | 5a76b81 | 2011-12-21 20:52:00 | [diff] [blame] | 6 | #include "net/base/completion_callback.h" |
[email protected] | d245c34 | 2012-02-23 20:49:15 | [diff] [blame] | 7 | #include "net/base/net_log_unittest.h" |
[email protected] | f54c8579 | 2012-03-08 19:06:41 | [diff] [blame] | 8 | #include "net/spdy/buffered_spdy_framer.h" |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 9 | #include "net/spdy/spdy_stream.h" |
[email protected] | 9e1bdd3 | 2011-02-03 21:48:34 | [diff] [blame] | 10 | #include "net/spdy/spdy_http_utils.h" |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 11 | #include "net/spdy/spdy_session.h" |
[email protected] | 448d4ca5 | 2012-03-04 04:12:23 | [diff] [blame] | 12 | #include "net/spdy/spdy_test_util_spdy3.h" |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 13 | #include "testing/gtest/include/gtest/gtest.h" |
| 14 | |
[email protected] | 448d4ca5 | 2012-03-04 04:12:23 | [diff] [blame] | 15 | using namespace net::test_spdy3; |
| 16 | |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 17 | // TODO(ukai): factor out common part with spdy_http_stream_unittest.cc |
[email protected] | b9ec688 | 2011-07-01 07:40:26 | [diff] [blame] | 18 | // |
| 19 | namespace net { |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 20 | |
| 21 | namespace { |
| 22 | |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 23 | class TestSpdyStreamDelegate : public SpdyStream::Delegate { |
| 24 | public: |
| 25 | TestSpdyStreamDelegate(SpdyStream* stream, |
| 26 | IOBufferWithSize* buf, |
[email protected] | 5a76b81 | 2011-12-21 20:52:00 | [diff] [blame] | 27 | const CompletionCallback& callback) |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 28 | : stream_(stream), |
| 29 | buf_(buf), |
| 30 | callback_(callback), |
| 31 | send_headers_completed_(false), |
| 32 | response_(new spdy::SpdyHeaderBlock), |
| 33 | data_sent_(0), |
| 34 | closed_(false) {} |
| 35 | virtual ~TestSpdyStreamDelegate() {} |
| 36 | |
| 37 | virtual bool OnSendHeadersComplete(int status) { |
| 38 | send_headers_completed_ = true; |
| 39 | return true; |
| 40 | } |
| 41 | virtual int OnSendBody() { |
| 42 | ADD_FAILURE() << "OnSendBody should not be called"; |
| 43 | return ERR_UNEXPECTED; |
| 44 | } |
[email protected] | 0c9bf87 | 2011-03-04 17:53:22 | [diff] [blame] | 45 | virtual int OnSendBodyComplete(int /*status*/, bool* /*eof*/) { |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 46 | ADD_FAILURE() << "OnSendBodyComplete should not be called"; |
[email protected] | 0c9bf87 | 2011-03-04 17:53:22 | [diff] [blame] | 47 | return ERR_UNEXPECTED; |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 48 | } |
[email protected] | 31024059 | 2010-08-05 21:04:19 | [diff] [blame] | 49 | |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 50 | virtual int OnResponseReceived(const spdy::SpdyHeaderBlock& response, |
| 51 | base::Time response_time, |
| 52 | int status) { |
| 53 | EXPECT_TRUE(send_headers_completed_); |
| 54 | *response_ = response; |
| 55 | if (buf_) { |
| 56 | EXPECT_EQ(ERR_IO_PENDING, |
| 57 | stream_->WriteStreamData(buf_.get(), buf_->size(), |
| 58 | spdy::DATA_FLAG_NONE)); |
| 59 | } |
| 60 | return status; |
| 61 | } |
| 62 | virtual void OnDataReceived(const char* buffer, int bytes) { |
| 63 | received_data_ += std::string(buffer, bytes); |
| 64 | } |
| 65 | virtual void OnDataSent(int length) { |
| 66 | data_sent_ += length; |
| 67 | } |
| 68 | virtual void OnClose(int status) { |
| 69 | closed_ = true; |
[email protected] | 5a76b81 | 2011-12-21 20:52:00 | [diff] [blame] | 70 | CompletionCallback callback = callback_; |
| 71 | callback_.Reset(); |
| 72 | callback.Run(OK); |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 73 | } |
[email protected] | 0c9bf87 | 2011-03-04 17:53:22 | [diff] [blame] | 74 | virtual void set_chunk_callback(net::ChunkCallback *) {} |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 75 | |
| 76 | bool send_headers_completed() const { return send_headers_completed_; } |
| 77 | const linked_ptr<spdy::SpdyHeaderBlock>& response() const { |
| 78 | return response_; |
| 79 | } |
| 80 | const std::string& received_data() const { return received_data_; } |
| 81 | int data_sent() const { return data_sent_; } |
| 82 | bool closed() const { return closed_; } |
| 83 | |
| 84 | private: |
| 85 | SpdyStream* stream_; |
| 86 | scoped_refptr<IOBufferWithSize> buf_; |
[email protected] | 5a76b81 | 2011-12-21 20:52:00 | [diff] [blame] | 87 | CompletionCallback callback_; |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 88 | bool send_headers_completed_; |
| 89 | linked_ptr<spdy::SpdyHeaderBlock> response_; |
| 90 | std::string received_data_; |
| 91 | int data_sent_; |
| 92 | bool closed_; |
| 93 | }; |
| 94 | |
| 95 | spdy::SpdyFrame* ConstructSpdyBodyFrame(const char* data, int length) { |
[email protected] | f54c8579 | 2012-03-08 19:06:41 | [diff] [blame] | 96 | spdy::BufferedSpdyFramer framer(3); |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 97 | return framer.CreateDataFrame(1, data, length, spdy::DATA_FLAG_NONE); |
| 98 | } |
| 99 | |
| 100 | } // anonymous namespace |
| 101 | |
[email protected] | 448d4ca5 | 2012-03-04 04:12:23 | [diff] [blame] | 102 | class SpdyStreamSpdy3Test : public testing::Test { |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 103 | protected: |
[email protected] | 448d4ca5 | 2012-03-04 04:12:23 | [diff] [blame] | 104 | SpdyStreamSpdy3Test() { |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 105 | } |
| 106 | |
| 107 | scoped_refptr<SpdySession> CreateSpdySession() { |
| 108 | spdy::SpdyFramer::set_enable_compression_default(false); |
| 109 | HostPortPair host_port_pair("www.google.com", 80); |
[email protected] | 31e68d7 | 2010-08-25 06:36:58 | [diff] [blame] | 110 | HostPortProxyPair pair(host_port_pair, ProxyServer::Direct()); |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 111 | scoped_refptr<SpdySession> session( |
[email protected] | 102e27c | 2011-02-23 01:01:31 | [diff] [blame] | 112 | session_->spdy_session_pool()->Get(pair, BoundNetLog())); |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 113 | return session; |
| 114 | } |
| 115 | |
[email protected] | 39c48fc | 2012-03-12 18:42:12 | [diff] [blame] | 116 | virtual void SetUp() { |
| 117 | SpdySession::set_default_protocol(SSLClientSocket::kProtoSPDY3); |
| 118 | } |
| 119 | |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 120 | virtual void TearDown() { |
| 121 | MessageLoop::current()->RunAllPending(); |
| 122 | } |
| 123 | |
| 124 | scoped_refptr<HttpNetworkSession> session_; |
| 125 | }; |
| 126 | |
[email protected] | 448d4ca5 | 2012-03-04 04:12:23 | [diff] [blame] | 127 | TEST_F(SpdyStreamSpdy3Test, SendDataAfterOpen) { |
[email protected] | 30c942b | 2010-07-21 16:59:59 | [diff] [blame] | 128 | SpdySessionDependencies session_deps; |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 129 | |
[email protected] | 30c942b | 2010-07-21 16:59:59 | [diff] [blame] | 130 | session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps); |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 131 | SpdySessionPoolPeer pool_peer_(session_->spdy_session_pool()); |
| 132 | |
| 133 | const SpdyHeaderInfo kSynStartHeader = { |
| 134 | spdy::SYN_STREAM, |
| 135 | 1, |
| 136 | 0, |
[email protected] | c9c6f5c | 2010-07-31 01:30:03 | [diff] [blame] | 137 | net::ConvertRequestPriorityToSpdyPriority(LOWEST), |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 138 | spdy::CONTROL_FLAG_NONE, |
| 139 | false, |
| 140 | spdy::INVALID, |
| 141 | NULL, |
| 142 | 0, |
| 143 | spdy::DATA_FLAG_NONE |
| 144 | }; |
| 145 | static const char* const kGetHeaders[] = { |
[email protected] | 0e861e9 | 2012-03-15 18:42:19 | [diff] [blame] | 146 | ":method", |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 147 | "GET", |
[email protected] | 0e861e9 | 2012-03-15 18:42:19 | [diff] [blame] | 148 | ":scheme", |
[email protected] | a7a265ef | 2010-12-08 18:05:57 | [diff] [blame] | 149 | "http", |
[email protected] | 0e861e9 | 2012-03-15 18:42:19 | [diff] [blame] | 150 | ":host", |
[email protected] | a7a265ef | 2010-12-08 18:05:57 | [diff] [blame] | 151 | "www.google.com", |
[email protected] | 0e861e9 | 2012-03-15 18:42:19 | [diff] [blame] | 152 | ":path", |
[email protected] | a7a265ef | 2010-12-08 18:05:57 | [diff] [blame] | 153 | "/", |
[email protected] | 0e861e9 | 2012-03-15 18:42:19 | [diff] [blame] | 154 | ":version", |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 155 | "HTTP/1.1", |
| 156 | }; |
| 157 | scoped_ptr<spdy::SpdyFrame> req( |
| 158 | ConstructSpdyPacket( |
| 159 | kSynStartHeader, NULL, 0, kGetHeaders, arraysize(kGetHeaders) / 2)); |
| 160 | scoped_ptr<spdy::SpdyFrame> msg( |
| 161 | ConstructSpdyBodyFrame("\0hello!\xff", 8)); |
| 162 | MockWrite writes[] = { |
| 163 | CreateMockWrite(*req), |
| 164 | CreateMockWrite(*msg), |
| 165 | }; |
| 166 | writes[0].sequence_number = 0; |
| 167 | writes[1].sequence_number = 2; |
| 168 | |
| 169 | scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 170 | scoped_ptr<spdy::SpdyFrame> echo( |
| 171 | ConstructSpdyBodyFrame("\0hello!\xff", 8)); |
| 172 | MockRead reads[] = { |
| 173 | CreateMockRead(*resp), |
| 174 | CreateMockRead(*echo), |
[email protected] | 8ddf832 | 2012-02-23 18:08:06 | [diff] [blame] | 175 | MockRead(ASYNC, 0, 0), // EOF |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 176 | }; |
| 177 | reads[0].sequence_number = 1; |
| 178 | reads[1].sequence_number = 3; |
| 179 | reads[2].sequence_number = 4; |
| 180 | |
[email protected] | a159531 | 2012-01-22 03:25:04 | [diff] [blame] | 181 | scoped_ptr<OrderedSocketData> data( |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 182 | new OrderedSocketData(reads, arraysize(reads), |
| 183 | writes, arraysize(writes))); |
[email protected] | d973e99a | 2012-02-17 21:02:36 | [diff] [blame] | 184 | MockConnect connect_data(SYNCHRONOUS, OK); |
[email protected] | 1442b29a | 2010-07-20 11:14:54 | [diff] [blame] | 185 | data->set_connect_data(connect_data); |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 186 | |
[email protected] | 3b782843 | 2010-08-18 18:33:27 | [diff] [blame] | 187 | session_deps.socket_factory->AddSocketDataProvider(data.get()); |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 188 | |
| 189 | scoped_refptr<SpdySession> session(CreateSpdySession()); |
[email protected] | a7a265ef | 2010-12-08 18:05:57 | [diff] [blame] | 190 | const char* kStreamUrl = "http://www.google.com/"; |
| 191 | GURL url(kStreamUrl); |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 192 | |
| 193 | HostPortPair host_port_pair("www.google.com", 80); |
[email protected] | ab73904 | 2011-04-07 15:22:28 | [diff] [blame] | 194 | scoped_refptr<TransportSocketParams> transport_params( |
[email protected] | acdda41 | 2011-11-15 21:21:29 | [diff] [blame] | 195 | new TransportSocketParams(host_port_pair, LOWEST, false, false)); |
[email protected] | 02b0c34 | 2010-09-25 21:09:38 | [diff] [blame] | 196 | |
| 197 | scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); |
[email protected] | 6ecf2b9 | 2011-12-15 01:14:52 | [diff] [blame] | 198 | EXPECT_EQ(OK, connection->Init(host_port_pair.ToString(), transport_params, |
| 199 | LOWEST, CompletionCallback(), |
[email protected] | e5c02664 | 2012-03-17 00:14:02 | [diff] [blame^] | 200 | session_->GetTransportSocketPool( |
| 201 | HttpNetworkSession::NORMAL_SOCKET_POOL), |
[email protected] | 6ecf2b9 | 2011-12-15 01:14:52 | [diff] [blame] | 202 | BoundNetLog())); |
[email protected] | 02b0c34 | 2010-09-25 21:09:38 | [diff] [blame] | 203 | session->InitializeWithSocket(connection.release(), false, OK); |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 204 | |
| 205 | scoped_refptr<SpdyStream> stream; |
| 206 | ASSERT_EQ( |
| 207 | OK, |
[email protected] | 49639fa | 2011-12-20 23:22:41 | [diff] [blame] | 208 | session->CreateStream(url, LOWEST, &stream, BoundNetLog(), |
| 209 | CompletionCallback())); |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 210 | scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(8)); |
| 211 | memcpy(buf->data(), "\0hello!\xff", 8); |
[email protected] | 5a76b81 | 2011-12-21 20:52:00 | [diff] [blame] | 212 | TestCompletionCallback callback; |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 213 | |
| 214 | scoped_ptr<TestSpdyStreamDelegate> delegate( |
[email protected] | 5a76b81 | 2011-12-21 20:52:00 | [diff] [blame] | 215 | new TestSpdyStreamDelegate(stream.get(), buf.get(), callback.callback())); |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 216 | stream->SetDelegate(delegate.get()); |
| 217 | |
[email protected] | a7a265ef | 2010-12-08 18:05:57 | [diff] [blame] | 218 | EXPECT_FALSE(stream->HasUrl()); |
| 219 | |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 220 | linked_ptr<spdy::SpdyHeaderBlock> headers(new spdy::SpdyHeaderBlock); |
[email protected] | 0e861e9 | 2012-03-15 18:42:19 | [diff] [blame] | 221 | (*headers)[":method"] = "GET"; |
| 222 | (*headers)[":scheme"] = url.scheme(); |
| 223 | (*headers)[":host"] = url.host(); |
| 224 | (*headers)[":path"] = url.path(); |
| 225 | (*headers)[":version"] = "HTTP/1.1"; |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 226 | stream->set_spdy_headers(headers); |
[email protected] | a7a265ef | 2010-12-08 18:05:57 | [diff] [blame] | 227 | EXPECT_TRUE(stream->HasUrl()); |
| 228 | EXPECT_EQ(kStreamUrl, stream->GetUrl().spec()); |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 229 | |
[email protected] | a5c493b9 | 2010-08-06 23:04:29 | [diff] [blame] | 230 | EXPECT_EQ(ERR_IO_PENDING, stream->SendRequest(true)); |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 231 | |
| 232 | EXPECT_EQ(OK, callback.WaitForResult()); |
| 233 | |
| 234 | EXPECT_TRUE(delegate->send_headers_completed()); |
| 235 | EXPECT_EQ("200", (*delegate->response())["status"]); |
| 236 | EXPECT_EQ("HTTP/1.1", (*delegate->response())["version"]); |
| 237 | EXPECT_EQ(std::string("\0hello!\xff", 8), delegate->received_data()); |
| 238 | EXPECT_EQ(8, delegate->data_sent()); |
| 239 | EXPECT_TRUE(delegate->closed()); |
| 240 | } |
| 241 | |
[email protected] | 448d4ca5 | 2012-03-04 04:12:23 | [diff] [blame] | 242 | TEST_F(SpdyStreamSpdy3Test, PushedStream) { |
[email protected] | a7a265ef | 2010-12-08 18:05:57 | [diff] [blame] | 243 | const char kStreamUrl[] = "http://www.google.com/"; |
| 244 | |
| 245 | SpdySessionDependencies session_deps; |
| 246 | session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps); |
| 247 | SpdySessionPoolPeer pool_peer_(session_->spdy_session_pool()); |
| 248 | scoped_refptr<SpdySession> spdy_session(CreateSpdySession()); |
[email protected] | 0e861e9 | 2012-03-15 18:42:19 | [diff] [blame] | 249 | |
| 250 | MockRead reads[] = { |
| 251 | MockRead(ASYNC, 0, 0), // EOF |
| 252 | }; |
| 253 | |
| 254 | scoped_ptr<OrderedSocketData> data( |
| 255 | new OrderedSocketData(reads, arraysize(reads), NULL, 0)); |
| 256 | MockConnect connect_data(SYNCHRONOUS, OK); |
| 257 | data->set_connect_data(connect_data); |
| 258 | |
| 259 | session_deps.socket_factory->AddSocketDataProvider(data.get()); |
[email protected] | 0e861e9 | 2012-03-15 18:42:19 | [diff] [blame] | 260 | |
| 261 | HostPortPair host_port_pair("www.google.com", 80); |
| 262 | scoped_refptr<TransportSocketParams> transport_params( |
| 263 | new TransportSocketParams(host_port_pair, LOWEST, false, false)); |
| 264 | scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); |
| 265 | EXPECT_EQ(OK, connection->Init(host_port_pair.ToString(), transport_params, |
| 266 | LOWEST, CompletionCallback(), |
[email protected] | e5c02664 | 2012-03-17 00:14:02 | [diff] [blame^] | 267 | session_->GetTransportSocketPool( |
| 268 | HttpNetworkSession::NORMAL_SOCKET_POOL), |
[email protected] | 0e861e9 | 2012-03-15 18:42:19 | [diff] [blame] | 269 | BoundNetLog())); |
| 270 | spdy_session->InitializeWithSocket(connection.release(), false, OK); |
[email protected] | a7a265ef | 2010-12-08 18:05:57 | [diff] [blame] | 271 | BoundNetLog net_log; |
| 272 | |
| 273 | // Conjure up a stream. |
| 274 | scoped_refptr<SpdyStream> stream = new SpdyStream(spdy_session, |
| 275 | 2, |
| 276 | true, |
| 277 | net_log); |
| 278 | EXPECT_FALSE(stream->response_received()); |
| 279 | EXPECT_FALSE(stream->HasUrl()); |
| 280 | |
| 281 | // Set a couple of headers. |
| 282 | spdy::SpdyHeaderBlock response; |
[email protected] | 0e861e9 | 2012-03-15 18:42:19 | [diff] [blame] | 283 | GURL url(kStreamUrl); |
| 284 | response[":host"] = url.host(); |
| 285 | response[":scheme"] = url.scheme(); |
| 286 | response[":path"] = url.path(); |
[email protected] | a7a265ef | 2010-12-08 18:05:57 | [diff] [blame] | 287 | stream->OnResponseReceived(response); |
| 288 | |
| 289 | // Send some basic headers. |
| 290 | spdy::SpdyHeaderBlock headers; |
| 291 | response["status"] = "200"; |
| 292 | response["version"] = "OK"; |
| 293 | stream->OnHeaders(headers); |
| 294 | |
| 295 | stream->set_response_received(); |
| 296 | EXPECT_TRUE(stream->response_received()); |
| 297 | EXPECT_TRUE(stream->HasUrl()); |
| 298 | EXPECT_EQ(kStreamUrl, stream->GetUrl().spec()); |
| 299 | } |
| 300 | |
[email protected] | 448d4ca5 | 2012-03-04 04:12:23 | [diff] [blame] | 301 | TEST_F(SpdyStreamSpdy3Test, StreamError) { |
[email protected] | d245c34 | 2012-02-23 20:49:15 | [diff] [blame] | 302 | SpdySessionDependencies session_deps; |
| 303 | |
| 304 | session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps); |
| 305 | SpdySessionPoolPeer pool_peer_(session_->spdy_session_pool()); |
| 306 | |
| 307 | const SpdyHeaderInfo kSynStartHeader = { |
| 308 | spdy::SYN_STREAM, |
| 309 | 1, |
| 310 | 0, |
| 311 | net::ConvertRequestPriorityToSpdyPriority(LOWEST), |
| 312 | spdy::CONTROL_FLAG_NONE, |
| 313 | false, |
| 314 | spdy::INVALID, |
| 315 | NULL, |
| 316 | 0, |
| 317 | spdy::DATA_FLAG_NONE |
| 318 | }; |
| 319 | static const char* const kGetHeaders[] = { |
[email protected] | 0e861e9 | 2012-03-15 18:42:19 | [diff] [blame] | 320 | ":method", |
[email protected] | d245c34 | 2012-02-23 20:49:15 | [diff] [blame] | 321 | "GET", |
[email protected] | 0e861e9 | 2012-03-15 18:42:19 | [diff] [blame] | 322 | ":scheme", |
[email protected] | d245c34 | 2012-02-23 20:49:15 | [diff] [blame] | 323 | "http", |
[email protected] | 0e861e9 | 2012-03-15 18:42:19 | [diff] [blame] | 324 | ":host", |
[email protected] | d245c34 | 2012-02-23 20:49:15 | [diff] [blame] | 325 | "www.google.com", |
[email protected] | 0e861e9 | 2012-03-15 18:42:19 | [diff] [blame] | 326 | ":path", |
[email protected] | d245c34 | 2012-02-23 20:49:15 | [diff] [blame] | 327 | "/", |
[email protected] | 0e861e9 | 2012-03-15 18:42:19 | [diff] [blame] | 328 | ":version", |
[email protected] | d245c34 | 2012-02-23 20:49:15 | [diff] [blame] | 329 | "HTTP/1.1", |
| 330 | }; |
| 331 | scoped_ptr<spdy::SpdyFrame> req( |
| 332 | ConstructSpdyPacket( |
| 333 | kSynStartHeader, NULL, 0, kGetHeaders, arraysize(kGetHeaders) / 2)); |
| 334 | scoped_ptr<spdy::SpdyFrame> msg( |
| 335 | ConstructSpdyBodyFrame("\0hello!\xff", 8)); |
| 336 | MockWrite writes[] = { |
| 337 | CreateMockWrite(*req), |
| 338 | CreateMockWrite(*msg), |
| 339 | }; |
| 340 | writes[0].sequence_number = 0; |
| 341 | writes[1].sequence_number = 2; |
| 342 | |
| 343 | scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 344 | scoped_ptr<spdy::SpdyFrame> echo( |
| 345 | ConstructSpdyBodyFrame("\0hello!\xff", 8)); |
| 346 | MockRead reads[] = { |
| 347 | CreateMockRead(*resp), |
| 348 | CreateMockRead(*echo), |
| 349 | MockRead(ASYNC, 0, 0), // EOF |
| 350 | }; |
| 351 | reads[0].sequence_number = 1; |
| 352 | reads[1].sequence_number = 3; |
| 353 | reads[2].sequence_number = 4; |
| 354 | |
| 355 | net::CapturingBoundNetLog log(net::CapturingNetLog::kUnbounded); |
| 356 | |
| 357 | scoped_ptr<OrderedSocketData> data( |
| 358 | new OrderedSocketData(reads, arraysize(reads), |
| 359 | writes, arraysize(writes))); |
| 360 | MockConnect connect_data(SYNCHRONOUS, OK); |
| 361 | data->set_connect_data(connect_data); |
| 362 | |
| 363 | session_deps.socket_factory->AddSocketDataProvider(data.get()); |
[email protected] | d245c34 | 2012-02-23 20:49:15 | [diff] [blame] | 364 | |
| 365 | scoped_refptr<SpdySession> session(CreateSpdySession()); |
| 366 | const char* kStreamUrl = "http://www.google.com/"; |
| 367 | GURL url(kStreamUrl); |
| 368 | |
| 369 | HostPortPair host_port_pair("www.google.com", 80); |
| 370 | scoped_refptr<TransportSocketParams> transport_params( |
| 371 | new TransportSocketParams(host_port_pair, LOWEST, false, false)); |
| 372 | |
| 373 | scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); |
| 374 | EXPECT_EQ(OK, connection->Init(host_port_pair.ToString(), transport_params, |
| 375 | LOWEST, CompletionCallback(), |
[email protected] | e5c02664 | 2012-03-17 00:14:02 | [diff] [blame^] | 376 | session_->GetTransportSocketPool( |
| 377 | HttpNetworkSession::NORMAL_SOCKET_POOL), |
[email protected] | d245c34 | 2012-02-23 20:49:15 | [diff] [blame] | 378 | log.bound())); |
| 379 | session->InitializeWithSocket(connection.release(), false, OK); |
| 380 | |
| 381 | scoped_refptr<SpdyStream> stream; |
| 382 | ASSERT_EQ( |
| 383 | OK, |
| 384 | session->CreateStream(url, LOWEST, &stream, log.bound(), |
| 385 | CompletionCallback())); |
| 386 | scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(8)); |
| 387 | memcpy(buf->data(), "\0hello!\xff", 8); |
| 388 | TestCompletionCallback callback; |
| 389 | |
| 390 | scoped_ptr<TestSpdyStreamDelegate> delegate( |
| 391 | new TestSpdyStreamDelegate(stream.get(), buf.get(), callback.callback())); |
| 392 | stream->SetDelegate(delegate.get()); |
| 393 | |
| 394 | EXPECT_FALSE(stream->HasUrl()); |
| 395 | |
| 396 | linked_ptr<spdy::SpdyHeaderBlock> headers(new spdy::SpdyHeaderBlock); |
[email protected] | 0e861e9 | 2012-03-15 18:42:19 | [diff] [blame] | 397 | (*headers)[":method"] = "GET"; |
| 398 | (*headers)[":scheme"] = url.scheme(); |
| 399 | (*headers)[":host"] = url.host(); |
| 400 | (*headers)[":path"] = url.path(); |
| 401 | (*headers)[":version"] = "HTTP/1.1"; |
[email protected] | d245c34 | 2012-02-23 20:49:15 | [diff] [blame] | 402 | stream->set_spdy_headers(headers); |
| 403 | EXPECT_TRUE(stream->HasUrl()); |
| 404 | EXPECT_EQ(kStreamUrl, stream->GetUrl().spec()); |
| 405 | |
| 406 | EXPECT_EQ(ERR_IO_PENDING, stream->SendRequest(true)); |
| 407 | |
| 408 | const spdy::SpdyStreamId stream_id = stream->stream_id(); |
| 409 | |
| 410 | EXPECT_EQ(OK, callback.WaitForResult()); |
| 411 | |
| 412 | EXPECT_TRUE(delegate->send_headers_completed()); |
| 413 | EXPECT_EQ("200", (*delegate->response())["status"]); |
| 414 | EXPECT_EQ("HTTP/1.1", (*delegate->response())["version"]); |
| 415 | EXPECT_EQ(std::string("\0hello!\xff", 8), delegate->received_data()); |
| 416 | EXPECT_EQ(8, delegate->data_sent()); |
| 417 | EXPECT_TRUE(delegate->closed()); |
| 418 | |
| 419 | // Check that the NetLog was filled reasonably. |
| 420 | net::CapturingNetLog::EntryList entries; |
| 421 | log.GetEntries(&entries); |
| 422 | EXPECT_LT(0u, entries.size()); |
| 423 | |
| 424 | // Check that we logged SPDY_STREAM_ERROR correctly. |
| 425 | int pos = net::ExpectLogContainsSomewhere( |
| 426 | entries, 0, |
| 427 | net::NetLog::TYPE_SPDY_STREAM_ERROR, |
| 428 | net::NetLog::PHASE_NONE); |
| 429 | |
| 430 | CapturingNetLog::Entry entry = entries[pos]; |
| 431 | NetLogSpdyStreamErrorParameter* request_params = |
| 432 | static_cast<NetLogSpdyStreamErrorParameter*>( |
| 433 | entry.extra_parameters.get()); |
| 434 | EXPECT_EQ(stream_id, request_params->stream_id()); |
| 435 | } |
[email protected] | a7a265ef | 2010-12-08 18:05:57 | [diff] [blame] | 436 | |
[email protected] | 4f38642 | 2010-07-20 04:19:49 | [diff] [blame] | 437 | } // namespace net |