blob: 643cfd83c78ae0f61f8f72f0e1cf9ab75f1c0a5d [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]34a4dea2013-03-13 00:42:305#include "base/basictypes.h"
[email protected]3b63f8f42011-03-28 01:54:156#include "base/memory/ref_counted.h"
[email protected]34a4dea2013-03-13 00:42:307#include "base/memory/scoped_ptr.h"
[email protected]d069c11a2013-04-13 00:01:558#include "base/strings/string_piece.h"
[email protected]5a76b812011-12-21 20:52:009#include "net/base/completion_callback.h"
[email protected]d245c342012-02-23 20:49:1510#include "net/base/net_log_unittest.h"
[email protected]1bbabc82013-03-25 21:11:0211#include "net/base/request_priority.h"
[email protected]bb88e1d32013-05-03 23:11:0712#include "net/socket/next_proto.h"
[email protected]f54c85792012-03-08 19:06:4113#include "net/spdy/buffered_spdy_framer.h"
[email protected]9e1bdd32011-02-03 21:48:3414#include "net/spdy/spdy_http_utils.h"
[email protected]34a4dea2013-03-13 00:42:3015#include "net/spdy/spdy_protocol.h"
[email protected]4f386422010-07-20 04:19:4916#include "net/spdy/spdy_session.h"
[email protected]d069c11a2013-04-13 00:01:5517#include "net/spdy/spdy_stream.h"
[email protected]39d13d942012-07-19 16:48:2018#include "net/spdy/spdy_stream_test_util.h"
[email protected]e3861ca2013-03-02 01:00:4519#include "net/spdy/spdy_test_util_common.h"
[email protected]448d4ca52012-03-04 04:12:2320#include "net/spdy/spdy_test_util_spdy3.h"
[email protected]5e248dc2012-08-21 02:27:3221#include "net/spdy/spdy_websocket_test_util_spdy3.h"
[email protected]4f386422010-07-20 04:19:4922#include "testing/gtest/include/gtest/gtest.h"
23
[email protected]448d4ca52012-03-04 04:12:2324using namespace net::test_spdy3;
25
[email protected]4f386422010-07-20 04:19:4926// TODO(ukai): factor out common part with spdy_http_stream_unittest.cc
[email protected]b9ec6882011-07-01 07:40:2627//
28namespace net {
[email protected]4f386422010-07-20 04:19:4929
[email protected]34a4dea2013-03-13 00:42:3030namespace test {
31
[email protected]4f386422010-07-20 04:19:4932namespace {
33
[email protected]cbdd73162013-03-18 23:27:3334const char kStreamUrl[] = "http://www.google.com/";
35const char kPostBody[] = "\0hello!\xff";
36const size_t kPostBodyLength = arraysize(kPostBody);
[email protected]1c6b12a2013-03-21 00:59:1137const base::StringPiece kPostBodyStringPiece(kPostBody, kPostBodyLength);
[email protected]39d13d942012-07-19 16:48:2038
[email protected]448d4ca52012-03-04 04:12:2339class SpdyStreamSpdy3Test : public testing::Test {
[email protected]4f386422010-07-20 04:19:4940 protected:
[email protected]bb88e1d32013-05-03 23:11:0741 SpdyStreamSpdy3Test()
[email protected]a4a67772013-05-08 22:56:0742 : spdy_util_(kProtoSPDY3),
43 host_port_pair_("www.google.com", 80),
[email protected]bb88e1d32013-05-03 23:11:0744 session_deps_(kProtoSPDY3) {}
[email protected]4f386422010-07-20 04:19:4945
46 scoped_refptr<SpdySession> CreateSpdySession() {
[email protected]34a4dea2013-03-13 00:42:3047 HostPortProxyPair pair(host_port_pair_, ProxyServer::Direct());
[email protected]4f386422010-07-20 04:19:4948 scoped_refptr<SpdySession> session(
[email protected]102e27c2011-02-23 01:01:3149 session_->spdy_session_pool()->Get(pair, BoundNetLog()));
[email protected]4f386422010-07-20 04:19:4950 return session;
51 }
52
[email protected]34a4dea2013-03-13 00:42:3053 void InitializeSpdySession(const scoped_refptr<SpdySession>& session,
54 const HostPortPair& host_port_pair) {
55 scoped_refptr<TransportSocketParams> transport_params(
56 new TransportSocketParams(host_port_pair, LOWEST, false, false,
57 OnHostResolutionCallback()));
58
59 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
60 EXPECT_EQ(OK, connection->Init(host_port_pair.ToString(), transport_params,
61 LOWEST, CompletionCallback(),
62 session_->GetTransportSocketPool(
63 HttpNetworkSession::NORMAL_SOCKET_POOL),
64 BoundNetLog()));
65 session->InitializeWithSocket(connection.release(), false, OK);
66 }
67
[email protected]4f386422010-07-20 04:19:4968 virtual void TearDown() {
[email protected]b4c62eb2012-11-14 18:36:5169 MessageLoop::current()->RunUntilIdle();
[email protected]4f386422010-07-20 04:19:4970 }
71
[email protected]a4a67772013-05-08 22:56:0772 SpdyTestUtil spdy_util_;
[email protected]34a4dea2013-03-13 00:42:3073 HostPortPair host_port_pair_;
74 SpdySessionDependencies session_deps_;
[email protected]4f386422010-07-20 04:19:4975 scoped_refptr<HttpNetworkSession> session_;
76};
77
[email protected]448d4ca52012-03-04 04:12:2378TEST_F(SpdyStreamSpdy3Test, SendDataAfterOpen) {
[email protected]cbdd73162013-03-18 23:27:3379 GURL url(kStreamUrl);
[email protected]34a4dea2013-03-13 00:42:3080 session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
[email protected]4f386422010-07-20 04:19:4981
[email protected]cbdd73162013-03-18 23:27:3382 scoped_ptr<SpdyFrame> req(
83 ConstructSpdyPost(kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
84 scoped_ptr<SpdyFrame> msg(
85 ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
[email protected]4f386422010-07-20 04:19:4986 MockWrite writes[] = {
87 CreateMockWrite(*req),
88 CreateMockWrite(*msg),
89 };
90 writes[0].sequence_number = 0;
91 writes[1].sequence_number = 2;
92
[email protected]ff98d7f02012-03-22 21:44:1993 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]cbdd73162013-03-18 23:27:3394 scoped_ptr<SpdyFrame> echo(
95 ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
[email protected]4f386422010-07-20 04:19:4996 MockRead reads[] = {
97 CreateMockRead(*resp),
98 CreateMockRead(*echo),
[email protected]8ddf8322012-02-23 18:08:0699 MockRead(ASYNC, 0, 0), // EOF
[email protected]4f386422010-07-20 04:19:49100 };
101 reads[0].sequence_number = 1;
102 reads[1].sequence_number = 3;
103 reads[2].sequence_number = 4;
104
[email protected]dd54bd82012-07-19 23:44:57105 OrderedSocketData data(reads, arraysize(reads),
106 writes, arraysize(writes));
[email protected]d973e99a2012-02-17 21:02:36107 MockConnect connect_data(SYNCHRONOUS, OK);
[email protected]dd54bd82012-07-19 23:44:57108 data.set_connect_data(connect_data);
[email protected]4f386422010-07-20 04:19:49109
[email protected]34a4dea2013-03-13 00:42:30110 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]4f386422010-07-20 04:19:49111
112 scoped_refptr<SpdySession> session(CreateSpdySession());
[email protected]4f386422010-07-20 04:19:49113
[email protected]34a4dea2013-03-13 00:42:30114 InitializeSpdySession(session, host_port_pair_);
[email protected]e3861ca2013-03-02 01:00:45115
116 scoped_refptr<SpdyStream> stream =
117 CreateStreamSynchronously(session, url, LOWEST, BoundNetLog());
118 ASSERT_TRUE(stream.get() != NULL);
[email protected]4f386422010-07-20 04:19:49119
[email protected]34a4dea2013-03-13 00:42:30120 StreamDelegateSendImmediate delegate(
[email protected]1c6b12a2013-03-21 00:59:11121 stream.get(), scoped_ptr<SpdyHeaderBlock>(), kPostBodyStringPiece);
[email protected]34a4dea2013-03-13 00:42:30122 stream->SetDelegate(&delegate);
[email protected]4f386422010-07-20 04:19:49123
[email protected]a7a265ef2010-12-08 18:05:57124 EXPECT_FALSE(stream->HasUrl());
125
[email protected]cbdd73162013-03-18 23:27:33126 stream->set_spdy_headers(
[email protected]a4a67772013-05-08 22:56:07127 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
[email protected]a7a265ef2010-12-08 18:05:57128 EXPECT_TRUE(stream->HasUrl());
129 EXPECT_EQ(kStreamUrl, stream->GetUrl().spec());
[email protected]4f386422010-07-20 04:19:49130
[email protected]a5c493b92010-08-06 23:04:29131 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequest(true));
[email protected]4f386422010-07-20 04:19:49132
[email protected]34a4dea2013-03-13 00:42:30133 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
[email protected]4f386422010-07-20 04:19:49134
[email protected]34a4dea2013-03-13 00:42:30135 EXPECT_TRUE(delegate.send_headers_completed());
136 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
137 EXPECT_EQ("HTTP/1.1", delegate.GetResponseHeaderValue(":version"));
[email protected]09a8d9172013-04-17 19:23:49138 EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
139 delegate.TakeReceivedData());
[email protected]cbdd73162013-03-18 23:27:33140 EXPECT_EQ(static_cast<int>(kPostBodyLength), delegate.data_sent());
[email protected]4f386422010-07-20 04:19:49141}
142
[email protected]0837bc62012-08-03 07:31:26143TEST_F(SpdyStreamSpdy3Test, SendHeaderAndDataAfterOpen) {
[email protected]34a4dea2013-03-13 00:42:30144 session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
[email protected]0837bc62012-08-03 07:31:26145
[email protected]5e248dc2012-08-21 02:27:32146 scoped_ptr<SpdyFrame> expected_request(ConstructSpdyWebSocketSynStream(
[email protected]0837bc62012-08-03 07:31:26147 1,
148 "/chat",
149 "server.example.com",
150 "http://example.com"));
151 scoped_ptr<SpdyFrame> expected_headers(ConstructSpdyWebSocketHeadersFrame(
152 1, "6", true));
[email protected]cbdd73162013-03-18 23:27:33153 scoped_ptr<SpdyFrame> expected_message(
154 ConstructSpdyBodyFrame(1, "hello!", 6, false));
[email protected]0837bc62012-08-03 07:31:26155 MockWrite writes[] = {
156 CreateMockWrite(*expected_request),
157 CreateMockWrite(*expected_headers),
158 CreateMockWrite(*expected_message)
159 };
160 writes[0].sequence_number = 0;
161 writes[1].sequence_number = 2;
162 writes[1].sequence_number = 3;
163
164 scoped_ptr<SpdyFrame> response(
165 ConstructSpdyWebSocketSynReply(1));
166 MockRead reads[] = {
167 CreateMockRead(*response),
168 MockRead(ASYNC, 0, 0), // EOF
169 };
170 reads[0].sequence_number = 1;
171 reads[1].sequence_number = 4;
172
173 OrderedSocketData data(reads, arraysize(reads),
174 writes, arraysize(writes));
175 MockConnect connect_data(SYNCHRONOUS, OK);
176 data.set_connect_data(connect_data);
177
[email protected]34a4dea2013-03-13 00:42:30178 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]0837bc62012-08-03 07:31:26179
180 scoped_refptr<SpdySession> session(CreateSpdySession());
[email protected]cbdd73162013-03-18 23:27:33181 GURL url("ws://server.example.com/chat");
[email protected]0837bc62012-08-03 07:31:26182
183 HostPortPair host_port_pair("server.example.com", 80);
[email protected]34a4dea2013-03-13 00:42:30184 InitializeSpdySession(session, host_port_pair);
[email protected]0837bc62012-08-03 07:31:26185
[email protected]e3861ca2013-03-02 01:00:45186 scoped_refptr<SpdyStream> stream =
187 CreateStreamSynchronously(session, url, HIGHEST, BoundNetLog());
188 ASSERT_TRUE(stream.get() != NULL);
[email protected]0837bc62012-08-03 07:31:26189 TestCompletionCallback callback;
190 scoped_ptr<SpdyHeaderBlock> message_headers(new SpdyHeaderBlock);
191 (*message_headers)[":opcode"] = "1";
192 (*message_headers)[":length"] = "6";
193 (*message_headers)[":fin"] = "1";
194
[email protected]34a4dea2013-03-13 00:42:30195 StreamDelegateSendImmediate delegate(
[email protected]1c6b12a2013-03-21 00:59:11196 stream.get(), message_headers.Pass(), base::StringPiece("hello!", 6));
[email protected]34a4dea2013-03-13 00:42:30197 stream->SetDelegate(&delegate);
[email protected]0837bc62012-08-03 07:31:26198
199 EXPECT_FALSE(stream->HasUrl());
200
201 scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock);
202 (*headers)[":path"] = url.path();
203 (*headers)[":host"] = url.host();
204 (*headers)[":version"] = "WebSocket/13";
205 (*headers)[":scheme"] = url.scheme();
206 (*headers)[":origin"] = "http://example.com";
207 stream->set_spdy_headers(headers.Pass());
208 EXPECT_TRUE(stream->HasUrl());
209
210 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequest(true));
211
[email protected]34a4dea2013-03-13 00:42:30212 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
[email protected]0837bc62012-08-03 07:31:26213
[email protected]34a4dea2013-03-13 00:42:30214 EXPECT_TRUE(delegate.send_headers_completed());
215 EXPECT_EQ("101", delegate.GetResponseHeaderValue(":status"));
216 EXPECT_EQ(1, delegate.headers_sent());
[email protected]09a8d9172013-04-17 19:23:49217 EXPECT_EQ(std::string(), delegate.TakeReceivedData());
[email protected]34a4dea2013-03-13 00:42:30218 EXPECT_EQ(6, delegate.data_sent());
[email protected]0837bc62012-08-03 07:31:26219}
220
[email protected]448d4ca52012-03-04 04:12:23221TEST_F(SpdyStreamSpdy3Test, PushedStream) {
[email protected]34a4dea2013-03-13 00:42:30222 session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
[email protected]a7a265ef2010-12-08 18:05:57223 scoped_refptr<SpdySession> spdy_session(CreateSpdySession());
[email protected]0e861e92012-03-15 18:42:19224
225 MockRead reads[] = {
226 MockRead(ASYNC, 0, 0), // EOF
227 };
228
[email protected]dd54bd82012-07-19 23:44:57229 OrderedSocketData data(reads, arraysize(reads), NULL, 0);
[email protected]0e861e92012-03-15 18:42:19230 MockConnect connect_data(SYNCHRONOUS, OK);
[email protected]dd54bd82012-07-19 23:44:57231 data.set_connect_data(connect_data);
[email protected]0e861e92012-03-15 18:42:19232
[email protected]34a4dea2013-03-13 00:42:30233 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]0e861e92012-03-15 18:42:19234
[email protected]34a4dea2013-03-13 00:42:30235 InitializeSpdySession(spdy_session, host_port_pair_);
[email protected]a7a265ef2010-12-08 18:05:57236 BoundNetLog net_log;
237
238 // Conjure up a stream.
[email protected]1bbabc82013-03-25 21:11:02239 scoped_refptr<SpdyStream> stream =
240 new SpdyStream(spdy_session,
241 std::string(),
242 DEFAULT_PRIORITY,
243 kSpdyStreamInitialWindowSize,
244 kSpdyStreamInitialWindowSize,
245 true,
246 net_log);
[email protected]c92f4b4542012-07-26 23:53:21247 stream->set_stream_id(2);
[email protected]a7a265ef2010-12-08 18:05:57248 EXPECT_FALSE(stream->response_received());
249 EXPECT_FALSE(stream->HasUrl());
250
251 // Set a couple of headers.
[email protected]ff98d7f02012-03-22 21:44:19252 SpdyHeaderBlock response;
[email protected]0e861e92012-03-15 18:42:19253 GURL url(kStreamUrl);
254 response[":host"] = url.host();
255 response[":scheme"] = url.scheme();
256 response[":path"] = url.path();
[email protected]a7a265ef2010-12-08 18:05:57257 stream->OnResponseReceived(response);
258
259 // Send some basic headers.
[email protected]ff98d7f02012-03-22 21:44:19260 SpdyHeaderBlock headers;
[email protected]d42dedd02012-04-03 19:42:06261 response[":status"] = "200";
262 response[":version"] = "OK";
[email protected]a7a265ef2010-12-08 18:05:57263 stream->OnHeaders(headers);
264
265 stream->set_response_received();
266 EXPECT_TRUE(stream->response_received());
267 EXPECT_TRUE(stream->HasUrl());
268 EXPECT_EQ(kStreamUrl, stream->GetUrl().spec());
269}
270
[email protected]448d4ca52012-03-04 04:12:23271TEST_F(SpdyStreamSpdy3Test, StreamError) {
[email protected]cbdd73162013-03-18 23:27:33272 GURL url(kStreamUrl);
273
[email protected]34a4dea2013-03-13 00:42:30274 session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
[email protected]d245c342012-02-23 20:49:15275
[email protected]cbdd73162013-03-18 23:27:33276 scoped_ptr<SpdyFrame> req(
277 ConstructSpdyPost(kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
278 scoped_ptr<SpdyFrame> msg(
279 ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
[email protected]d245c342012-02-23 20:49:15280 MockWrite writes[] = {
281 CreateMockWrite(*req),
282 CreateMockWrite(*msg),
283 };
284 writes[0].sequence_number = 0;
285 writes[1].sequence_number = 2;
286
[email protected]ff98d7f02012-03-22 21:44:19287 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]cbdd73162013-03-18 23:27:33288 scoped_ptr<SpdyFrame> echo(
289 ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
[email protected]d245c342012-02-23 20:49:15290 MockRead reads[] = {
291 CreateMockRead(*resp),
292 CreateMockRead(*echo),
293 MockRead(ASYNC, 0, 0), // EOF
294 };
295 reads[0].sequence_number = 1;
296 reads[1].sequence_number = 3;
297 reads[2].sequence_number = 4;
298
[email protected]333bdf62012-06-08 22:57:29299 CapturingBoundNetLog log;
[email protected]d245c342012-02-23 20:49:15300
[email protected]dd54bd82012-07-19 23:44:57301 OrderedSocketData data(reads, arraysize(reads),
302 writes, arraysize(writes));
[email protected]d245c342012-02-23 20:49:15303 MockConnect connect_data(SYNCHRONOUS, OK);
[email protected]dd54bd82012-07-19 23:44:57304 data.set_connect_data(connect_data);
[email protected]d245c342012-02-23 20:49:15305
[email protected]34a4dea2013-03-13 00:42:30306 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]d245c342012-02-23 20:49:15307
308 scoped_refptr<SpdySession> session(CreateSpdySession());
[email protected]d245c342012-02-23 20:49:15309
[email protected]34a4dea2013-03-13 00:42:30310 InitializeSpdySession(session, host_port_pair_);
[email protected]d245c342012-02-23 20:49:15311
[email protected]e3861ca2013-03-02 01:00:45312 scoped_refptr<SpdyStream> stream =
313 CreateStreamSynchronously(session, url, LOWEST, log.bound());
314 ASSERT_TRUE(stream.get() != NULL);
[email protected]d245c342012-02-23 20:49:15315
[email protected]34a4dea2013-03-13 00:42:30316 StreamDelegateSendImmediate delegate(
[email protected]1c6b12a2013-03-21 00:59:11317 stream.get(), scoped_ptr<SpdyHeaderBlock>(), kPostBodyStringPiece);
[email protected]34a4dea2013-03-13 00:42:30318 stream->SetDelegate(&delegate);
[email protected]d245c342012-02-23 20:49:15319
320 EXPECT_FALSE(stream->HasUrl());
321
[email protected]cbdd73162013-03-18 23:27:33322 stream->set_spdy_headers(
[email protected]a4a67772013-05-08 22:56:07323 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
[email protected]d245c342012-02-23 20:49:15324 EXPECT_TRUE(stream->HasUrl());
325 EXPECT_EQ(kStreamUrl, stream->GetUrl().spec());
326
327 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequest(true));
328
[email protected]34a4dea2013-03-13 00:42:30329 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
[email protected]218f4b62012-07-20 20:12:41330
[email protected]c92f4b4542012-07-26 23:53:21331 const SpdyStreamId stream_id = stream->stream_id();
332
[email protected]34a4dea2013-03-13 00:42:30333 EXPECT_TRUE(delegate.send_headers_completed());
334 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
335 EXPECT_EQ("HTTP/1.1", delegate.GetResponseHeaderValue(":version"));
[email protected]09a8d9172013-04-17 19:23:49336 EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
337 delegate.TakeReceivedData());
[email protected]cbdd73162013-03-18 23:27:33338 EXPECT_EQ(static_cast<int>(kPostBodyLength), delegate.data_sent());
[email protected]d245c342012-02-23 20:49:15339
340 // Check that the NetLog was filled reasonably.
[email protected]f3da152d2012-06-02 01:00:57341 net::CapturingNetLog::CapturedEntryList entries;
[email protected]d245c342012-02-23 20:49:15342 log.GetEntries(&entries);
343 EXPECT_LT(0u, entries.size());
344
345 // Check that we logged SPDY_STREAM_ERROR correctly.
346 int pos = net::ExpectLogContainsSomewhere(
347 entries, 0,
348 net::NetLog::TYPE_SPDY_STREAM_ERROR,
349 net::NetLog::PHASE_NONE);
350
[email protected]f3da152d2012-06-02 01:00:57351 int stream_id2;
352 ASSERT_TRUE(entries[pos].GetIntegerValue("stream_id", &stream_id2));
353 EXPECT_EQ(static_cast<int>(stream_id), stream_id2);
[email protected]d245c342012-02-23 20:49:15354}
[email protected]a7a265ef2010-12-08 18:05:57355
[email protected]1e5ebd82013-02-20 20:07:24356// Call IncreaseSendWindowSize on a stream with a large enough delta
357// to overflow an int32. The SpdyStream should handle that case
358// gracefully.
359TEST_F(SpdyStreamSpdy3Test, IncreaseSendWindowSizeOverflow) {
[email protected]34a4dea2013-03-13 00:42:30360 session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
[email protected]1e5ebd82013-02-20 20:07:24361
362 MockRead reads[] = {
363 MockRead(ASYNC, 0, 1), // EOF
364 };
365
366 // Triggered by the overflowing call to IncreaseSendWindowSize
367 // below.
368 scoped_ptr<SpdyFrame> rst(
369 ConstructSpdyRstStream(0, RST_STREAM_FLOW_CONTROL_ERROR));
370 MockWrite writes[] = {
371 CreateMockWrite(*rst),
372 };
373 writes[0].sequence_number = 0;
374
375 CapturingBoundNetLog log;
376
377 OrderedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
378 MockConnect connect_data(SYNCHRONOUS, OK);
379 data.set_connect_data(connect_data);
380
[email protected]34a4dea2013-03-13 00:42:30381 session_deps_.socket_factory->AddSocketDataProvider(&data);
[email protected]1e5ebd82013-02-20 20:07:24382
383 scoped_refptr<SpdySession> session(CreateSpdySession());
[email protected]1e5ebd82013-02-20 20:07:24384 GURL url(kStreamUrl);
385
[email protected]34a4dea2013-03-13 00:42:30386 InitializeSpdySession(session, host_port_pair_);
[email protected]1e5ebd82013-02-20 20:07:24387
[email protected]e3861ca2013-03-02 01:00:45388 scoped_refptr<SpdyStream> stream =
389 CreateStreamSynchronously(session, url, LOWEST, log.bound());
390 ASSERT_TRUE(stream.get() != NULL);
[email protected]1e5ebd82013-02-20 20:07:24391
[email protected]1c6b12a2013-03-21 00:59:11392 StreamDelegateSendImmediate delegate(
393 stream.get(), scoped_ptr<SpdyHeaderBlock>(), kPostBodyStringPiece);
394 stream->SetDelegate(&delegate);
[email protected]1e5ebd82013-02-20 20:07:24395
396 EXPECT_FALSE(stream->HasUrl());
397 EXPECT_EQ(0u, stream->stream_id());
398 EXPECT_FALSE(stream->closed());
399
400 int32 old_send_window_size = stream->send_window_size();
401 ASSERT_GT(old_send_window_size, 0);
402 int32 delta_window_size = kint32max - old_send_window_size + 1;
403 stream->IncreaseSendWindowSize(delta_window_size);
404 EXPECT_EQ(old_send_window_size, stream->send_window_size());
405
[email protected]1c6b12a2013-03-21 00:59:11406 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
[email protected]1e5ebd82013-02-20 20:07:24407}
408
[email protected]1c6b12a2013-03-21 00:59:11409// Cause a send stall by reducing the flow control send window to
410// 0. The stream should resume when that window is then increased.
[email protected]cbdd73162013-03-18 23:27:33411TEST_F(SpdyStreamSpdy3Test, ResumeAfterSendWindowSizeIncrease) {
[email protected]34a4dea2013-03-13 00:42:30412 GURL url(kStreamUrl);
413
[email protected]34a4dea2013-03-13 00:42:30414 session_ =
415 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
416
[email protected]cbdd73162013-03-18 23:27:33417 scoped_ptr<SpdyFrame> req(
418 ConstructSpdyPost(kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
[email protected]34a4dea2013-03-13 00:42:30419 scoped_ptr<SpdyFrame> msg(
[email protected]cbdd73162013-03-18 23:27:33420 ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
[email protected]34a4dea2013-03-13 00:42:30421 MockWrite writes[] = {
422 CreateMockWrite(*req, 0),
423 CreateMockWrite(*msg, 2),
424 };
425
426 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
427 scoped_ptr<SpdyFrame> echo(
[email protected]cbdd73162013-03-18 23:27:33428 ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
[email protected]34a4dea2013-03-13 00:42:30429 MockRead reads[] = {
430 CreateMockRead(*resp, 1),
431 CreateMockRead(*echo, 3),
432 MockRead(ASYNC, 0, 0, 4), // EOF
433 };
434
435 DeterministicSocketData data(reads, arraysize(reads),
436 writes, arraysize(writes));
437 MockConnect connect_data(SYNCHRONOUS, OK);
438 data.set_connect_data(connect_data);
439
440 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
441
442 scoped_refptr<SpdySession> session(CreateSpdySession());
[email protected]34a4dea2013-03-13 00:42:30443
444 InitializeSpdySession(session, host_port_pair_);
445
446 scoped_refptr<SpdyStream> stream =
447 CreateStreamSynchronously(session, url, LOWEST, BoundNetLog());
448 ASSERT_TRUE(stream.get() != NULL);
[email protected]34a4dea2013-03-13 00:42:30449
[email protected]1c6b12a2013-03-21 00:59:11450 StreamDelegateWithBody delegate(stream.get(), kPostBodyStringPiece);
[email protected]34a4dea2013-03-13 00:42:30451 stream->SetDelegate(&delegate);
452
453 EXPECT_FALSE(stream->HasUrl());
454
[email protected]cbdd73162013-03-18 23:27:33455 stream->set_spdy_headers(
[email protected]a4a67772013-05-08 22:56:07456 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
[email protected]34a4dea2013-03-13 00:42:30457 EXPECT_TRUE(stream->HasUrl());
458 EXPECT_EQ(kStreamUrl, stream->GetUrl().spec());
459
460 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequest(true));
461
462 data.RunFor(2);
463
[email protected]1c6b12a2013-03-21 00:59:11464 EXPECT_FALSE(stream->send_stalled_by_flow_control());
[email protected]34a4dea2013-03-13 00:42:30465
466 // Reduce the send window size to 0 to stall.
467 while (stream->send_window_size() > 0) {
468 stream->DecreaseSendWindowSize(
469 std::min(kMaxSpdyFrameChunkSize, stream->send_window_size()));
470 }
471
[email protected]1c6b12a2013-03-21 00:59:11472 EXPECT_EQ(ERR_IO_PENDING, delegate.OnSendBody());
[email protected]34a4dea2013-03-13 00:42:30473
[email protected]1c6b12a2013-03-21 00:59:11474 EXPECT_TRUE(stream->send_stalled_by_flow_control());
[email protected]34a4dea2013-03-13 00:42:30475
[email protected]cbdd73162013-03-18 23:27:33476 stream->IncreaseSendWindowSize(kPostBodyLength);
[email protected]34a4dea2013-03-13 00:42:30477
[email protected]1c6b12a2013-03-21 00:59:11478 EXPECT_FALSE(stream->send_stalled_by_flow_control());
[email protected]34a4dea2013-03-13 00:42:30479
480 data.RunFor(3);
481
482 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
483
484 EXPECT_TRUE(delegate.send_headers_completed());
485 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
486 EXPECT_EQ("HTTP/1.1", delegate.GetResponseHeaderValue(":version"));
[email protected]09a8d9172013-04-17 19:23:49487 EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
488 delegate.TakeReceivedData());
[email protected]cbdd73162013-03-18 23:27:33489 EXPECT_EQ(static_cast<int>(kPostBodyLength), delegate.body_data_sent());
490}
491
[email protected]1c6b12a2013-03-21 00:59:11492// Cause a send stall by reducing the flow control send window to
493// 0. The stream should resume when that window is then adjusted
494// positively.
[email protected]cbdd73162013-03-18 23:27:33495TEST_F(SpdyStreamSpdy3Test, ResumeAfterSendWindowSizeAdjust) {
496 GURL url(kStreamUrl);
497
498 session_ =
499 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
500
501 scoped_ptr<SpdyFrame> req(
502 ConstructSpdyPost(kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
503 scoped_ptr<SpdyFrame> msg(
504 ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
505 MockWrite writes[] = {
506 CreateMockWrite(*req, 0),
507 CreateMockWrite(*msg, 2),
508 };
509
510 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
511 scoped_ptr<SpdyFrame> echo(
512 ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
513 MockRead reads[] = {
514 CreateMockRead(*resp, 1),
515 CreateMockRead(*echo, 3),
516 MockRead(ASYNC, 0, 0, 4), // EOF
517 };
518
519 DeterministicSocketData data(reads, arraysize(reads),
520 writes, arraysize(writes));
521 MockConnect connect_data(SYNCHRONOUS, OK);
522 data.set_connect_data(connect_data);
523
524 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
525
526 scoped_refptr<SpdySession> session(CreateSpdySession());
527
528 InitializeSpdySession(session, host_port_pair_);
529
530 scoped_refptr<SpdyStream> stream =
531 CreateStreamSynchronously(session, url, LOWEST, BoundNetLog());
532 ASSERT_TRUE(stream.get() != NULL);
[email protected]cbdd73162013-03-18 23:27:33533
[email protected]1c6b12a2013-03-21 00:59:11534 StreamDelegateWithBody delegate(stream.get(), kPostBodyStringPiece);
[email protected]cbdd73162013-03-18 23:27:33535 stream->SetDelegate(&delegate);
536
537 EXPECT_FALSE(stream->HasUrl());
538
539 stream->set_spdy_headers(
[email protected]a4a67772013-05-08 22:56:07540 spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
[email protected]cbdd73162013-03-18 23:27:33541 EXPECT_TRUE(stream->HasUrl());
542 EXPECT_EQ(kStreamUrl, stream->GetUrl().spec());
543
544 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequest(true));
545
546 data.RunFor(2);
547
[email protected]1c6b12a2013-03-21 00:59:11548 EXPECT_FALSE(stream->send_stalled_by_flow_control());
[email protected]cbdd73162013-03-18 23:27:33549
550 // Reduce the send window size to 0 to stall.
551 while (stream->send_window_size() > 0) {
552 stream->DecreaseSendWindowSize(
553 std::min(kMaxSpdyFrameChunkSize, stream->send_window_size()));
554 }
555
[email protected]1c6b12a2013-03-21 00:59:11556 EXPECT_EQ(ERR_IO_PENDING, delegate.OnSendBody());
[email protected]cbdd73162013-03-18 23:27:33557
[email protected]1c6b12a2013-03-21 00:59:11558 EXPECT_TRUE(stream->send_stalled_by_flow_control());
[email protected]cbdd73162013-03-18 23:27:33559
560 stream->AdjustSendWindowSize(-static_cast<int>(kPostBodyLength));
561
[email protected]1c6b12a2013-03-21 00:59:11562 EXPECT_TRUE(stream->send_stalled_by_flow_control());
[email protected]cbdd73162013-03-18 23:27:33563
564 stream->AdjustSendWindowSize(kPostBodyLength);
565
[email protected]1c6b12a2013-03-21 00:59:11566 EXPECT_TRUE(stream->send_stalled_by_flow_control());
[email protected]cbdd73162013-03-18 23:27:33567
568 stream->AdjustSendWindowSize(kPostBodyLength);
569
[email protected]1c6b12a2013-03-21 00:59:11570 EXPECT_FALSE(stream->send_stalled_by_flow_control());
[email protected]cbdd73162013-03-18 23:27:33571
572 data.RunFor(3);
573
574 EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
575
576 EXPECT_TRUE(delegate.send_headers_completed());
577 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
578 EXPECT_EQ("HTTP/1.1", delegate.GetResponseHeaderValue(":version"));
[email protected]09a8d9172013-04-17 19:23:49579 EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
580 delegate.TakeReceivedData());
[email protected]cbdd73162013-03-18 23:27:33581 EXPECT_EQ(static_cast<int>(kPostBodyLength), delegate.body_data_sent());
[email protected]34a4dea2013-03-13 00:42:30582}
583
584} // namespace
585
[email protected]39d13d942012-07-19 16:48:20586} // namespace test
587
[email protected]4f386422010-07-20 04:19:49588} // namespace net