blob: 5544630d3aa5eba8630ce483a63266d348bf1d85 [file] [log] [blame]
[email protected]a1595312012-01-22 03:25:041// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]5af3c572010-07-20 14:16:272// Use of this source code is governed by a BSD-style license that can be
[email protected]aea80602009-09-18 00:55:083// found in the LICENSE file.
4
[email protected]d8ef27b2010-08-06 17:34:395#include <string>
[email protected]a33cad2b62010-07-30 22:24:396#include <vector>
7
[email protected]49639fa2011-12-20 23:22:418#include "base/bind.h"
9#include "base/bind_helpers.h"
thestigd8df0332014-09-04 06:33:2910#include "base/files/file_util.h"
[email protected]ea1a3f62012-11-16 20:34:2311#include "base/files/scoped_temp_dir.h"
[email protected]69e6b4a2012-10-18 08:03:0112#include "base/memory/scoped_vector.h"
[email protected]fc9d88472013-08-14 02:31:1713#include "base/run_loop.h"
[email protected]b771bb72013-06-24 09:55:4114#include "base/stl_util.h"
[email protected]251029e2014-03-19 06:04:4015#include "base/strings/string_piece.h"
[email protected]999dd8c2013-11-12 06:45:5416#include "base/test/test_file_util.h"
[email protected]018aabc2010-10-29 16:16:5917#include "net/base/auth.h"
mmenkecbc2b712014-10-09 20:29:0718#include "net/base/chunked_upload_data_stream.h"
19#include "net/base/elements_upload_data_stream.h"
[email protected]262eec82013-03-19 21:01:3620#include "net/base/request_priority.h"
bncce36dca22015-04-21 22:11:2321#include "net/base/test_data_directory.h"
[email protected]b2d26cfd2012-12-11 10:36:0622#include "net/base/upload_bytes_element_reader.h"
[email protected]b2d26cfd2012-12-11 10:36:0623#include "net/base/upload_file_element_reader.h"
[email protected]87bfa3f2010-09-30 14:54:5624#include "net/http/http_network_session_peer.h"
[email protected]513963e2013-06-15 01:53:0425#include "net/http/http_network_transaction.h"
26#include "net/http/http_server_properties.h"
[email protected]c41737d2014-05-14 07:47:1927#include "net/http/http_transaction_test_util.h"
mmenke16a7cbdd2015-04-24 23:00:5628#include "net/log/test_net_log.h"
mmenke43758e62015-05-04 21:09:4629#include "net/log/test_net_log_entry.h"
30#include "net/log/test_net_log_util.h"
[email protected]2d6728692011-03-12 01:39:5531#include "net/socket/client_socket_pool_base.h"
[email protected]bb88e1d32013-05-03 23:11:0732#include "net/socket/next_proto.h"
[email protected]f54c85792012-03-08 19:06:4133#include "net/spdy/buffered_spdy_framer.h"
[email protected]9be804c82010-06-24 17:59:4634#include "net/spdy/spdy_http_stream.h"
[email protected]9e1bdd32011-02-03 21:48:3435#include "net/spdy/spdy_http_utils.h"
[email protected]bdebd1b2010-08-09 20:18:0836#include "net/spdy/spdy_session.h"
[email protected]19ec8a72010-08-23 03:38:2337#include "net/spdy/spdy_session_pool.h"
[email protected]86aa87b2013-02-15 01:10:0338#include "net/spdy/spdy_test_util_common.h"
[email protected]a4bfdf72013-02-22 04:06:1639#include "net/spdy/spdy_test_utils.h"
[email protected]514aeaf2014-05-23 10:31:5140#include "net/ssl/ssl_connection_status_flags.h"
bncce36dca22015-04-21 22:11:2341#include "net/test/cert_test_util.h"
[email protected]d2db0292011-01-26 20:23:4442#include "net/url_request/url_request_test_util.h"
[email protected]251029e2014-03-19 06:04:4043#include "testing/gmock/include/gmock/gmock.h"
[email protected]aea80602009-09-18 00:55:0844#include "testing/platform_test.h"
45
46//-----------------------------------------------------------------------------
47
[email protected]d1eda932009-11-04 01:03:1048namespace net {
[email protected]dae22c52010-07-30 02:16:3549
[email protected]cbdd73162013-03-18 23:27:3350namespace {
[email protected]251029e2014-03-19 06:04:4051
52using testing::Each;
53using testing::Eq;
54
[email protected]513963e2013-06-15 01:53:0455enum SpdyNetworkTransactionTestSSLType {
rchebf12982015-04-10 01:15:0056 // Request an https:// URL and use NPN (or ALPN) to negotiate SPDY during
57 // the TLS handshake.
58 HTTPS_SPDY_VIA_NPN,
59 // Request and http:// URL to a server that supports SPDY via Alternative
60 // Service on port 443.
61 // See: https//tools.ietf.org/id/draft-ietf-httpbis-alt-svc-06.html
62 HTTP_SPDY_VIA_ALT_SVC,
[email protected]9e9e842e2010-07-23 23:09:1563};
[email protected]ca6459f862012-04-11 19:43:2064
[email protected]513963e2013-06-15 01:53:0465struct SpdyNetworkTransactionTestParams {
66 SpdyNetworkTransactionTestParams()
rchebf12982015-04-10 01:15:0067 : protocol(kProtoSPDY31), ssl_type(HTTPS_SPDY_VIA_NPN) {}
[email protected]513963e2013-06-15 01:53:0468
rchebf12982015-04-10 01:15:0069 SpdyNetworkTransactionTestParams(NextProto protocol,
70 SpdyNetworkTransactionTestSSLType ssl_type)
71 : protocol(protocol), ssl_type(ssl_type) {}
72
73 friend std::ostream& operator<<(std::ostream& os,
74 const SpdyNetworkTransactionTestParams& p) {
75 std::string type_str;
76 switch (p.ssl_type) {
77 case HTTP_SPDY_VIA_ALT_SVC:
78 type_str = "HTTP_SPDY_VIA_ALT_SVC";
79 break;
80 case HTTPS_SPDY_VIA_NPN:
81 type_str = "HTTPS_SPDY_VIA_NPN";
82 break;
83 }
84 os << "{ protocol: " << SSLClientSocket::NextProtoToString(p.protocol)
85 << ", ssl_type: " << type_str << " }";
86 return os;
87 }
[email protected]513963e2013-06-15 01:53:0488
89 NextProto protocol;
90 SpdyNetworkTransactionTestSSLType ssl_type;
91};
92
rchebf12982015-04-10 01:15:0093void UpdateSpdySessionDependencies(SpdyNetworkTransactionTestParams test_params,
94 SpdySessionDependencies* session_deps) {
95 session_deps->use_alternate_protocols = true;
96 session_deps->next_protos = SpdyNextProtos();
97 if (test_params.ssl_type == HTTP_SPDY_VIA_ALT_SVC) {
98 session_deps->http_server_properties.SetAlternativeService(
bncce36dca22015-04-21 22:11:2399 HostPortPair("www.example.org", 80),
rchebf12982015-04-10 01:15:00100 AlternativeService(AlternateProtocolFromNextProto(test_params.protocol),
bncce36dca22015-04-21 22:11:23101 "www.example.org", 443),
rchebf12982015-04-10 01:15:00102 1);
[email protected]d7599122014-05-24 03:37:23103 }
104}
105
[email protected]513963e2013-06-15 01:53:04106SpdySessionDependencies* CreateSpdySessionDependencies(
107 SpdyNetworkTransactionTestParams test_params) {
[email protected]d7599122014-05-24 03:37:23108 SpdySessionDependencies* session_deps =
109 new SpdySessionDependencies(test_params.protocol);
110 UpdateSpdySessionDependencies(test_params, session_deps);
111 return session_deps;
[email protected]513963e2013-06-15 01:53:04112}
113
114SpdySessionDependencies* CreateSpdySessionDependencies(
115 SpdyNetworkTransactionTestParams test_params,
[email protected]bb88e1d32013-05-03 23:11:07116 ProxyService* proxy_service) {
[email protected]d7599122014-05-24 03:37:23117 SpdySessionDependencies* session_deps =
118 new SpdySessionDependencies(test_params.protocol, proxy_service);
119 UpdateSpdySessionDependencies(test_params, session_deps);
120 return session_deps;
[email protected]bb88e1d32013-05-03 23:11:07121}
122
[email protected]513963e2013-06-15 01:53:04123} // namespace
124
125class SpdyNetworkTransactionTest
126 : public ::testing::TestWithParam<SpdyNetworkTransactionTestParams> {
[email protected]34437af82009-11-06 02:28:49127 protected:
[email protected]513963e2013-06-15 01:53:04128 SpdyNetworkTransactionTest() : spdy_util_(GetParam().protocol) {
rchebf12982015-04-10 01:15:00129 spdy_util_.set_default_url(GURL(GetDefaultUrl()));
[email protected]9ec54f82013-05-10 02:53:05130 }
[email protected]2d6728692011-03-12 01:39:55131
[email protected]fc9d88472013-08-14 02:31:17132 virtual ~SpdyNetworkTransactionTest() {
mmenkecbc2b712014-10-09 20:29:07133 // UploadDataStream may post a deletion tasks back to the message loop on
[email protected]fc9d88472013-08-14 02:31:17134 // destruction.
135 upload_data_stream_.reset();
136 base::RunLoop().RunUntilIdle();
137 }
138
dcheng67be2b1f2014-10-27 21:47:29139 void SetUp() override {
bncce36dca22015-04-21 22:11:23140 get_request_initialized_ = false;
141 post_request_initialized_ = false;
142 chunked_post_request_initialized_ = false;
[email protected]69e6b4a2012-10-18 08:03:01143 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
[email protected]aea80602009-09-18 00:55:08144 }
145
[email protected]72552f02009-10-28 15:25:01146 struct TransactionHelperResult {
[email protected]aea80602009-09-18 00:55:08147 int rv;
148 std::string status_line;
149 std::string response_data;
[email protected]8b070372009-11-16 22:01:25150 HttpResponseInfo response_info;
[email protected]aea80602009-09-18 00:55:08151 };
152
[email protected]3caf5542010-07-16 15:19:47153 // A helper class that handles all the initial npn/ssl setup.
154 class NormalSpdyTransactionHelper {
155 public:
156 NormalSpdyTransactionHelper(const HttpRequestInfo& request,
[email protected]262eec82013-03-19 21:01:36157 RequestPriority priority,
[email protected]9e9e842e2010-07-23 23:09:15158 const BoundNetLog& log,
[email protected]513963e2013-06-15 01:53:04159 SpdyNetworkTransactionTestParams test_params,
[email protected]61b4efc2012-04-27 18:12:50160 SpdySessionDependencies* session_deps)
[email protected]30c942b2010-07-21 16:59:59161 : request_(request),
[email protected]262eec82013-03-19 21:01:36162 priority_(priority),
rchebf12982015-04-10 01:15:00163 session_deps_(session_deps == NULL
164 ? CreateSpdySessionDependencies(test_params)
165 : session_deps),
166 session_(
167 SpdySessionDependencies::SpdyCreateSession(session_deps_.get())),
[email protected]9e9e842e2010-07-23 23:09:15168 log_(log),
[email protected]513963e2013-06-15 01:53:04169 test_params_(test_params),
rchebf12982015-04-10 01:15:00170 port_(443),
[email protected]1f418ee2010-10-16 19:46:56171 deterministic_(false),
rchebf12982015-04-10 01:15:00172 spdy_enabled_(true) {}
[email protected]61b4efc2012-04-27 18:12:50173
[email protected]19ec8a72010-08-23 03:38:23174 ~NormalSpdyTransactionHelper() {
175 // Any test which doesn't close the socket by sending it an EOF will
176 // have a valid session left open, which leaks the entire session pool.
177 // This is just fine - in fact, some of our tests intentionally do this
178 // so that we can check consistency of the SpdySessionPool as the test
179 // finishes. If we had put an EOF on the socket, the SpdySession would
180 // have closed and we wouldn't be able to check the consistency.
181
182 // Forcefully close existing sessions here.
183 session()->spdy_session_pool()->CloseAllSessions();
184 }
185
[email protected]3b7828432010-08-18 18:33:27186 void SetDeterministic() {
187 session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
188 session_deps_.get());
189 deterministic_ = true;
190 }
191
[email protected]1f418ee2010-10-16 19:46:56192 void SetSpdyDisabled() {
193 spdy_enabled_ = false;
rchebf12982015-04-10 01:15:00194 port_ = test_params_.ssl_type == HTTP_SPDY_VIA_ALT_SVC ? 80 : 443;
[email protected]1f418ee2010-10-16 19:46:56195 }
196
[email protected]3caf5542010-07-16 15:19:47197 void RunPreTestSetup() {
[email protected]b261d0e2010-08-02 19:13:24198 if (!session_deps_.get())
[email protected]513963e2013-06-15 01:53:04199 session_deps_.reset(CreateSpdySessionDependencies(test_params_));
[email protected]d7599122014-05-24 03:37:23200 if (!session_.get()) {
[email protected]b261d0e2010-08-02 19:13:24201 session_ = SpdySessionDependencies::SpdyCreateSession(
202 session_deps_.get());
[email protected]3caf5542010-07-16 15:19:47203 }
[email protected]aea80602009-09-18 00:55:08204
[email protected]3caf5542010-07-16 15:19:47205 // We're now ready to use SSL-npn SPDY.
[email protected]90499482013-06-01 00:39:50206 trans_.reset(new HttpNetworkTransaction(priority_, session_.get()));
[email protected]cb54b3b22010-06-03 16:28:55207 }
[email protected]aea80602009-09-18 00:55:08208
[email protected]3caf5542010-07-16 15:19:47209 // Start the transaction, read some data, finish.
210 void RunDefaultTest() {
[email protected]34b345f92013-02-22 03:27:26211 if (!StartDefaultTest())
212 return;
213 FinishDefaultTest();
214 }
215
216 bool StartDefaultTest() {
[email protected]514aeaf2014-05-23 10:31:51217 output_.rv = trans_->Start(&request_, callback_.callback(), log_);
[email protected]aea80602009-09-18 00:55:08218
[email protected]3caf5542010-07-16 15:19:47219 // We expect an IO Pending or some sort of error.
220 EXPECT_LT(output_.rv, 0);
[email protected]34b345f92013-02-22 03:27:26221 return output_.rv == ERR_IO_PENDING;
222 }
[email protected]aea80602009-09-18 00:55:08223
[email protected]34b345f92013-02-22 03:27:26224 void FinishDefaultTest() {
[email protected]514aeaf2014-05-23 10:31:51225 output_.rv = callback_.WaitForResult();
[email protected]3caf5542010-07-16 15:19:47226 if (output_.rv != OK) {
bnc301745a2015-03-10 03:22:16227 session_->spdy_session_pool()->CloseCurrentSessions(ERR_ABORTED);
[email protected]3caf5542010-07-16 15:19:47228 return;
229 }
[email protected]ff57bb82009-11-12 06:52:14230
[email protected]3caf5542010-07-16 15:19:47231 // Verify responses.
232 const HttpResponseInfo* response = trans_->GetResponseInfo();
233 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:50234 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]3caf5542010-07-16 15:19:47235 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]1f418ee2010-10-16 19:46:56236 EXPECT_EQ(spdy_enabled_, response->was_fetched_via_spdy);
[email protected]808957c2013-03-13 03:51:27237 if (HttpStreamFactory::spdy_enabled()) {
[email protected]88a332622013-07-30 07:13:32238 EXPECT_EQ(
239 HttpResponseInfo::ConnectionInfoFromNextProto(
240 test_params_.protocol),
241 response->connection_info);
[email protected]808957c2013-03-13 03:51:27242 } else {
243 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1,
244 response->connection_info);
245 }
rchebf12982015-04-10 01:15:00246 if (spdy_enabled_) {
[email protected]9e9e842e2010-07-23 23:09:15247 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]a33cad2b62010-07-30 22:24:39248 } else {
rchebf12982015-04-10 01:15:00249 // If SPDY is disabled, an HTTP request should not be diverted
250 // over an SSL session.
[email protected]1f418ee2010-10-16 19:46:56251 EXPECT_EQ(request_.url.SchemeIs("https"),
252 response->was_npn_negotiated);
253 }
[email protected]80a09a82012-11-16 17:40:06254 EXPECT_EQ("127.0.0.1", response->socket_address.host());
255 EXPECT_EQ(port_, response->socket_address.port());
[email protected]3caf5542010-07-16 15:19:47256 output_.status_line = response->headers->GetStatusLine();
257 output_.response_info = *response; // Make a copy so we can verify.
258 output_.rv = ReadTransaction(trans_.get(), &output_.response_data);
[email protected]3caf5542010-07-16 15:19:47259 }
260
bncfacdd852015-01-09 19:22:54261 void FinishDefaultTestWithoutVerification() {
262 output_.rv = callback_.WaitForResult();
263 if (output_.rv != OK)
bnc301745a2015-03-10 03:22:16264 session_->spdy_session_pool()->CloseCurrentSessions(ERR_ABORTED);
bncfacdd852015-01-09 19:22:54265 }
266
[email protected]3caf5542010-07-16 15:19:47267 // Most tests will want to call this function. In particular, the MockReads
268 // should end with an empty read, and that read needs to be processed to
269 // ensure proper deletion of the spdy_session_pool.
270 void VerifyDataConsumed() {
rch73e17422015-05-04 19:52:06271 for (const SocketDataProvider* provider : data_vector_) {
272 EXPECT_TRUE(provider->AllReadDataConsumed());
273 EXPECT_TRUE(provider->AllWriteDataConsumed());
[email protected]3caf5542010-07-16 15:19:47274 }
275 }
276
277 // Occasionally a test will expect to error out before certain reads are
278 // processed. In that case we want to explicitly ensure that the reads were
279 // not processed.
280 void VerifyDataNotConsumed() {
rch73e17422015-05-04 19:52:06281 for (const SocketDataProvider* provider : data_vector_) {
282 EXPECT_FALSE(provider->AllReadDataConsumed());
283 EXPECT_FALSE(provider->AllWriteDataConsumed());
[email protected]3caf5542010-07-16 15:19:47284 }
285 }
286
rch73e17422015-05-04 19:52:06287 void RunToCompletion(SocketDataProvider* data) {
[email protected]3caf5542010-07-16 15:19:47288 RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:58289 AddData(data);
[email protected]3caf5542010-07-16 15:19:47290 RunDefaultTest();
291 VerifyDataConsumed();
292 }
[email protected]e6b06862010-07-20 16:32:58293
[email protected]514aeaf2014-05-23 10:31:51294 void RunToCompletionWithSSLData(
rch73e17422015-05-04 19:52:06295 SocketDataProvider* data,
[email protected]514aeaf2014-05-23 10:31:51296 scoped_ptr<SSLSocketDataProvider> ssl_provider) {
297 RunPreTestSetup();
298 AddDataWithSSLSocketDataProvider(data, ssl_provider.Pass());
299 RunDefaultTest();
300 VerifyDataConsumed();
301 }
302
rch73e17422015-05-04 19:52:06303 void AddData(SocketDataProvider* data) {
[email protected]514aeaf2014-05-23 10:31:51304 scoped_ptr<SSLSocketDataProvider> ssl_provider(
305 new SSLSocketDataProvider(ASYNC, OK));
bncce36dca22015-04-21 22:11:23306 ssl_provider->cert =
307 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
[email protected]514aeaf2014-05-23 10:31:51308 AddDataWithSSLSocketDataProvider(data, ssl_provider.Pass());
309 }
310
311 void AddDataWithSSLSocketDataProvider(
rch73e17422015-05-04 19:52:06312 SocketDataProvider* data,
[email protected]514aeaf2014-05-23 10:31:51313 scoped_ptr<SSLSocketDataProvider> ssl_provider) {
[email protected]3b7828432010-08-18 18:33:27314 DCHECK(!deterministic_);
[email protected]3caf5542010-07-16 15:19:47315 data_vector_.push_back(data);
rchebf12982015-04-10 01:15:00316 if (ssl_provider->next_proto_status ==
317 SSLClientSocket::kNextProtoUnsupported) {
[email protected]513963e2013-06-15 01:53:04318 ssl_provider->SetNextProto(test_params_.protocol);
[email protected]514aeaf2014-05-23 10:31:51319 }
rchebf12982015-04-10 01:15:00320
321 session_deps_->socket_factory->AddSSLSocketDataProvider(
322 ssl_provider.get());
[email protected]514aeaf2014-05-23 10:31:51323 ssl_vector_.push_back(ssl_provider.release());
[email protected]d4f00222012-07-10 06:24:51324
[email protected]3b7828432010-08-18 18:33:27325 session_deps_->socket_factory->AddSocketDataProvider(data);
rchebf12982015-04-10 01:15:00326 if (test_params_.ssl_type == HTTP_SPDY_VIA_ALT_SVC) {
327 MockConnect hanging_connect(SYNCHRONOUS, ERR_IO_PENDING);
328 StaticSocketDataProvider* hanging_non_alt_svc_socket =
[email protected]513963e2013-06-15 01:53:04329 new StaticSocketDataProvider(NULL, 0, NULL, 0);
rchebf12982015-04-10 01:15:00330 hanging_non_alt_svc_socket->set_connect_data(hanging_connect);
[email protected]2d6728692011-03-12 01:39:55331 session_deps_->socket_factory->AddSocketDataProvider(
rchebf12982015-04-10 01:15:00332 hanging_non_alt_svc_socket);
333 alternate_vector_.push_back(hanging_non_alt_svc_socket);
[email protected]2d6728692011-03-12 01:39:55334 }
[email protected]3b7828432010-08-18 18:33:27335 }
336
337 void AddDeterministicData(DeterministicSocketData* data) {
338 DCHECK(deterministic_);
339 data_vector_.push_back(data);
[email protected]d4f00222012-07-10 06:24:51340 SSLSocketDataProvider* ssl_provider =
341 new SSLSocketDataProvider(ASYNC, OK);
rchebf12982015-04-10 01:15:00342 ssl_provider->SetNextProto(test_params_.protocol);
bncce36dca22015-04-21 22:11:23343 ssl_provider->cert =
344 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
[email protected]d4f00222012-07-10 06:24:51345 ssl_vector_.push_back(ssl_provider);
rchebf12982015-04-10 01:15:00346 session_deps_->deterministic_socket_factory->AddSSLSocketDataProvider(
347 ssl_provider);
348
[email protected]3b7828432010-08-18 18:33:27349 session_deps_->deterministic_socket_factory->AddSocketDataProvider(data);
rchebf12982015-04-10 01:15:00350 if (test_params_.ssl_type == HTTP_SPDY_VIA_ALT_SVC) {
351 MockConnect hanging_connect(SYNCHRONOUS, ERR_IO_PENDING);
352 DeterministicSocketData* hanging_non_alt_svc_socket =
[email protected]d4f00222012-07-10 06:24:51353 new DeterministicSocketData(NULL, 0, NULL, 0);
rchebf12982015-04-10 01:15:00354 hanging_non_alt_svc_socket->set_connect_data(hanging_connect);
[email protected]2d6728692011-03-12 01:39:55355 session_deps_->deterministic_socket_factory->AddSocketDataProvider(
rchebf12982015-04-10 01:15:00356 hanging_non_alt_svc_socket);
357 alternate_vector_.push_back(hanging_non_alt_svc_socket);
[email protected]2d6728692011-03-12 01:39:55358 }
[email protected]3caf5542010-07-16 15:19:47359 }
360
[email protected]a33cad2b62010-07-30 22:24:39361 void SetSession(const scoped_refptr<HttpNetworkSession>& session) {
[email protected]3caf5542010-07-16 15:19:47362 session_ = session;
363 }
364 HttpNetworkTransaction* trans() { return trans_.get(); }
365 void ResetTrans() { trans_.reset(); }
366 TransactionHelperResult& output() { return output_; }
[email protected]19ec8a72010-08-23 03:38:23367 const HttpRequestInfo& request() const { return request_; }
368 const scoped_refptr<HttpNetworkSession>& session() const {
369 return session_;
370 }
[email protected]b261d0e2010-08-02 19:13:24371 scoped_ptr<SpdySessionDependencies>& session_deps() {
372 return session_deps_;
373 }
[email protected]19ec8a72010-08-23 03:38:23374 int port() const { return port_; }
[email protected]513963e2013-06-15 01:53:04375 SpdyNetworkTransactionTestParams test_params() const {
376 return test_params_;
[email protected]448d4ca52012-03-04 04:12:23377 }
[email protected]3caf5542010-07-16 15:19:47378
379 private:
rch73e17422015-05-04 19:52:06380 typedef std::vector<SocketDataProvider*> DataVector;
[email protected]d4f00222012-07-10 06:24:51381 typedef ScopedVector<SSLSocketDataProvider> SSLVector;
rch73e17422015-05-04 19:52:06382 typedef ScopedVector<SocketDataProvider> AlternateVector;
[email protected]d4f00222012-07-10 06:24:51383 typedef ScopedVector<DeterministicSocketData> AlternateDeterministicVector;
[email protected]3caf5542010-07-16 15:19:47384 HttpRequestInfo request_;
[email protected]262eec82013-03-19 21:01:36385 RequestPriority priority_;
[email protected]b261d0e2010-08-02 19:13:24386 scoped_ptr<SpdySessionDependencies> session_deps_;
[email protected]3caf5542010-07-16 15:19:47387 scoped_refptr<HttpNetworkSession> session_;
388 TransactionHelperResult output_;
rch73e17422015-05-04 19:52:06389 scoped_ptr<SocketDataProvider> first_transaction_;
[email protected]3caf5542010-07-16 15:19:47390 SSLVector ssl_vector_;
[email protected]514aeaf2014-05-23 10:31:51391 TestCompletionCallback callback_;
[email protected]3caf5542010-07-16 15:19:47392 scoped_ptr<HttpNetworkTransaction> trans_;
393 scoped_ptr<HttpNetworkTransaction> trans_http_;
394 DataVector data_vector_;
[email protected]2d6728692011-03-12 01:39:55395 AlternateVector alternate_vector_;
396 AlternateDeterministicVector alternate_deterministic_vector_;
bnc29b1f072015-01-14 20:37:49397 const BoundNetLog log_;
[email protected]513963e2013-06-15 01:53:04398 SpdyNetworkTransactionTestParams test_params_;
[email protected]9e9e842e2010-07-23 23:09:15399 int port_;
[email protected]3b7828432010-08-18 18:33:27400 bool deterministic_;
[email protected]1f418ee2010-10-16 19:46:56401 bool spdy_enabled_;
[email protected]3caf5542010-07-16 15:19:47402 };
[email protected]aea80602009-09-18 00:55:08403
404 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
405 int expected_status);
406
407 void ConnectStatusHelper(const MockRead& status);
[email protected]d3cee19d2010-06-22 18:42:18408
[email protected]e3ebba0f2010-08-05 17:59:58409 const HttpRequestInfo& CreateGetPushRequest() {
bncce36dca22015-04-21 22:11:23410 get_push_request_.method = "GET";
411 get_push_request_.url = GURL(GetDefaultUrlWithPath("/foo.dat"));
412 get_push_request_.load_flags = 0;
413 return get_push_request_;
[email protected]e3ebba0f2010-08-05 17:59:58414 }
415
[email protected]d3cee19d2010-06-22 18:42:18416 const HttpRequestInfo& CreateGetRequest() {
bncce36dca22015-04-21 22:11:23417 if (!get_request_initialized_) {
418 get_request_.method = "GET";
419 get_request_.url = GURL(GetDefaultUrl());
420 get_request_.load_flags = 0;
421 get_request_initialized_ = true;
[email protected]d3cee19d2010-06-22 18:42:18422 }
bncce36dca22015-04-21 22:11:23423 return get_request_;
[email protected]d3cee19d2010-06-22 18:42:18424 }
425
[email protected]3deb9a52010-11-11 00:24:40426 const HttpRequestInfo& CreateGetRequestWithUserAgent() {
bncce36dca22015-04-21 22:11:23427 if (!get_request_initialized_) {
428 get_request_.method = "GET";
429 get_request_.url = GURL(GetDefaultUrl());
430 get_request_.load_flags = 0;
431 get_request_.extra_headers.SetHeader("User-Agent", "Chrome");
432 get_request_initialized_ = true;
[email protected]3deb9a52010-11-11 00:24:40433 }
bncce36dca22015-04-21 22:11:23434 return get_request_;
[email protected]3deb9a52010-11-11 00:24:40435 }
436
[email protected]310240592010-08-05 21:04:19437 const HttpRequestInfo& CreatePostRequest() {
bncce36dca22015-04-21 22:11:23438 if (!post_request_initialized_) {
[email protected]b2d26cfd2012-12-11 10:36:06439 ScopedVector<UploadElementReader> element_readers;
440 element_readers.push_back(
441 new UploadBytesElementReader(kUploadData, kUploadDataSize));
[email protected]96c77a72013-09-24 09:49:20442 upload_data_stream_.reset(
mmenkecbc2b712014-10-09 20:29:07443 new ElementsUploadDataStream(element_readers.Pass(), 0));
[email protected]329b68b2012-11-14 17:54:27444
bncce36dca22015-04-21 22:11:23445 post_request_.method = "POST";
446 post_request_.url = GURL(GetDefaultUrl());
447 post_request_.upload_data_stream = upload_data_stream_.get();
448 post_request_initialized_ = true;
[email protected]310240592010-08-05 21:04:19449 }
bncce36dca22015-04-21 22:11:23450 return post_request_;
[email protected]310240592010-08-05 21:04:19451 }
452
[email protected]69e6b4a2012-10-18 08:03:01453 const HttpRequestInfo& CreateFilePostRequest() {
bncce36dca22015-04-21 22:11:23454 if (!post_request_initialized_) {
[email protected]6cdfd7f2013-02-08 20:40:15455 base::FilePath file_path;
[email protected]03d9afc02013-12-03 17:55:52456 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
[email protected]69e6b4a2012-10-18 08:03:01457 CHECK_EQ(static_cast<int>(kUploadDataSize),
[email protected]e5c2a22e2014-03-06 20:42:30458 base::WriteFile(file_path, kUploadData, kUploadDataSize));
[email protected]69e6b4a2012-10-18 08:03:01459
[email protected]b2d26cfd2012-12-11 10:36:06460 ScopedVector<UploadElementReader> element_readers;
[email protected]cadac622013-06-11 16:46:36461 element_readers.push_back(
462 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
463 file_path,
464 0,
465 kUploadDataSize,
466 base::Time()));
[email protected]96c77a72013-09-24 09:49:20467 upload_data_stream_.reset(
mmenkecbc2b712014-10-09 20:29:07468 new ElementsUploadDataStream(element_readers.Pass(), 0));
[email protected]329b68b2012-11-14 17:54:27469
bncce36dca22015-04-21 22:11:23470 post_request_.method = "POST";
471 post_request_.url = GURL(GetDefaultUrl());
472 post_request_.upload_data_stream = upload_data_stream_.get();
473 post_request_initialized_ = true;
[email protected]69e6b4a2012-10-18 08:03:01474 }
bncce36dca22015-04-21 22:11:23475 return post_request_;
[email protected]69e6b4a2012-10-18 08:03:01476 }
477
[email protected]999dd8c2013-11-12 06:45:54478 const HttpRequestInfo& CreateUnreadableFilePostRequest() {
bncce36dca22015-04-21 22:11:23479 if (post_request_initialized_)
480 return post_request_;
[email protected]999dd8c2013-11-12 06:45:54481
482 base::FilePath file_path;
[email protected]03d9afc02013-12-03 17:55:52483 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
[email protected]999dd8c2013-11-12 06:45:54484 CHECK_EQ(static_cast<int>(kUploadDataSize),
[email protected]e5c2a22e2014-03-06 20:42:30485 base::WriteFile(file_path, kUploadData, kUploadDataSize));
[email protected]92be8eb2014-08-07 22:57:11486 CHECK(base::MakeFileUnreadable(file_path));
[email protected]999dd8c2013-11-12 06:45:54487
488 ScopedVector<UploadElementReader> element_readers;
489 element_readers.push_back(
490 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
491 file_path,
492 0,
493 kUploadDataSize,
494 base::Time()));
495 upload_data_stream_.reset(
mmenkecbc2b712014-10-09 20:29:07496 new ElementsUploadDataStream(element_readers.Pass(), 0));
[email protected]999dd8c2013-11-12 06:45:54497
bncce36dca22015-04-21 22:11:23498 post_request_.method = "POST";
499 post_request_.url = GURL(GetDefaultUrl());
500 post_request_.upload_data_stream = upload_data_stream_.get();
501 post_request_initialized_ = true;
502 return post_request_;
[email protected]999dd8c2013-11-12 06:45:54503 }
504
[email protected]69e6b4a2012-10-18 08:03:01505 const HttpRequestInfo& CreateComplexPostRequest() {
bncce36dca22015-04-21 22:11:23506 if (!post_request_initialized_) {
[email protected]69e6b4a2012-10-18 08:03:01507 const int kFileRangeOffset = 1;
508 const int kFileRangeLength = 3;
509 CHECK_LT(kFileRangeOffset + kFileRangeLength, kUploadDataSize);
510
[email protected]6cdfd7f2013-02-08 20:40:15511 base::FilePath file_path;
[email protected]03d9afc02013-12-03 17:55:52512 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
[email protected]69e6b4a2012-10-18 08:03:01513 CHECK_EQ(static_cast<int>(kUploadDataSize),
[email protected]e5c2a22e2014-03-06 20:42:30514 base::WriteFile(file_path, kUploadData, kUploadDataSize));
[email protected]69e6b4a2012-10-18 08:03:01515
[email protected]b2d26cfd2012-12-11 10:36:06516 ScopedVector<UploadElementReader> element_readers;
517 element_readers.push_back(
518 new UploadBytesElementReader(kUploadData, kFileRangeOffset));
[email protected]cadac622013-06-11 16:46:36519 element_readers.push_back(
520 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
521 file_path,
522 kFileRangeOffset,
523 kFileRangeLength,
524 base::Time()));
[email protected]b2d26cfd2012-12-11 10:36:06525 element_readers.push_back(new UploadBytesElementReader(
[email protected]69e6b4a2012-10-18 08:03:01526 kUploadData + kFileRangeOffset + kFileRangeLength,
[email protected]b2d26cfd2012-12-11 10:36:06527 kUploadDataSize - (kFileRangeOffset + kFileRangeLength)));
[email protected]96c77a72013-09-24 09:49:20528 upload_data_stream_.reset(
mmenkecbc2b712014-10-09 20:29:07529 new ElementsUploadDataStream(element_readers.Pass(), 0));
[email protected]329b68b2012-11-14 17:54:27530
bncce36dca22015-04-21 22:11:23531 post_request_.method = "POST";
532 post_request_.url = GURL(GetDefaultUrl());
533 post_request_.upload_data_stream = upload_data_stream_.get();
534 post_request_initialized_ = true;
[email protected]69e6b4a2012-10-18 08:03:01535 }
bncce36dca22015-04-21 22:11:23536 return post_request_;
[email protected]69e6b4a2012-10-18 08:03:01537 }
538
[email protected]0c9bf872011-03-04 17:53:22539 const HttpRequestInfo& CreateChunkedPostRequest() {
bncce36dca22015-04-21 22:11:23540 if (!chunked_post_request_initialized_) {
mmenkecbc2b712014-10-09 20:29:07541 upload_chunked_data_stream_.reset(new ChunkedUploadDataStream(0));
bncce36dca22015-04-21 22:11:23542 chunked_post_request_.method = "POST";
543 chunked_post_request_.url = GURL(GetDefaultUrl());
544 chunked_post_request_.upload_data_stream =
mmenkecbc2b712014-10-09 20:29:07545 upload_chunked_data_stream_.get();
bncce36dca22015-04-21 22:11:23546 chunked_post_request_initialized_ = true;
[email protected]0c9bf872011-03-04 17:53:22547 }
bncce36dca22015-04-21 22:11:23548 return chunked_post_request_;
[email protected]0c9bf872011-03-04 17:53:22549 }
550
[email protected]19ec8a72010-08-23 03:38:23551 // Read the result of a particular transaction, knowing that we've got
552 // multiple transactions in the read pipeline; so as we read, we may have
553 // to skip over data destined for other transactions while we consume
554 // the data for |trans|.
555 int ReadResult(HttpNetworkTransaction* trans,
rch73e17422015-05-04 19:52:06556 SocketDataProvider* data,
[email protected]19ec8a72010-08-23 03:38:23557 std::string* result) {
558 const int kSize = 3000;
[email protected]e3ebba0f2010-08-05 17:59:58559
[email protected]19ec8a72010-08-23 03:38:23560 int bytes_read = 0;
bnc301745a2015-03-10 03:22:16561 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(kSize));
[email protected]49639fa2011-12-20 23:22:41562 TestCompletionCallback callback;
[email protected]19ec8a72010-08-23 03:38:23563 while (true) {
[email protected]90499482013-06-01 00:39:50564 int rv = trans->Read(buf.get(), kSize, callback.callback());
[email protected]19ec8a72010-08-23 03:38:23565 if (rv == ERR_IO_PENDING) {
[email protected]19ec8a72010-08-23 03:38:23566 rv = callback.WaitForResult();
567 } else if (rv <= 0) {
568 break;
569 }
570 result->append(buf->data(), rv);
571 bytes_read += rv;
[email protected]e3ebba0f2010-08-05 17:59:58572 }
[email protected]19ec8a72010-08-23 03:38:23573 return bytes_read;
574 }
[email protected]e3ebba0f2010-08-05 17:59:58575
[email protected]19ec8a72010-08-23 03:38:23576 void VerifyStreamsClosed(const NormalSpdyTransactionHelper& helper) {
577 // This lengthy block is reaching into the pool to dig out the active
578 // session. Once we have the session, we verify that the streams are
579 // all closed and not leaked at this point.
580 const GURL& url = helper.request().url;
rchebf12982015-04-10 01:15:00581 HostPortPair host_port_pair(url.host(), 443);
[email protected]e6d017652013-05-17 18:01:40582 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
[email protected]314b03992014-04-01 01:28:53583 PRIVACY_MODE_DISABLED);
[email protected]19ec8a72010-08-23 03:38:23584 BoundNetLog log;
585 const scoped_refptr<HttpNetworkSession>& session = helper.session();
[email protected]795cbf82013-07-22 09:37:27586 base::WeakPtr<SpdySession> spdy_session =
[email protected]04644d42013-07-08 04:29:59587 session->spdy_session_pool()->FindAvailableSession(key, log);
[email protected]41d64e82013-07-03 22:44:26588 ASSERT_TRUE(spdy_session != NULL);
[email protected]19ec8a72010-08-23 03:38:23589 EXPECT_EQ(0u, spdy_session->num_active_streams());
590 EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams());
591 }
[email protected]e3ebba0f2010-08-05 17:59:58592
rch73e17422015-05-04 19:52:06593 void RunServerPushTest(SequencedSocketData* data,
[email protected]e3ebba0f2010-08-05 17:59:58594 HttpResponseInfo* response,
[email protected]a7a265ef2010-12-08 18:05:57595 HttpResponseInfo* push_response,
[email protected]8a0fc822013-06-27 20:52:43596 const std::string& expected) {
[email protected]262eec82013-03-19 21:01:36597 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:50598 BoundNetLog(), GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:58599 helper.RunPreTestSetup();
[email protected]d08358502010-12-03 22:04:03600 helper.AddData(data);
[email protected]e3ebba0f2010-08-05 17:59:58601
602 HttpNetworkTransaction* trans = helper.trans();
603
604 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:41605 TestCompletionCallback callback;
606 int rv = trans->Start(
607 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]e3ebba0f2010-08-05 17:59:58608 EXPECT_EQ(ERR_IO_PENDING, rv);
609 rv = callback.WaitForResult();
610
611 // Request the pushed path.
[email protected]e3ebba0f2010-08-05 17:59:58612 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:50613 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]49639fa2011-12-20 23:22:41614 rv = trans2->Start(
615 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
[email protected]e3ebba0f2010-08-05 17:59:58616 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]fc9d88472013-08-14 02:31:17617 base::RunLoop().RunUntilIdle();
[email protected]e3ebba0f2010-08-05 17:59:58618
[email protected]513963e2013-06-15 01:53:04619 // The data for the pushed path may be coming in more than 1 frame. Compile
[email protected]e3ebba0f2010-08-05 17:59:58620 // the results into a single string.
[email protected]19ec8a72010-08-23 03:38:23621
622 // Read the server push body.
623 std::string result2;
624 ReadResult(trans2.get(), data, &result2);
625 // Read the response body.
[email protected]e3ebba0f2010-08-05 17:59:58626 std::string result;
[email protected]19ec8a72010-08-23 03:38:23627 ReadResult(trans, data, &result);
[email protected]e3ebba0f2010-08-05 17:59:58628
629 // Verify that we consumed all test data.
rchbce10d972015-05-04 18:21:19630 EXPECT_TRUE(data->AllReadDataConsumed());
631 EXPECT_TRUE(data->AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:58632
633 // Verify that the received push data is same as the expected push data.
[email protected]19ec8a72010-08-23 03:38:23634 EXPECT_EQ(result2.compare(expected), 0) << "Received data: "
635 << result2
636 << "||||| Expected data: "
637 << expected;
[email protected]e3ebba0f2010-08-05 17:59:58638
639 // Verify the SYN_REPLY.
640 // Copy the response info, because trans goes away.
641 *response = *trans->GetResponseInfo();
[email protected]a7a265ef2010-12-08 18:05:57642 *push_response = *trans2->GetResponseInfo();
[email protected]19ec8a72010-08-23 03:38:23643
644 VerifyStreamsClosed(helper);
[email protected]e3ebba0f2010-08-05 17:59:58645 }
646
[email protected]49639fa2011-12-20 23:22:41647 static void DeleteSessionCallback(NormalSpdyTransactionHelper* helper,
648 int result) {
649 helper->ResetTrans();
650 }
651
652 static void StartTransactionCallback(
653 const scoped_refptr<HttpNetworkSession>& session,
rchebf12982015-04-10 01:15:00654 GURL url,
[email protected]49639fa2011-12-20 23:22:41655 int result) {
656 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]90499482013-06-01 00:39:50657 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:41658 TestCompletionCallback callback;
659 HttpRequestInfo request;
660 request.method = "GET";
rchebf12982015-04-10 01:15:00661 request.url = url;
[email protected]49639fa2011-12-20 23:22:41662 request.load_flags = 0;
663 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
664 EXPECT_EQ(ERR_IO_PENDING, rv);
665 callback.WaitForResult();
666 }
667
mmenkecbc2b712014-10-09 20:29:07668 ChunkedUploadDataStream* upload_chunked_data_stream() const {
669 return upload_chunked_data_stream_.get();
670 }
671
rchebf12982015-04-10 01:15:00672 const char* GetDefaultUrl() {
673 switch (GetParam().ssl_type) {
674 case HTTP_SPDY_VIA_ALT_SVC:
bncce36dca22015-04-21 22:11:23675 return "http://www.example.org";
rchebf12982015-04-10 01:15:00676 case HTTPS_SPDY_VIA_NPN:
bncce36dca22015-04-21 22:11:23677 return "https://www.example.org";
rchebf12982015-04-10 01:15:00678 default:
679 NOTREACHED();
680 return "";
681 }
682 }
683
684 std::string GetDefaultUrlWithPath(const char* path) {
685 return std::string(GetDefaultUrl()) + path;
686 }
687
[email protected]9ec54f82013-05-10 02:53:05688 SpdyTestUtil spdy_util_;
689
[email protected]d3cee19d2010-06-22 18:42:18690 private:
mmenkecbc2b712014-10-09 20:29:07691 scoped_ptr<ChunkedUploadDataStream> upload_chunked_data_stream_;
[email protected]329b68b2012-11-14 17:54:27692 scoped_ptr<UploadDataStream> upload_data_stream_;
bncce36dca22015-04-21 22:11:23693 bool get_request_initialized_;
694 bool post_request_initialized_;
695 bool chunked_post_request_initialized_;
696 HttpRequestInfo get_request_;
697 HttpRequestInfo post_request_;
698 HttpRequestInfo chunked_post_request_;
699 HttpRequestInfo get_push_request_;
[email protected]ea1a3f62012-11-16 20:34:23700 base::ScopedTempDir temp_dir_;
[email protected]aea80602009-09-18 00:55:08701};
702
703//-----------------------------------------------------------------------------
[email protected]9e9e842e2010-07-23 23:09:15704// All tests are run with three different connection types: SPDY after NPN
705// negotiation, SPDY without SSL, and SPDY with SSL.
[email protected]513963e2013-06-15 01:53:04706//
707// TODO(akalin): Use ::testing::Combine() when we are able to use
708// <tr1/tuple>.
709INSTANTIATE_TEST_CASE_P(
710 Spdy,
711 SpdyNetworkTransactionTest,
712 ::testing::Values(
rchebf12982015-04-10 01:15:00713 SpdyNetworkTransactionTestParams(kProtoSPDY31, HTTPS_SPDY_VIA_NPN),
714 SpdyNetworkTransactionTestParams(kProtoSPDY31, HTTP_SPDY_VIA_ALT_SVC),
715 SpdyNetworkTransactionTestParams(kProtoSPDY4_14, HTTPS_SPDY_VIA_NPN),
716 SpdyNetworkTransactionTestParams(kProtoSPDY4_14, HTTP_SPDY_VIA_ALT_SVC),
717 SpdyNetworkTransactionTestParams(kProtoSPDY4, HTTPS_SPDY_VIA_NPN),
718 SpdyNetworkTransactionTestParams(kProtoSPDY4, HTTP_SPDY_VIA_ALT_SVC)));
[email protected]aea80602009-09-18 00:55:08719
[email protected]3caf5542010-07-16 15:19:47720// Verify HttpNetworkTransaction constructor.
[email protected]513963e2013-06-15 01:53:04721TEST_P(SpdyNetworkTransactionTest, Constructor) {
[email protected]bb88e1d32013-05-03 23:11:07722 scoped_ptr<SpdySessionDependencies> session_deps(
[email protected]513963e2013-06-15 01:53:04723 CreateSpdySessionDependencies(GetParam()));
[email protected]ad8e04a2010-11-01 04:16:27724 scoped_refptr<HttpNetworkSession> session(
[email protected]bb88e1d32013-05-03 23:11:07725 SpdySessionDependencies::SpdyCreateSession(session_deps.get()));
[email protected]262eec82013-03-19 21:01:36726 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:50727 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]aea80602009-09-18 00:55:08728}
729
[email protected]513963e2013-06-15 01:53:04730TEST_P(SpdyNetworkTransactionTest, Get) {
[email protected]75f30cc22010-06-28 21:41:38731 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:46732 scoped_ptr<SpdyFrame> req(
733 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch73e17422015-05-04 19:52:06734 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]72552f02009-10-28 15:25:01735
[email protected]513963e2013-06-15 01:53:04736 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
737 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]72552f02009-10-28 15:25:01738 MockRead reads[] = {
rch73e17422015-05-04 19:52:06739 CreateMockRead(*resp, 1),
740 CreateMockRead(*body, 2),
741 MockRead(ASYNC, 0, 3) // EOF
[email protected]72552f02009-10-28 15:25:01742 };
743
rch73e17422015-05-04 19:52:06744 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:36745 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:50746 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:57747 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:47748 TransactionHelperResult out = helper.output();
[email protected]72552f02009-10-28 15:25:01749 EXPECT_EQ(OK, out.rv);
750 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
751 EXPECT_EQ("hello!", out.response_data);
752}
753
[email protected]513963e2013-06-15 01:53:04754TEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) {
[email protected]3d08dd382013-10-19 00:13:11755 for (RequestPriority p = MINIMUM_PRIORITY; p <= MAXIMUM_PRIORITY;
[email protected]31ae7ab2012-04-24 21:09:05756 p = RequestPriority(p + 1)) {
[email protected]c9c6f5c2010-07-31 01:30:03757 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:46758 scoped_ptr<SpdyFrame> req(
759 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, p, true));
rch73e17422015-05-04 19:52:06760 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]c9c6f5c2010-07-31 01:30:03761
[email protected]86aa87b2013-02-15 01:10:03762 SpdyPriority spdy_prio = 0;
[email protected]513963e2013-06-15 01:53:04763 EXPECT_TRUE(GetSpdyPriority(spdy_util_.spdy_version(), *req, &spdy_prio));
[email protected]c9c6f5c2010-07-31 01:30:03764 // this repeats the RequestPriority-->SpdyPriority mapping from
765 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
766 // sure it's being done right.
[email protected]513963e2013-06-15 01:53:04767 if (spdy_util_.spdy_version() < SPDY3) {
mmenkecbc2b712014-10-09 20:29:07768 switch (p) {
[email protected]513963e2013-06-15 01:53:04769 case HIGHEST:
770 EXPECT_EQ(0, spdy_prio);
771 break;
772 case MEDIUM:
773 EXPECT_EQ(1, spdy_prio);
774 break;
775 case LOW:
776 case LOWEST:
777 EXPECT_EQ(2, spdy_prio);
778 break;
779 case IDLE:
780 EXPECT_EQ(3, spdy_prio);
781 break;
782 default:
783 FAIL();
784 }
785 } else {
786 switch(p) {
787 case HIGHEST:
788 EXPECT_EQ(0, spdy_prio);
789 break;
790 case MEDIUM:
791 EXPECT_EQ(1, spdy_prio);
792 break;
793 case LOW:
794 EXPECT_EQ(2, spdy_prio);
795 break;
796 case LOWEST:
797 EXPECT_EQ(3, spdy_prio);
798 break;
799 case IDLE:
800 EXPECT_EQ(4, spdy_prio);
801 break;
802 default:
803 FAIL();
804 }
[email protected]c9c6f5c2010-07-31 01:30:03805 }
806
[email protected]513963e2013-06-15 01:53:04807 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
808 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c9c6f5c2010-07-31 01:30:03809 MockRead reads[] = {
rch73e17422015-05-04 19:52:06810 CreateMockRead(*resp, 1),
811 CreateMockRead(*body, 2),
812 MockRead(ASYNC, 0, 3) // EOF
[email protected]c9c6f5c2010-07-31 01:30:03813 };
814
rch73e17422015-05-04 19:52:06815 SequencedSocketData data(reads, arraysize(reads), writes,
816 arraysize(writes));
[email protected]c9c6f5c2010-07-31 01:30:03817 HttpRequestInfo http_req = CreateGetRequest();
[email protected]c9c6f5c2010-07-31 01:30:03818
[email protected]262eec82013-03-19 21:01:36819 NormalSpdyTransactionHelper helper(http_req, p, BoundNetLog(),
[email protected]61b4efc2012-04-27 18:12:50820 GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:57821 helper.RunToCompletion(&data);
[email protected]c9c6f5c2010-07-31 01:30:03822 TransactionHelperResult out = helper.output();
823 EXPECT_EQ(OK, out.rv);
824 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
825 EXPECT_EQ("hello!", out.response_data);
826 }
827}
828
[email protected]2bd93022010-07-17 00:58:44829// Start three gets simultaniously; making sure that multiplexed
830// streams work properly.
831
832// This can't use the TransactionHelper method, since it only
833// handles a single transaction, and finishes them as soon
834// as it launches them.
835
836// TODO(gavinp): create a working generalized TransactionHelper that
837// can allow multiple streams in flight.
838
[email protected]513963e2013-06-15 01:53:04839TEST_P(SpdyNetworkTransactionTest, ThreeGets) {
[email protected]cdf8f7e72013-05-23 10:56:46840 scoped_ptr<SpdyFrame> req(
841 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:04842 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
843 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
844 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2bd93022010-07-17 00:58:44845
[email protected]cdf8f7e72013-05-23 10:56:46846 scoped_ptr<SpdyFrame> req2(
847 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:04848 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
849 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
850 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]2bd93022010-07-17 00:58:44851
[email protected]cdf8f7e72013-05-23 10:56:46852 scoped_ptr<SpdyFrame> req3(
853 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
[email protected]513963e2013-06-15 01:53:04854 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
855 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
856 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
[email protected]2bd93022010-07-17 00:58:44857
[email protected]1b323172011-03-01 17:50:17858 MockWrite writes[] = {
rch73e17422015-05-04 19:52:06859 CreateMockWrite(*req, 0),
860 CreateMockWrite(*req2, 3),
861 CreateMockWrite(*req3, 6),
[email protected]2bd93022010-07-17 00:58:44862 };
863 MockRead reads[] = {
rch73e17422015-05-04 19:52:06864 CreateMockRead(*resp, 1),
865 CreateMockRead(*body, 2),
866 CreateMockRead(*resp2, 4),
867 CreateMockRead(*body2, 5),
868 CreateMockRead(*resp3, 7),
869 CreateMockRead(*body3, 8),
[email protected]2bd93022010-07-17 00:58:44870
rch73e17422015-05-04 19:52:06871 CreateMockRead(*fbody, 9),
872 CreateMockRead(*fbody2, 10),
873 CreateMockRead(*fbody3, 11),
[email protected]2bd93022010-07-17 00:58:44874
rch73e17422015-05-04 19:52:06875 MockRead(ASYNC, 0, 12), // EOF
[email protected]2bd93022010-07-17 00:58:44876 };
rch73e17422015-05-04 19:52:06877 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
878 SequencedSocketData data_placeholder(NULL, 0, NULL, 0);
[email protected]2bd93022010-07-17 00:58:44879
880 BoundNetLog log;
881 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:36882 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:50883 BoundNetLog(), GetParam(), NULL);
[email protected]bdebd1b2010-08-09 20:18:08884 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:57885 helper.AddData(&data);
rchaeb3f052015-04-14 16:02:49886 // We require placeholder data because three get requests are sent out at
887 // the same time which results in three sockets being connected. The first
888 // on will negotiate SPDY and will be used for all requests.
[email protected]dd54bd82012-07-19 23:44:57889 helper.AddData(&data_placeholder);
890 helper.AddData(&data_placeholder);
[email protected]bdebd1b2010-08-09 20:18:08891 scoped_ptr<HttpNetworkTransaction> trans1(
[email protected]90499482013-06-01 00:39:50892 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:08893 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:50894 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:08895 scoped_ptr<HttpNetworkTransaction> trans3(
[email protected]90499482013-06-01 00:39:50896 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]2bd93022010-07-17 00:58:44897
[email protected]49639fa2011-12-20 23:22:41898 TestCompletionCallback callback1;
899 TestCompletionCallback callback2;
900 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:44901
[email protected]bdebd1b2010-08-09 20:18:08902 HttpRequestInfo httpreq1 = CreateGetRequest();
903 HttpRequestInfo httpreq2 = CreateGetRequest();
904 HttpRequestInfo httpreq3 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:44905
[email protected]49639fa2011-12-20 23:22:41906 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:08907 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:41908 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:08909 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:41910 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:08911 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]2bd93022010-07-17 00:58:44912
[email protected]bdebd1b2010-08-09 20:18:08913 out.rv = callback1.WaitForResult();
914 ASSERT_EQ(OK, out.rv);
915 out.rv = callback3.WaitForResult();
916 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:44917
[email protected]bdebd1b2010-08-09 20:18:08918 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]90499482013-06-01 00:39:50919 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]bdebd1b2010-08-09 20:18:08920 EXPECT_TRUE(response1->was_fetched_via_spdy);
921 out.status_line = response1->headers->GetStatusLine();
922 out.response_info = *response1;
[email protected]2bd93022010-07-17 00:58:44923
[email protected]bdebd1b2010-08-09 20:18:08924 trans2->GetResponseInfo();
[email protected]2bd93022010-07-17 00:58:44925
[email protected]bdebd1b2010-08-09 20:18:08926 out.rv = ReadTransaction(trans1.get(), &out.response_data);
927 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:44928 EXPECT_EQ(OK, out.rv);
929
[email protected]2bd93022010-07-17 00:58:44930 EXPECT_EQ(OK, out.rv);
931 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
932 EXPECT_EQ("hello!hello!", out.response_data);
933}
934
[email protected]513963e2013-06-15 01:53:04935TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
[email protected]cdf8f7e72013-05-23 10:56:46936 scoped_ptr<SpdyFrame> req(
937 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:04938 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
939 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
940 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]1b323172011-03-01 17:50:17941
[email protected]cdf8f7e72013-05-23 10:56:46942 scoped_ptr<SpdyFrame> req2(
943 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:04944 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
945 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
946 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]1b323172011-03-01 17:50:17947
948 MockWrite writes[] = {
rch73e17422015-05-04 19:52:06949 CreateMockWrite(*req, 0), CreateMockWrite(*req2, 3),
[email protected]1b323172011-03-01 17:50:17950 };
951 MockRead reads[] = {
rch73e17422015-05-04 19:52:06952 CreateMockRead(*resp, 1),
953 CreateMockRead(*body, 2),
954 CreateMockRead(*resp2, 4),
955 CreateMockRead(*body2, 5),
956 CreateMockRead(*fbody, 6),
957 CreateMockRead(*fbody2, 7),
958 MockRead(ASYNC, 0, 8), // EOF
[email protected]1b323172011-03-01 17:50:17959 };
rch73e17422015-05-04 19:52:06960 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]1b323172011-03-01 17:50:17961
[email protected]d973e99a2012-02-17 21:02:36962 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
rch73e17422015-05-04 19:52:06963 SequencedSocketData data_placeholder(NULL, 0, NULL, 0);
[email protected]dd54bd82012-07-19 23:44:57964 data_placeholder.set_connect_data(never_finishing_connect);
[email protected]1b323172011-03-01 17:50:17965
966 BoundNetLog log;
967 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:36968 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:50969 BoundNetLog(), GetParam(), NULL);
[email protected]1b323172011-03-01 17:50:17970 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:57971 helper.AddData(&data);
rchaeb3f052015-04-14 16:02:49972 // We require placeholder data because two requests are sent out at
973 // the same time which results in two sockets being connected. The first
974 // on will negotiate SPDY and will be used for all requests.
[email protected]dd54bd82012-07-19 23:44:57975 helper.AddData(&data_placeholder);
[email protected]1b323172011-03-01 17:50:17976 scoped_ptr<HttpNetworkTransaction> trans1(
[email protected]90499482013-06-01 00:39:50977 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]1b323172011-03-01 17:50:17978 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:50979 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]1b323172011-03-01 17:50:17980
[email protected]49639fa2011-12-20 23:22:41981 TestCompletionCallback callback1;
982 TestCompletionCallback callback2;
[email protected]1b323172011-03-01 17:50:17983
984 HttpRequestInfo httpreq1 = CreateGetRequest();
985 HttpRequestInfo httpreq2 = CreateGetRequest();
986
[email protected]49639fa2011-12-20 23:22:41987 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]1b323172011-03-01 17:50:17988 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:41989 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]1b323172011-03-01 17:50:17990 ASSERT_EQ(ERR_IO_PENDING, out.rv);
991
992 out.rv = callback1.WaitForResult();
993 ASSERT_EQ(OK, out.rv);
994 out.rv = callback2.WaitForResult();
995 ASSERT_EQ(OK, out.rv);
996
997 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]90499482013-06-01 00:39:50998 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]1b323172011-03-01 17:50:17999 EXPECT_TRUE(response1->was_fetched_via_spdy);
1000 out.status_line = response1->headers->GetStatusLine();
1001 out.response_info = *response1;
1002 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1003 EXPECT_EQ(OK, out.rv);
1004 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1005 EXPECT_EQ("hello!hello!", out.response_data);
1006
1007 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
[email protected]90499482013-06-01 00:39:501008 EXPECT_TRUE(response2->headers.get() != NULL);
[email protected]1b323172011-03-01 17:50:171009 EXPECT_TRUE(response2->was_fetched_via_spdy);
1010 out.status_line = response2->headers->GetStatusLine();
1011 out.response_info = *response2;
1012 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1013 EXPECT_EQ(OK, out.rv);
1014 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1015 EXPECT_EQ("hello!hello!", out.response_data);
1016
1017 helper.VerifyDataConsumed();
1018}
1019
[email protected]513963e2013-06-15 01:53:041020TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
[email protected]cdf8f7e72013-05-23 10:56:461021 scoped_ptr<SpdyFrame> req(
1022 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041023 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1024 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1025 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]1b323172011-03-01 17:50:171026
[email protected]cdf8f7e72013-05-23 10:56:461027 scoped_ptr<SpdyFrame> req2(
1028 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041029 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1030 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1031 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]1b323172011-03-01 17:50:171032
1033 MockWrite writes[] = {
rch73e17422015-05-04 19:52:061034 CreateMockWrite(*req, 0), CreateMockWrite(*req2, 3),
[email protected]1b323172011-03-01 17:50:171035 };
1036 MockRead reads[] = {
rch73e17422015-05-04 19:52:061037 CreateMockRead(*resp, 1),
1038 CreateMockRead(*body, 2),
1039 CreateMockRead(*resp2, 4),
1040 CreateMockRead(*body2, 5),
1041 CreateMockRead(*fbody, 6),
1042 CreateMockRead(*fbody2, 7),
1043 MockRead(ASYNC, 0, 8), // EOF
[email protected]1b323172011-03-01 17:50:171044 };
rch73e17422015-05-04 19:52:061045 SequencedSocketData preconnect_data(reads, arraysize(reads), writes,
1046 arraysize(writes));
[email protected]1b323172011-03-01 17:50:171047
[email protected]d973e99a2012-02-17 21:02:361048 MockConnect never_finishing_connect(ASYNC, ERR_IO_PENDING);
[email protected]1b323172011-03-01 17:50:171049
rch73e17422015-05-04 19:52:061050 SequencedSocketData data_placeholder(NULL, 0, NULL, 0);
[email protected]dd54bd82012-07-19 23:44:571051 data_placeholder.set_connect_data(never_finishing_connect);
[email protected]1b323172011-03-01 17:50:171052
1053 BoundNetLog log;
1054 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361055 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501056 BoundNetLog(), GetParam(), NULL);
[email protected]1b323172011-03-01 17:50:171057 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571058 helper.AddData(&preconnect_data);
[email protected]1b323172011-03-01 17:50:171059 // We require placeholder data because 3 connections are attempted (first is
1060 // the preconnect, 2nd and 3rd are the never finished connections.
[email protected]dd54bd82012-07-19 23:44:571061 helper.AddData(&data_placeholder);
1062 helper.AddData(&data_placeholder);
[email protected]1b323172011-03-01 17:50:171063
1064 scoped_ptr<HttpNetworkTransaction> trans1(
[email protected]90499482013-06-01 00:39:501065 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]1b323172011-03-01 17:50:171066 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:501067 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]1b323172011-03-01 17:50:171068
[email protected]49639fa2011-12-20 23:22:411069 TestCompletionCallback callback1;
1070 TestCompletionCallback callback2;
[email protected]1b323172011-03-01 17:50:171071
1072 HttpRequestInfo httpreq = CreateGetRequest();
1073
1074 // Preconnect the first.
1075 SSLConfig preconnect_ssl_config;
1076 helper.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config);
1077 HttpStreamFactory* http_stream_factory =
1078 helper.session()->http_stream_factory();
[email protected]d7599122014-05-24 03:37:231079 helper.session()->GetNextProtos(&preconnect_ssl_config.next_protos);
[email protected]1b323172011-03-01 17:50:171080
1081 http_stream_factory->PreconnectStreams(
[email protected]262eec82013-03-19 21:01:361082 1, httpreq, DEFAULT_PRIORITY,
1083 preconnect_ssl_config, preconnect_ssl_config);
[email protected]1b323172011-03-01 17:50:171084
[email protected]49639fa2011-12-20 23:22:411085 out.rv = trans1->Start(&httpreq, callback1.callback(), log);
[email protected]1b323172011-03-01 17:50:171086 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:411087 out.rv = trans2->Start(&httpreq, callback2.callback(), log);
[email protected]1b323172011-03-01 17:50:171088 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1089
1090 out.rv = callback1.WaitForResult();
1091 ASSERT_EQ(OK, out.rv);
1092 out.rv = callback2.WaitForResult();
1093 ASSERT_EQ(OK, out.rv);
1094
1095 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]90499482013-06-01 00:39:501096 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]1b323172011-03-01 17:50:171097 EXPECT_TRUE(response1->was_fetched_via_spdy);
1098 out.status_line = response1->headers->GetStatusLine();
1099 out.response_info = *response1;
1100 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1101 EXPECT_EQ(OK, out.rv);
1102 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1103 EXPECT_EQ("hello!hello!", out.response_data);
1104
1105 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
[email protected]90499482013-06-01 00:39:501106 EXPECT_TRUE(response2->headers.get() != NULL);
[email protected]1b323172011-03-01 17:50:171107 EXPECT_TRUE(response2->was_fetched_via_spdy);
1108 out.status_line = response2->headers->GetStatusLine();
1109 out.response_info = *response2;
1110 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1111 EXPECT_EQ(OK, out.rv);
1112 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1113 EXPECT_EQ("hello!hello!", out.response_data);
1114
1115 helper.VerifyDataConsumed();
1116}
1117
[email protected]2bd93022010-07-17 00:58:441118// Similar to ThreeGets above, however this test adds a SETTINGS
1119// frame. The SETTINGS frame is read during the IO loop waiting on
1120// the first transaction completion, and sets a maximum concurrent
1121// stream limit of 1. This means that our IO loop exists after the
1122// second transaction completes, so we can assert on read_index().
[email protected]513963e2013-06-15 01:53:041123TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
[email protected]2bd93022010-07-17 00:58:441124 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:461125 scoped_ptr<SpdyFrame> req(
1126 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041127 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1128 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1129 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2bd93022010-07-17 00:58:441130
[email protected]cdf8f7e72013-05-23 10:56:461131 scoped_ptr<SpdyFrame> req2(
1132 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041133 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1134 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1135 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]2bd93022010-07-17 00:58:441136
[email protected]cdf8f7e72013-05-23 10:56:461137 scoped_ptr<SpdyFrame> req3(
1138 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041139 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
1140 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
1141 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
[email protected]2bd93022010-07-17 00:58:441142
[email protected]18b28ab2012-04-18 02:14:421143 SettingsMap settings;
[email protected]9dcec242013-01-10 23:24:281144 const uint32 max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:421145 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1146 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
[email protected]c10b20852013-05-15 21:29:201147 scoped_ptr<SpdyFrame> settings_frame(
1148 spdy_util_.ConstructSpdySettings(settings));
[email protected]d4a77c12014-05-15 20:45:211149 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]2bd93022010-07-17 00:58:441150
[email protected]2d6728692011-03-12 01:39:551151 MockWrite writes[] = {
rch73e17422015-05-04 19:52:061152 CreateMockWrite(*req, 0),
1153 CreateMockWrite(*settings_ack, 5),
1154 CreateMockWrite(*req2, 6),
1155 CreateMockWrite(*req3, 10),
[email protected]2bd93022010-07-17 00:58:441156 };
[email protected]2d6728692011-03-12 01:39:551157
[email protected]2bd93022010-07-17 00:58:441158 MockRead reads[] = {
rch73e17422015-05-04 19:52:061159 CreateMockRead(*settings_frame, 1),
1160 CreateMockRead(*resp, 2),
1161 CreateMockRead(*body, 3),
1162 CreateMockRead(*fbody, 4),
1163 CreateMockRead(*resp2, 7),
1164 CreateMockRead(*body2, 8),
1165 CreateMockRead(*fbody2, 9),
1166 CreateMockRead(*resp3, 11),
1167 CreateMockRead(*body3, 12),
1168 CreateMockRead(*fbody3, 13),
[email protected]2bd93022010-07-17 00:58:441169
rch73e17422015-05-04 19:52:061170 MockRead(ASYNC, 0, 14), // EOF
[email protected]2bd93022010-07-17 00:58:441171 };
1172
rch73e17422015-05-04 19:52:061173 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]2bd93022010-07-17 00:58:441174
1175 BoundNetLog log;
1176 TransactionHelperResult out;
1177 {
[email protected]262eec82013-03-19 21:01:361178 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501179 BoundNetLog(), GetParam(), NULL);
[email protected]2d6728692011-03-12 01:39:551180 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571181 helper.AddData(&data);
[email protected]bdebd1b2010-08-09 20:18:081182 scoped_ptr<HttpNetworkTransaction> trans1(
[email protected]90499482013-06-01 00:39:501183 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:081184 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:501185 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:081186 scoped_ptr<HttpNetworkTransaction> trans3(
[email protected]90499482013-06-01 00:39:501187 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]2bd93022010-07-17 00:58:441188
[email protected]49639fa2011-12-20 23:22:411189 TestCompletionCallback callback1;
1190 TestCompletionCallback callback2;
1191 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:441192
1193 HttpRequestInfo httpreq1 = CreateGetRequest();
1194 HttpRequestInfo httpreq2 = CreateGetRequest();
1195 HttpRequestInfo httpreq3 = CreateGetRequest();
1196
[email protected]49639fa2011-12-20 23:22:411197 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]2bd93022010-07-17 00:58:441198 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]513963e2013-06-15 01:53:041199 // Run transaction 1 through quickly to force a read of our SETTINGS
1200 // frame.
[email protected]2bd93022010-07-17 00:58:441201 out.rv = callback1.WaitForResult();
[email protected]bdebd1b2010-08-09 20:18:081202 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441203
[email protected]49639fa2011-12-20 23:22:411204 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]2bd93022010-07-17 00:58:441205 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]49639fa2011-12-20 23:22:411206 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]2bd93022010-07-17 00:58:441207 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1208 out.rv = callback2.WaitForResult();
1209 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441210
1211 out.rv = callback3.WaitForResult();
1212 ASSERT_EQ(OK, out.rv);
1213
1214 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]bdebd1b2010-08-09 20:18:081215 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:501216 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]2bd93022010-07-17 00:58:441217 EXPECT_TRUE(response1->was_fetched_via_spdy);
1218 out.status_line = response1->headers->GetStatusLine();
1219 out.response_info = *response1;
1220 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1221 EXPECT_EQ(OK, out.rv);
1222 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1223 EXPECT_EQ("hello!hello!", out.response_data);
1224
1225 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1226 out.status_line = response2->headers->GetStatusLine();
1227 out.response_info = *response2;
1228 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1229 EXPECT_EQ(OK, out.rv);
1230 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1231 EXPECT_EQ("hello!hello!", out.response_data);
1232
1233 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1234 out.status_line = response3->headers->GetStatusLine();
1235 out.response_info = *response3;
1236 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1237 EXPECT_EQ(OK, out.rv);
1238 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1239 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]044dcc52010-09-17 15:44:261240
1241 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441242 }
1243 EXPECT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441244}
1245
1246// Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1247// a fourth transaction. The third and fourth transactions have
1248// different data ("hello!" vs "hello!hello!") and because of the
1249// user specified priority, we expect to see them inverted in
1250// the response from the server.
[email protected]513963e2013-06-15 01:53:041251TEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
[email protected]2bd93022010-07-17 00:58:441252 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:461253 scoped_ptr<SpdyFrame> req(
1254 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041255 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1256 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1257 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2bd93022010-07-17 00:58:441258
[email protected]cdf8f7e72013-05-23 10:56:461259 scoped_ptr<SpdyFrame> req2(
1260 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041261 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1262 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1263 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]2bd93022010-07-17 00:58:441264
[email protected]ff98d7f02012-03-22 21:44:191265 scoped_ptr<SpdyFrame> req4(
[email protected]cdf8f7e72013-05-23 10:56:461266 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, HIGHEST, true));
[email protected]513963e2013-06-15 01:53:041267 scoped_ptr<SpdyFrame> resp4(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
1268 scoped_ptr<SpdyFrame> fbody4(spdy_util_.ConstructSpdyBodyFrame(5, true));
[email protected]2bd93022010-07-17 00:58:441269
[email protected]cdf8f7e72013-05-23 10:56:461270 scoped_ptr<SpdyFrame> req3(
1271 spdy_util_.ConstructSpdyGet(NULL, 0, false, 7, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041272 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 7));
1273 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(7, false));
1274 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(7, true));
[email protected]2bd93022010-07-17 00:58:441275
[email protected]18b28ab2012-04-18 02:14:421276 SettingsMap settings;
[email protected]9dcec242013-01-10 23:24:281277 const uint32 max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:421278 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1279 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
[email protected]c10b20852013-05-15 21:29:201280 scoped_ptr<SpdyFrame> settings_frame(
1281 spdy_util_.ConstructSpdySettings(settings));
[email protected]d4a77c12014-05-15 20:45:211282 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
rch73e17422015-05-04 19:52:061283 MockWrite writes[] = {
1284 CreateMockWrite(*req, 0),
1285 CreateMockWrite(*settings_ack, 5),
1286 // By making these synchronous, it guarantees that they are not *started*
1287 // before their sequence number, which in turn verifies that only a single
1288 // request is in-flight at a time.
1289 CreateMockWrite(*req2, 6, SYNCHRONOUS),
1290 CreateMockWrite(*req4, 10, SYNCHRONOUS),
1291 CreateMockWrite(*req3, 13, SYNCHRONOUS),
[email protected]2bd93022010-07-17 00:58:441292 };
1293 MockRead reads[] = {
rch73e17422015-05-04 19:52:061294 CreateMockRead(*settings_frame, 1),
1295 CreateMockRead(*resp, 2),
1296 CreateMockRead(*body, 3),
1297 CreateMockRead(*fbody, 4),
1298 CreateMockRead(*resp2, 7),
1299 CreateMockRead(*body2, 8),
1300 CreateMockRead(*fbody2, 9),
1301 CreateMockRead(*resp4, 11),
1302 CreateMockRead(*fbody4, 12),
1303 CreateMockRead(*resp3, 14),
1304 CreateMockRead(*body3, 15),
1305 CreateMockRead(*fbody3, 16),
[email protected]2bd93022010-07-17 00:58:441306
rch73e17422015-05-04 19:52:061307 MockRead(ASYNC, 0, 17), // EOF
[email protected]2bd93022010-07-17 00:58:441308 };
rch73e17422015-05-04 19:52:061309 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]2bd93022010-07-17 00:58:441310 BoundNetLog log;
1311 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361312 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1313 BoundNetLog(), GetParam(), NULL);
[email protected]bdebd1b2010-08-09 20:18:081314 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571315 helper.AddData(&data);
rch73e17422015-05-04 19:52:061316
[email protected]bdebd1b2010-08-09 20:18:081317 scoped_ptr<HttpNetworkTransaction> trans1(
[email protected]90499482013-06-01 00:39:501318 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:081319 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:501320 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:081321 scoped_ptr<HttpNetworkTransaction> trans3(
[email protected]90499482013-06-01 00:39:501322 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:081323 scoped_ptr<HttpNetworkTransaction> trans4(
[email protected]90499482013-06-01 00:39:501324 new HttpNetworkTransaction(HIGHEST, helper.session().get()));
[email protected]2bd93022010-07-17 00:58:441325
[email protected]49639fa2011-12-20 23:22:411326 TestCompletionCallback callback1;
1327 TestCompletionCallback callback2;
1328 TestCompletionCallback callback3;
1329 TestCompletionCallback callback4;
[email protected]2bd93022010-07-17 00:58:441330
[email protected]bdebd1b2010-08-09 20:18:081331 HttpRequestInfo httpreq1 = CreateGetRequest();
1332 HttpRequestInfo httpreq2 = CreateGetRequest();
1333 HttpRequestInfo httpreq3 = CreateGetRequest();
1334 HttpRequestInfo httpreq4 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:441335
[email protected]49639fa2011-12-20 23:22:411336 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081337 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]e0935cc2012-03-24 14:12:481338 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]bdebd1b2010-08-09 20:18:081339 out.rv = callback1.WaitForResult();
1340 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441341
[email protected]49639fa2011-12-20 23:22:411342 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081343 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:411344 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081345 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:411346 out.rv = trans4->Start(&httpreq4, callback4.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081347 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]2bd93022010-07-17 00:58:441348
[email protected]bdebd1b2010-08-09 20:18:081349 out.rv = callback2.WaitForResult();
1350 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441351
[email protected]bdebd1b2010-08-09 20:18:081352 out.rv = callback3.WaitForResult();
1353 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441354
[email protected]bdebd1b2010-08-09 20:18:081355 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]90499482013-06-01 00:39:501356 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]bdebd1b2010-08-09 20:18:081357 EXPECT_TRUE(response1->was_fetched_via_spdy);
1358 out.status_line = response1->headers->GetStatusLine();
1359 out.response_info = *response1;
1360 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1361 EXPECT_EQ(OK, out.rv);
1362 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1363 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441364
[email protected]bdebd1b2010-08-09 20:18:081365 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1366 out.status_line = response2->headers->GetStatusLine();
1367 out.response_info = *response2;
1368 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1369 EXPECT_EQ(OK, out.rv);
1370 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1371 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441372
[email protected]bdebd1b2010-08-09 20:18:081373 // notice: response3 gets two hellos, response4 gets one
1374 // hello, so we know dequeuing priority was respected.
1375 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1376 out.status_line = response3->headers->GetStatusLine();
1377 out.response_info = *response3;
1378 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1379 EXPECT_EQ(OK, out.rv);
1380 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1381 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441382
[email protected]bdebd1b2010-08-09 20:18:081383 out.rv = callback4.WaitForResult();
1384 EXPECT_EQ(OK, out.rv);
1385 const HttpResponseInfo* response4 = trans4->GetResponseInfo();
1386 out.status_line = response4->headers->GetStatusLine();
1387 out.response_info = *response4;
1388 out.rv = ReadTransaction(trans4.get(), &out.response_data);
1389 EXPECT_EQ(OK, out.rv);
1390 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1391 EXPECT_EQ("hello!", out.response_data);
1392 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441393 EXPECT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441394}
1395
1396// Similar to ThreeGetsMaxConcurrrent above, however, this test
rch73e17422015-05-04 19:52:061397// deletes a session in the middle of the transaction to ensure
[email protected]2bd93022010-07-17 00:58:441398// that we properly remove pendingcreatestream objects from
1399// the spdy_session
[email protected]513963e2013-06-15 01:53:041400TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
[email protected]2bd93022010-07-17 00:58:441401 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:461402 scoped_ptr<SpdyFrame> req(
1403 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041404 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1405 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1406 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2bd93022010-07-17 00:58:441407
[email protected]cdf8f7e72013-05-23 10:56:461408 scoped_ptr<SpdyFrame> req2(
1409 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041410 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1411 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1412 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]2bd93022010-07-17 00:58:441413
[email protected]18b28ab2012-04-18 02:14:421414 SettingsMap settings;
[email protected]9dcec242013-01-10 23:24:281415 const uint32 max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:421416 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1417 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
[email protected]c10b20852013-05-15 21:29:201418 scoped_ptr<SpdyFrame> settings_frame(
1419 spdy_util_.ConstructSpdySettings(settings));
[email protected]d4a77c12014-05-15 20:45:211420 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]2bd93022010-07-17 00:58:441421
[email protected]d4a77c12014-05-15 20:45:211422 MockWrite writes[] = {
rch73e17422015-05-04 19:52:061423 CreateMockWrite(*req, 0),
1424 CreateMockWrite(*settings_ack, 5),
1425 CreateMockWrite(*req2, 6),
[email protected]2bd93022010-07-17 00:58:441426 };
1427 MockRead reads[] = {
rch73e17422015-05-04 19:52:061428 CreateMockRead(*settings_frame, 1),
1429 CreateMockRead(*resp, 2),
1430 CreateMockRead(*body, 3),
1431 CreateMockRead(*fbody, 4),
1432 CreateMockRead(*resp2, 7),
1433 CreateMockRead(*body2, 8),
1434 CreateMockRead(*fbody2, 9),
1435 MockRead(ASYNC, 0, 10), // EOF
[email protected]2bd93022010-07-17 00:58:441436 };
1437
rch73e17422015-05-04 19:52:061438 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]2bd93022010-07-17 00:58:441439
1440 BoundNetLog log;
1441 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361442 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1443 BoundNetLog(), GetParam(), NULL);
[email protected]bdebd1b2010-08-09 20:18:081444 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571445 helper.AddData(&data);
[email protected]bdebd1b2010-08-09 20:18:081446 scoped_ptr<HttpNetworkTransaction> trans1(
[email protected]90499482013-06-01 00:39:501447 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:081448 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:501449 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:081450 scoped_ptr<HttpNetworkTransaction> trans3(
[email protected]90499482013-06-01 00:39:501451 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]2bd93022010-07-17 00:58:441452
[email protected]49639fa2011-12-20 23:22:411453 TestCompletionCallback callback1;
1454 TestCompletionCallback callback2;
1455 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:441456
[email protected]bdebd1b2010-08-09 20:18:081457 HttpRequestInfo httpreq1 = CreateGetRequest();
1458 HttpRequestInfo httpreq2 = CreateGetRequest();
1459 HttpRequestInfo httpreq3 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:441460
[email protected]49639fa2011-12-20 23:22:411461 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081462 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]e0935cc2012-03-24 14:12:481463 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]bdebd1b2010-08-09 20:18:081464 out.rv = callback1.WaitForResult();
1465 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441466
[email protected]49639fa2011-12-20 23:22:411467 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081468 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]49639fa2011-12-20 23:22:411469 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081470 delete trans3.release();
1471 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1472 out.rv = callback2.WaitForResult();
1473 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441474
[email protected]bdebd1b2010-08-09 20:18:081475 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1476 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:501477 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]bdebd1b2010-08-09 20:18:081478 EXPECT_TRUE(response1->was_fetched_via_spdy);
1479 out.status_line = response1->headers->GetStatusLine();
1480 out.response_info = *response1;
1481 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1482 EXPECT_EQ(OK, out.rv);
1483 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1484 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441485
[email protected]bdebd1b2010-08-09 20:18:081486 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1487 ASSERT_TRUE(response2 != NULL);
1488 out.status_line = response2->headers->GetStatusLine();
1489 out.response_info = *response2;
1490 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1491 EXPECT_EQ(OK, out.rv);
1492 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1493 EXPECT_EQ("hello!hello!", out.response_data);
1494 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441495 EXPECT_EQ(OK, out.rv);
[email protected]044dcc52010-09-17 15:44:261496}
[email protected]2bd93022010-07-17 00:58:441497
[email protected]448d4ca52012-03-04 04:12:231498namespace {
1499
[email protected]044dcc52010-09-17 15:44:261500// The KillerCallback will delete the transaction on error as part of the
1501// callback.
[email protected]49639fa2011-12-20 23:22:411502class KillerCallback : public TestCompletionCallbackBase {
[email protected]044dcc52010-09-17 15:44:261503 public:
1504 explicit KillerCallback(HttpNetworkTransaction* transaction)
[email protected]49639fa2011-12-20 23:22:411505 : transaction_(transaction),
[email protected]aa249b52013-04-30 01:04:321506 callback_(base::Bind(&KillerCallback::OnComplete,
1507 base::Unretained(this))) {
[email protected]044dcc52010-09-17 15:44:261508 }
1509
dchengb03027d2014-10-21 12:00:201510 ~KillerCallback() override {}
[email protected]49639fa2011-12-20 23:22:411511
1512 const CompletionCallback& callback() const { return callback_; }
1513
[email protected]044dcc52010-09-17 15:44:261514 private:
[email protected]49639fa2011-12-20 23:22:411515 void OnComplete(int result) {
1516 if (result < 0)
1517 delete transaction_;
1518
1519 SetResult(result);
1520 }
1521
[email protected]044dcc52010-09-17 15:44:261522 HttpNetworkTransaction* transaction_;
[email protected]49639fa2011-12-20 23:22:411523 CompletionCallback callback_;
[email protected]044dcc52010-09-17 15:44:261524};
1525
[email protected]448d4ca52012-03-04 04:12:231526} // namespace
1527
[email protected]044dcc52010-09-17 15:44:261528// Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1529// closes the socket while we have a pending transaction waiting for
1530// a pending stream creation. http://crbug.com/52901
[email protected]513963e2013-06-15 01:53:041531TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
[email protected]044dcc52010-09-17 15:44:261532 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:461533 scoped_ptr<SpdyFrame> req(
1534 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041535 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1536 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1537 scoped_ptr<SpdyFrame> fin_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]044dcc52010-09-17 15:44:261538
[email protected]cdf8f7e72013-05-23 10:56:461539 scoped_ptr<SpdyFrame> req2(
1540 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041541 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
[email protected]044dcc52010-09-17 15:44:261542
[email protected]18b28ab2012-04-18 02:14:421543 SettingsMap settings;
[email protected]9dcec242013-01-10 23:24:281544 const uint32 max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:421545 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1546 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
[email protected]c10b20852013-05-15 21:29:201547 scoped_ptr<SpdyFrame> settings_frame(
1548 spdy_util_.ConstructSpdySettings(settings));
[email protected]d4a77c12014-05-15 20:45:211549 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]044dcc52010-09-17 15:44:261550
[email protected]d4a77c12014-05-15 20:45:211551 MockWrite writes[] = {
rch73e17422015-05-04 19:52:061552 CreateMockWrite(*req, 0),
1553 CreateMockWrite(*settings_ack, 5),
1554 CreateMockWrite(*req2, 6),
[email protected]044dcc52010-09-17 15:44:261555 };
1556 MockRead reads[] = {
rch73e17422015-05-04 19:52:061557 CreateMockRead(*settings_frame, 1),
1558 CreateMockRead(*resp, 2),
1559 CreateMockRead(*body, 3),
1560 CreateMockRead(*fin_body, 4),
1561 CreateMockRead(*resp2, 7),
1562 MockRead(ASYNC, ERR_CONNECTION_RESET, 8), // Abort!
[email protected]044dcc52010-09-17 15:44:261563 };
1564
rch73e17422015-05-04 19:52:061565 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
1566 SequencedSocketData data_placeholder(NULL, 0, NULL, 0);
[email protected]044dcc52010-09-17 15:44:261567
1568 BoundNetLog log;
1569 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361570 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1571 BoundNetLog(), GetParam(), NULL);
[email protected]044dcc52010-09-17 15:44:261572 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571573 helper.AddData(&data);
[email protected]044dcc52010-09-17 15:44:261574 // We require placeholder data because three get requests are sent out, so
1575 // there needs to be three sets of SSL connection data.
[email protected]dd54bd82012-07-19 23:44:571576 helper.AddData(&data_placeholder);
1577 helper.AddData(&data_placeholder);
[email protected]90499482013-06-01 00:39:501578 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session().get());
1579 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session().get());
[email protected]262eec82013-03-19 21:01:361580 HttpNetworkTransaction* trans3(
[email protected]90499482013-06-01 00:39:501581 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]044dcc52010-09-17 15:44:261582
[email protected]49639fa2011-12-20 23:22:411583 TestCompletionCallback callback1;
1584 TestCompletionCallback callback2;
[email protected]044dcc52010-09-17 15:44:261585 KillerCallback callback3(trans3);
1586
1587 HttpRequestInfo httpreq1 = CreateGetRequest();
1588 HttpRequestInfo httpreq2 = CreateGetRequest();
1589 HttpRequestInfo httpreq3 = CreateGetRequest();
1590
[email protected]49639fa2011-12-20 23:22:411591 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
[email protected]044dcc52010-09-17 15:44:261592 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]e0935cc2012-03-24 14:12:481593 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]044dcc52010-09-17 15:44:261594 out.rv = callback1.WaitForResult();
1595 ASSERT_EQ(OK, out.rv);
1596
[email protected]49639fa2011-12-20 23:22:411597 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
[email protected]044dcc52010-09-17 15:44:261598 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]49639fa2011-12-20 23:22:411599 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]044dcc52010-09-17 15:44:261600 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1601 out.rv = callback3.WaitForResult();
1602 ASSERT_EQ(ERR_ABORTED, out.rv);
1603
[email protected]044dcc52010-09-17 15:44:261604 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
1605 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:501606 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]044dcc52010-09-17 15:44:261607 EXPECT_TRUE(response1->was_fetched_via_spdy);
1608 out.status_line = response1->headers->GetStatusLine();
1609 out.response_info = *response1;
1610 out.rv = ReadTransaction(&trans1, &out.response_data);
1611 EXPECT_EQ(OK, out.rv);
1612
1613 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
1614 ASSERT_TRUE(response2 != NULL);
1615 out.status_line = response2->headers->GetStatusLine();
1616 out.response_info = *response2;
1617 out.rv = ReadTransaction(&trans2, &out.response_data);
1618 EXPECT_EQ(ERR_CONNECTION_RESET, out.rv);
1619
1620 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441621}
1622
[email protected]d8ef27b2010-08-06 17:34:391623// Test that a simple PUT request works.
[email protected]513963e2013-06-15 01:53:041624TEST_P(SpdyNetworkTransactionTest, Put) {
[email protected]d8ef27b2010-08-06 17:34:391625 // Setup the request
1626 HttpRequestInfo request;
1627 request.method = "PUT";
rchebf12982015-04-10 01:15:001628 request.url = GURL(GetDefaultUrl());
[email protected]d8ef27b2010-08-06 17:34:391629
[email protected]513963e2013-06-15 01:53:041630 scoped_ptr<SpdyHeaderBlock> put_headers(
rchebf12982015-04-10 01:15:001631 spdy_util_.ConstructPutHeaderBlock(GetDefaultUrl(), 0));
[email protected]745aa9c2014-06-27 02:21:291632 scoped_ptr<SpdyFrame> req(
1633 spdy_util_.ConstructSpdySyn(1, *put_headers, LOWEST, false, true));
[email protected]d8ef27b2010-08-06 17:34:391634 MockWrite writes[] = {
rch73e17422015-05-04 19:52:061635 CreateMockWrite(*req, 0),
[email protected]d8ef27b2010-08-06 17:34:391636 };
1637
[email protected]745aa9c2014-06-27 02:21:291638 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:041639 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d8ef27b2010-08-06 17:34:391640 MockRead reads[] = {
rch73e17422015-05-04 19:52:061641 CreateMockRead(*resp, 1),
1642 CreateMockRead(*body, 2),
1643 MockRead(ASYNC, 0, 3) // EOF
[email protected]d8ef27b2010-08-06 17:34:391644 };
1645
rch73e17422015-05-04 19:52:061646 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361647 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501648 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:571649 helper.RunToCompletion(&data);
[email protected]d8ef27b2010-08-06 17:34:391650 TransactionHelperResult out = helper.output();
1651
1652 EXPECT_EQ(OK, out.rv);
1653 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1654}
1655
1656// Test that a simple HEAD request works.
[email protected]513963e2013-06-15 01:53:041657TEST_P(SpdyNetworkTransactionTest, Head) {
[email protected]d8ef27b2010-08-06 17:34:391658 // Setup the request
1659 HttpRequestInfo request;
1660 request.method = "HEAD";
rchebf12982015-04-10 01:15:001661 request.url = GURL(GetDefaultUrl());
[email protected]d8ef27b2010-08-06 17:34:391662
[email protected]513963e2013-06-15 01:53:041663 scoped_ptr<SpdyHeaderBlock> head_headers(
rchebf12982015-04-10 01:15:001664 spdy_util_.ConstructHeadHeaderBlock(GetDefaultUrl(), 0));
[email protected]745aa9c2014-06-27 02:21:291665 scoped_ptr<SpdyFrame> req(
1666 spdy_util_.ConstructSpdySyn(1, *head_headers, LOWEST, false, true));
[email protected]d8ef27b2010-08-06 17:34:391667 MockWrite writes[] = {
rch73e17422015-05-04 19:52:061668 CreateMockWrite(*req, 0),
[email protected]d8ef27b2010-08-06 17:34:391669 };
1670
[email protected]745aa9c2014-06-27 02:21:291671 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:041672 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d8ef27b2010-08-06 17:34:391673 MockRead reads[] = {
rch73e17422015-05-04 19:52:061674 CreateMockRead(*resp, 1),
1675 CreateMockRead(*body, 2),
1676 MockRead(ASYNC, 0, 3) // EOF
[email protected]d8ef27b2010-08-06 17:34:391677 };
1678
rch73e17422015-05-04 19:52:061679 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361680 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501681 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:571682 helper.RunToCompletion(&data);
[email protected]d8ef27b2010-08-06 17:34:391683 TransactionHelperResult out = helper.output();
1684
1685 EXPECT_EQ(OK, out.rv);
1686 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1687}
1688
[email protected]72552f02009-10-28 15:25:011689// Test that a simple POST works.
[email protected]513963e2013-06-15 01:53:041690TEST_P(SpdyNetworkTransactionTest, Post) {
rchebf12982015-04-10 01:15:001691 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
1692 GetDefaultUrl(), 1, kUploadDataSize, LOWEST, NULL, 0));
[email protected]513963e2013-06-15 01:53:041693 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]ff57bb82009-11-12 06:52:141694 MockWrite writes[] = {
rch73e17422015-05-04 19:52:061695 CreateMockWrite(*req, 0), CreateMockWrite(*body, 1), // POST upload frame
[email protected]ff57bb82009-11-12 06:52:141696 };
[email protected]72552f02009-10-28 15:25:011697
[email protected]513963e2013-06-15 01:53:041698 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]ff57bb82009-11-12 06:52:141699 MockRead reads[] = {
rch73e17422015-05-04 19:52:061700 CreateMockRead(*resp, 2),
1701 CreateMockRead(*body, 3),
1702 MockRead(ASYNC, 0, 4) // EOF
[email protected]aea80602009-09-18 00:55:081703 };
1704
rch73e17422015-05-04 19:52:061705 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361706 NormalSpdyTransactionHelper helper(CreatePostRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501707 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:571708 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:471709 TransactionHelperResult out = helper.output();
[email protected]aea80602009-09-18 00:55:081710 EXPECT_EQ(OK, out.rv);
1711 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1712 EXPECT_EQ("hello!", out.response_data);
1713}
1714
[email protected]69e6b4a2012-10-18 08:03:011715// Test that a POST with a file works.
[email protected]513963e2013-06-15 01:53:041716TEST_P(SpdyNetworkTransactionTest, FilePost) {
rchebf12982015-04-10 01:15:001717 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
1718 GetDefaultUrl(), 1, kUploadDataSize, LOWEST, NULL, 0));
[email protected]513963e2013-06-15 01:53:041719 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]69e6b4a2012-10-18 08:03:011720 MockWrite writes[] = {
rch73e17422015-05-04 19:52:061721 CreateMockWrite(*req, 0), CreateMockWrite(*body, 1), // POST upload frame
[email protected]69e6b4a2012-10-18 08:03:011722 };
1723
[email protected]513963e2013-06-15 01:53:041724 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]69e6b4a2012-10-18 08:03:011725 MockRead reads[] = {
rch73e17422015-05-04 19:52:061726 CreateMockRead(*resp, 2),
1727 CreateMockRead(*body, 3),
1728 MockRead(ASYNC, 0, 4) // EOF
[email protected]69e6b4a2012-10-18 08:03:011729 };
1730
rch73e17422015-05-04 19:52:061731 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361732 NormalSpdyTransactionHelper helper(CreateFilePostRequest(), DEFAULT_PRIORITY,
[email protected]69e6b4a2012-10-18 08:03:011733 BoundNetLog(), GetParam(), NULL);
1734 helper.RunToCompletion(&data);
1735 TransactionHelperResult out = helper.output();
1736 EXPECT_EQ(OK, out.rv);
1737 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1738 EXPECT_EQ("hello!", out.response_data);
1739}
1740
[email protected]999dd8c2013-11-12 06:45:541741// Test that a POST with a unreadable file fails.
1742TEST_P(SpdyNetworkTransactionTest, UnreadableFilePost) {
1743 MockWrite writes[] = {
rch73e17422015-05-04 19:52:061744 MockWrite(ASYNC, 0, 0) // EOF
[email protected]999dd8c2013-11-12 06:45:541745 };
1746 MockRead reads[] = {
rch73e17422015-05-04 19:52:061747 MockRead(ASYNC, 0, 1) // EOF
[email protected]999dd8c2013-11-12 06:45:541748 };
1749
rch73e17422015-05-04 19:52:061750 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]999dd8c2013-11-12 06:45:541751 NormalSpdyTransactionHelper helper(CreateUnreadableFilePostRequest(),
1752 DEFAULT_PRIORITY,
1753 BoundNetLog(), GetParam(), NULL);
1754 helper.RunPreTestSetup();
1755 helper.AddData(&data);
1756 helper.RunDefaultTest();
1757
1758 base::RunLoop().RunUntilIdle();
1759 helper.VerifyDataNotConsumed();
1760 EXPECT_EQ(ERR_ACCESS_DENIED, helper.output().rv);
1761}
1762
[email protected]69e6b4a2012-10-18 08:03:011763// Test that a complex POST works.
[email protected]513963e2013-06-15 01:53:041764TEST_P(SpdyNetworkTransactionTest, ComplexPost) {
rchebf12982015-04-10 01:15:001765 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
1766 GetDefaultUrl(), 1, kUploadDataSize, LOWEST, NULL, 0));
[email protected]513963e2013-06-15 01:53:041767 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]69e6b4a2012-10-18 08:03:011768 MockWrite writes[] = {
rch73e17422015-05-04 19:52:061769 CreateMockWrite(*req, 0), CreateMockWrite(*body, 1), // POST upload frame
[email protected]69e6b4a2012-10-18 08:03:011770 };
1771
[email protected]513963e2013-06-15 01:53:041772 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]69e6b4a2012-10-18 08:03:011773 MockRead reads[] = {
rch73e17422015-05-04 19:52:061774 CreateMockRead(*resp, 2),
1775 CreateMockRead(*body, 3),
1776 MockRead(ASYNC, 0, 4) // EOF
[email protected]69e6b4a2012-10-18 08:03:011777 };
1778
rch73e17422015-05-04 19:52:061779 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]69e6b4a2012-10-18 08:03:011780 NormalSpdyTransactionHelper helper(CreateComplexPostRequest(),
[email protected]262eec82013-03-19 21:01:361781 DEFAULT_PRIORITY,
[email protected]69e6b4a2012-10-18 08:03:011782 BoundNetLog(), GetParam(), NULL);
1783 helper.RunToCompletion(&data);
1784 TransactionHelperResult out = helper.output();
1785 EXPECT_EQ(OK, out.rv);
1786 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1787 EXPECT_EQ("hello!", out.response_data);
1788}
1789
[email protected]0c9bf872011-03-04 17:53:221790// Test that a chunked POST works.
[email protected]513963e2013-06-15 01:53:041791TEST_P(SpdyNetworkTransactionTest, ChunkedPost) {
[email protected]513963e2013-06-15 01:53:041792 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1793 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]0c9bf872011-03-04 17:53:221794 MockWrite writes[] = {
rch73e17422015-05-04 19:52:061795 CreateMockWrite(*req, 0), CreateMockWrite(*body, 1),
[email protected]0c9bf872011-03-04 17:53:221796 };
1797
[email protected]513963e2013-06-15 01:53:041798 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]0c9bf872011-03-04 17:53:221799 MockRead reads[] = {
rch73e17422015-05-04 19:52:061800 CreateMockRead(*resp, 2),
1801 CreateMockRead(*body, 3),
1802 MockRead(ASYNC, 0, 4) // EOF
[email protected]0c9bf872011-03-04 17:53:221803 };
1804
rch73e17422015-05-04 19:52:061805 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]0c9bf872011-03-04 17:53:221806 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
[email protected]262eec82013-03-19 21:01:361807 DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501808 BoundNetLog(), GetParam(), NULL);
[email protected]34b345f92013-02-22 03:27:261809
1810 // These chunks get merged into a single frame when being sent.
1811 const int kFirstChunkSize = kUploadDataSize/2;
mmenkecbc2b712014-10-09 20:29:071812 upload_chunked_data_stream()->AppendData(kUploadData, kFirstChunkSize, false);
1813 upload_chunked_data_stream()->AppendData(
[email protected]34b345f92013-02-22 03:27:261814 kUploadData + kFirstChunkSize, kUploadDataSize - kFirstChunkSize, true);
1815
[email protected]dd54bd82012-07-19 23:44:571816 helper.RunToCompletion(&data);
[email protected]0c9bf872011-03-04 17:53:221817 TransactionHelperResult out = helper.output();
1818 EXPECT_EQ(OK, out.rv);
1819 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
[email protected]34b345f92013-02-22 03:27:261820 EXPECT_EQ(kUploadData, out.response_data);
1821}
1822
1823// Test that a chunked POST works with chunks appended after transaction starts.
[email protected]513963e2013-06-15 01:53:041824TEST_P(SpdyNetworkTransactionTest, DelayedChunkedPost) {
[email protected]513963e2013-06-15 01:53:041825 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1826 scoped_ptr<SpdyFrame> chunk1(spdy_util_.ConstructSpdyBodyFrame(1, false));
1827 scoped_ptr<SpdyFrame> chunk2(spdy_util_.ConstructSpdyBodyFrame(1, false));
1828 scoped_ptr<SpdyFrame> chunk3(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]34b345f92013-02-22 03:27:261829 MockWrite writes[] = {
rch73e17422015-05-04 19:52:061830 CreateMockWrite(*req, 0),
1831 CreateMockWrite(*chunk1, 1),
1832 CreateMockWrite(*chunk2, 2),
1833 CreateMockWrite(*chunk3, 3),
[email protected]34b345f92013-02-22 03:27:261834 };
1835
[email protected]513963e2013-06-15 01:53:041836 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]34b345f92013-02-22 03:27:261837 MockRead reads[] = {
rch73e17422015-05-04 19:52:061838 CreateMockRead(*resp, 4),
1839 CreateMockRead(*chunk1, 5),
1840 CreateMockRead(*chunk2, 6),
1841 CreateMockRead(*chunk3, 7),
1842 MockRead(ASYNC, 0, 8) // EOF
[email protected]34b345f92013-02-22 03:27:261843 };
1844
rch73e17422015-05-04 19:52:061845 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]34b345f92013-02-22 03:27:261846 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
[email protected]262eec82013-03-19 21:01:361847 DEFAULT_PRIORITY,
[email protected]34b345f92013-02-22 03:27:261848 BoundNetLog(), GetParam(), NULL);
1849
mmenkecbc2b712014-10-09 20:29:071850 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
[email protected]34b345f92013-02-22 03:27:261851
1852 helper.RunPreTestSetup();
1853 helper.AddData(&data);
1854 ASSERT_TRUE(helper.StartDefaultTest());
1855
[email protected]fc9d88472013-08-14 02:31:171856 base::RunLoop().RunUntilIdle();
mmenkecbc2b712014-10-09 20:29:071857 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
[email protected]fc9d88472013-08-14 02:31:171858 base::RunLoop().RunUntilIdle();
mmenkecbc2b712014-10-09 20:29:071859 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true);
[email protected]34b345f92013-02-22 03:27:261860
1861 helper.FinishDefaultTest();
1862 helper.VerifyDataConsumed();
1863
1864 std::string expected_response;
1865 expected_response += kUploadData;
1866 expected_response += kUploadData;
1867 expected_response += kUploadData;
1868
1869 TransactionHelperResult out = helper.output();
1870 EXPECT_EQ(OK, out.rv);
1871 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1872 EXPECT_EQ(expected_response, out.response_data);
[email protected]0c9bf872011-03-04 17:53:221873}
1874
[email protected]a33cad2b62010-07-30 22:24:391875// Test that a POST without any post data works.
[email protected]513963e2013-06-15 01:53:041876TEST_P(SpdyNetworkTransactionTest, NullPost) {
[email protected]d2c1a97b2014-03-03 19:25:091877 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]a33cad2b62010-07-30 22:24:391878 // Setup the request
1879 HttpRequestInfo request;
1880 request.method = "POST";
rchebf12982015-04-10 01:15:001881 request.url = GURL(GetDefaultUrl());
[email protected]a33cad2b62010-07-30 22:24:391882 // Create an empty UploadData.
[email protected]329b68b2012-11-14 17:54:271883 request.upload_data_stream = NULL;
[email protected]a33cad2b62010-07-30 22:24:391884
[email protected]329b68b2012-11-14 17:54:271885 // When request.upload_data_stream is NULL for post, content-length is
[email protected]a33cad2b62010-07-30 22:24:391886 // expected to be 0.
[email protected]745aa9c2014-06-27 02:21:291887 scoped_ptr<SpdyHeaderBlock> req_block(
rchebf12982015-04-10 01:15:001888 spdy_util_.ConstructPostHeaderBlock(GetDefaultUrl(), 0));
[email protected]745aa9c2014-06-27 02:21:291889 scoped_ptr<SpdyFrame> req(
1890 spdy_util_.ConstructSpdySyn(1, *req_block, LOWEST, false, true));
[email protected]d2c1a97b2014-03-03 19:25:091891
[email protected]a33cad2b62010-07-30 22:24:391892 MockWrite writes[] = {
rch73e17422015-05-04 19:52:061893 CreateMockWrite(*req, 0),
[email protected]a33cad2b62010-07-30 22:24:391894 };
1895
[email protected]513963e2013-06-15 01:53:041896 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1897 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]a33cad2b62010-07-30 22:24:391898 MockRead reads[] = {
rch73e17422015-05-04 19:52:061899 CreateMockRead(*resp, 1),
1900 CreateMockRead(*body, 2),
1901 MockRead(ASYNC, 0, 3) // EOF
[email protected]a33cad2b62010-07-30 22:24:391902 };
1903
rch73e17422015-05-04 19:52:061904 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]a33cad2b62010-07-30 22:24:391905
[email protected]262eec82013-03-19 21:01:361906 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501907 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:571908 helper.RunToCompletion(&data);
[email protected]a33cad2b62010-07-30 22:24:391909 TransactionHelperResult out = helper.output();
1910 EXPECT_EQ(OK, out.rv);
1911 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1912 EXPECT_EQ("hello!", out.response_data);
1913}
1914
[email protected]edd3b0a52009-11-24 18:56:361915// Test that a simple POST works.
[email protected]513963e2013-06-15 01:53:041916TEST_P(SpdyNetworkTransactionTest, EmptyPost) {
[email protected]d2c1a97b2014-03-03 19:25:091917 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]329b68b2012-11-14 17:54:271918 // Create an empty UploadDataStream.
[email protected]b2d26cfd2012-12-11 10:36:061919 ScopedVector<UploadElementReader> element_readers;
mmenkecbc2b712014-10-09 20:29:071920 ElementsUploadDataStream stream(element_readers.Pass(), 0);
[email protected]329b68b2012-11-14 17:54:271921
[email protected]edd3b0a52009-11-24 18:56:361922 // Setup the request
1923 HttpRequestInfo request;
1924 request.method = "POST";
rchebf12982015-04-10 01:15:001925 request.url = GURL(GetDefaultUrl());
[email protected]329b68b2012-11-14 17:54:271926 request.upload_data_stream = &stream;
[email protected]edd3b0a52009-11-24 18:56:361927
[email protected]ad91dc52012-09-01 03:46:061928 const uint64 kContentLength = 0;
[email protected]d2c1a97b2014-03-03 19:25:091929
[email protected]745aa9c2014-06-27 02:21:291930 scoped_ptr<SpdyHeaderBlock> req_block(
rchebf12982015-04-10 01:15:001931 spdy_util_.ConstructPostHeaderBlock(GetDefaultUrl(), kContentLength));
[email protected]745aa9c2014-06-27 02:21:291932 scoped_ptr<SpdyFrame> req(
1933 spdy_util_.ConstructSpdySyn(1, *req_block, LOWEST, false, true));
[email protected]d2c1a97b2014-03-03 19:25:091934
[email protected]edd3b0a52009-11-24 18:56:361935 MockWrite writes[] = {
rch73e17422015-05-04 19:52:061936 CreateMockWrite(*req, 0),
[email protected]edd3b0a52009-11-24 18:56:361937 };
1938
[email protected]513963e2013-06-15 01:53:041939 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1940 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]edd3b0a52009-11-24 18:56:361941 MockRead reads[] = {
rch73e17422015-05-04 19:52:061942 CreateMockRead(*resp, 1),
1943 CreateMockRead(*body, 2),
1944 MockRead(ASYNC, 0, 3) // EOF
[email protected]edd3b0a52009-11-24 18:56:361945 };
1946
rch73e17422015-05-04 19:52:061947 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]bf2491a92009-11-29 16:39:481948
[email protected]262eec82013-03-19 21:01:361949 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1950 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:571951 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:471952 TransactionHelperResult out = helper.output();
[email protected]edd3b0a52009-11-24 18:56:361953 EXPECT_EQ(OK, out.rv);
1954 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1955 EXPECT_EQ("hello!", out.response_data);
1956}
1957
[email protected]35c3fc732014-02-15 00:16:071958// While we're doing a post, the server sends the reply before upload completes.
1959TEST_P(SpdyNetworkTransactionTest, ResponseBeforePostCompletes) {
1960 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1961 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1962 MockWrite writes[] = {
1963 CreateMockWrite(*req, 0),
1964 CreateMockWrite(*body, 3),
1965 };
1966 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]a5566f9702010-05-05 22:25:431967 MockRead reads[] = {
[email protected]35c3fc732014-02-15 00:16:071968 CreateMockRead(*resp, 1),
1969 CreateMockRead(*body, 2),
[email protected]099bc7e2013-07-18 04:19:161970 MockRead(ASYNC, 0, 4) // EOF
[email protected]a5566f9702010-05-05 22:25:431971 };
1972
[email protected]35c3fc732014-02-15 00:16:071973 // Write the request headers, and read the complete response
1974 // while still waiting for chunked request data.
[email protected]c92f4b4542012-07-26 23:53:211975 DeterministicSocketData data(reads, arraysize(reads),
1976 writes, arraysize(writes));
[email protected]35c3fc732014-02-15 00:16:071977 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
1978 DEFAULT_PRIORITY,
[email protected]c92f4b4542012-07-26 23:53:211979 BoundNetLog(), GetParam(), NULL);
1980 helper.SetDeterministic();
1981 helper.RunPreTestSetup();
1982 helper.AddDeterministicData(&data);
[email protected]c92f4b4542012-07-26 23:53:211983
[email protected]35c3fc732014-02-15 00:16:071984 ASSERT_TRUE(helper.StartDefaultTest());
[email protected]c92f4b4542012-07-26 23:53:211985
[email protected]35c3fc732014-02-15 00:16:071986 // Process the request headers, SYN_REPLY, and response body.
1987 // The request body is still in flight.
1988 data.RunFor(3);
1989
1990 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
1991 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1992
1993 // Finish sending the request body.
mmenkecbc2b712014-10-09 20:29:071994 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true);
[email protected]35c3fc732014-02-15 00:16:071995 data.RunFor(2);
1996
1997 std::string response_body;
1998 EXPECT_EQ(OK, ReadTransaction(helper.trans(), &response_body));
1999 EXPECT_EQ(kUploadData, response_body);
2000 helper.VerifyDataConsumed();
[email protected]a5566f9702010-05-05 22:25:432001}
2002
[email protected]f9a26d72010-08-03 18:07:132003// The client upon cancellation tries to send a RST_STREAM frame. The mock
2004// socket causes the TCP write to return zero. This test checks that the client
2005// tries to queue up the RST_STREAM frame again.
[email protected]513963e2013-06-15 01:53:042006TEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
[email protected]cdf8f7e72013-05-23 10:56:462007 scoped_ptr<SpdyFrame> req(
2008 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]ff98d7f02012-03-22 21:44:192009 scoped_ptr<SpdyFrame> rst(
[email protected]c10b20852013-05-15 21:29:202010 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]f9a26d72010-08-03 18:07:132011 MockWrite writes[] = {
[email protected]8ddf8322012-02-23 18:08:062012 CreateMockWrite(*req.get(), 0, SYNCHRONOUS),
2013 MockWrite(SYNCHRONOUS, 0, 0, 2),
2014 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
[email protected]f9a26d72010-08-03 18:07:132015 };
2016
[email protected]513963e2013-06-15 01:53:042017 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]f9a26d72010-08-03 18:07:132018 MockRead reads[] = {
[email protected]8ddf8322012-02-23 18:08:062019 CreateMockRead(*resp.get(), 1, ASYNC),
2020 MockRead(ASYNC, 0, 0, 4) // EOF
[email protected]f9a26d72010-08-03 18:07:132021 };
2022
[email protected]dd54bd82012-07-19 23:44:572023 DeterministicSocketData data(reads, arraysize(reads),
2024 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362025 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502026 BoundNetLog(), GetParam(), NULL);
[email protected]3b7828432010-08-18 18:33:272027 helper.SetDeterministic();
[email protected]f9a26d72010-08-03 18:07:132028 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572029 helper.AddDeterministicData(&data);
[email protected]f9a26d72010-08-03 18:07:132030 HttpNetworkTransaction* trans = helper.trans();
2031
[email protected]49639fa2011-12-20 23:22:412032 TestCompletionCallback callback;
2033 int rv = trans->Start(
2034 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]f9a26d72010-08-03 18:07:132035 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3b7828432010-08-18 18:33:272036
[email protected]dd54bd82012-07-19 23:44:572037 data.SetStop(2);
2038 data.Run();
[email protected]f9a26d72010-08-03 18:07:132039 helper.ResetTrans();
[email protected]dd54bd82012-07-19 23:44:572040 data.SetStop(20);
2041 data.Run();
[email protected]3b7828432010-08-18 18:33:272042
[email protected]f9a26d72010-08-03 18:07:132043 helper.VerifyDataConsumed();
2044}
2045
[email protected]93300672009-10-24 13:22:512046// Test that the transaction doesn't crash when we don't have a reply.
[email protected]513963e2013-06-15 01:53:042047TEST_P(SpdyNetworkTransactionTest, ResponseWithoutSynReply) {
[email protected]513963e2013-06-15 01:53:042048 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]ff57bb82009-11-12 06:52:142049 MockRead reads[] = {
rch73e17422015-05-04 19:52:062050 CreateMockRead(*body, 1), MockRead(ASYNC, 0, 3) // EOF
[email protected]93300672009-10-24 13:22:512051 };
2052
rch73e17422015-05-04 19:52:062053 scoped_ptr<SpdyFrame> req(
2054 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2055 scoped_ptr<SpdyFrame> rst(
2056 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
2057 MockWrite writes[] = {
2058 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 2),
2059 };
2060 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362061 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502062 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:572063 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:472064 TransactionHelperResult out = helper.output();
[email protected]2aeef782013-06-21 18:30:562065 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]93300672009-10-24 13:22:512066}
2067
[email protected]d30022352010-06-24 19:17:582068// Test that the transaction doesn't crash when we get two replies on the same
2069// stream ID. See http://crbug.com/45639.
[email protected]513963e2013-06-15 01:53:042070TEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
[email protected]cdf8f7e72013-05-23 10:56:462071 scoped_ptr<SpdyFrame> req(
2072 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]2aeef782013-06-21 18:30:562073 scoped_ptr<SpdyFrame> rst(
[email protected]00b29472014-01-16 18:10:242074 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
[email protected]2aeef782013-06-21 18:30:562075 MockWrite writes[] = {
rch73e17422015-05-04 19:52:062076 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
[email protected]2aeef782013-06-21 18:30:562077 };
[email protected]d30022352010-06-24 19:17:582078
[email protected]513963e2013-06-15 01:53:042079 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2080 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d30022352010-06-24 19:17:582081 MockRead reads[] = {
rch73e17422015-05-04 19:52:062082 CreateMockRead(*resp, 1),
2083 CreateMockRead(*resp, 2),
2084 CreateMockRead(*body, 3),
2085 MockRead(ASYNC, 0, 5) // EOF
[email protected]d30022352010-06-24 19:17:582086 };
2087
rch73e17422015-05-04 19:52:062088 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]d30022352010-06-24 19:17:582089
[email protected]262eec82013-03-19 21:01:362090 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502091 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:472092 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572093 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:472094
2095 HttpNetworkTransaction* trans = helper.trans();
[email protected]d30022352010-06-24 19:17:582096
[email protected]49639fa2011-12-20 23:22:412097 TestCompletionCallback callback;
2098 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
[email protected]d30022352010-06-24 19:17:582099 EXPECT_EQ(ERR_IO_PENDING, rv);
2100 rv = callback.WaitForResult();
2101 EXPECT_EQ(OK, rv);
2102
2103 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a5c493b92010-08-06 23:04:292104 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:502105 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]d30022352010-06-24 19:17:582106 EXPECT_TRUE(response->was_fetched_via_spdy);
2107 std::string response_data;
[email protected]3caf5542010-07-16 15:19:472108 rv = ReadTransaction(trans, &response_data);
[email protected]d30022352010-06-24 19:17:582109 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
[email protected]3caf5542010-07-16 15:19:472110
2111 helper.VerifyDataConsumed();
[email protected]d30022352010-06-24 19:17:582112}
2113
[email protected]513963e2013-06-15 01:53:042114TEST_P(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) {
[email protected]b3503002012-03-27 04:57:252115 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:462116 scoped_ptr<SpdyFrame> req(
2117 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]5a7bb252013-02-09 00:21:052118 scoped_ptr<SpdyFrame> rst(
[email protected]c10b20852013-05-15 21:29:202119 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
[email protected]b3503002012-03-27 04:57:252120 MockWrite writes[] = {
rch73e17422015-05-04 19:52:062121 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 2),
[email protected]b3503002012-03-27 04:57:252122 };
2123
2124 const char* const headers[] = {
[email protected]513963e2013-06-15 01:53:042125 "transfer-encoding", "chunked"
[email protected]b3503002012-03-27 04:57:252126 };
[email protected]513963e2013-06-15 01:53:042127 scoped_ptr<SpdyFrame> resp(
2128 spdy_util_.ConstructSpdyGetSynReply(headers, 1, 1));
2129 scoped_ptr<SpdyFrame> body(
2130 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]b3503002012-03-27 04:57:252131 MockRead reads[] = {
rch73e17422015-05-04 19:52:062132 CreateMockRead(*resp, 1),
2133 CreateMockRead(*body, 3),
2134 MockRead(ASYNC, 0, 4) // EOF
[email protected]b3503002012-03-27 04:57:252135 };
2136
rch73e17422015-05-04 19:52:062137 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362138 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502139 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:572140 helper.RunToCompletion(&data);
[email protected]b3503002012-03-27 04:57:252141 TransactionHelperResult out = helper.output();
2142 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
2143
2144 helper.session()->spdy_session_pool()->CloseAllSessions();
2145 helper.VerifyDataConsumed();
2146}
2147
[email protected]513963e2013-06-15 01:53:042148TEST_P(SpdyNetworkTransactionTest, ResetPushWithTransferEncoding) {
[email protected]b3503002012-03-27 04:57:252149 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:462150 scoped_ptr<SpdyFrame> req(
2151 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]5a7bb252013-02-09 00:21:052152 scoped_ptr<SpdyFrame> rst(
[email protected]c10b20852013-05-15 21:29:202153 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
[email protected]b3503002012-03-27 04:57:252154 MockWrite writes[] = {
rch73e17422015-05-04 19:52:062155 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
[email protected]b3503002012-03-27 04:57:252156 };
2157
[email protected]513963e2013-06-15 01:53:042158 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2159 const char* const headers[] = {
2160 "transfer-encoding", "chunked"
2161 };
2162 scoped_ptr<SpdyFrame> push(
rchebf12982015-04-10 01:15:002163 spdy_util_.ConstructSpdyPush(headers, arraysize(headers) / 2, 2, 1,
2164 GetDefaultUrlWithPath("/1").c_str()));
[email protected]513963e2013-06-15 01:53:042165 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]b3503002012-03-27 04:57:252166 MockRead reads[] = {
rch73e17422015-05-04 19:52:062167 CreateMockRead(*resp, 1),
2168 CreateMockRead(*push, 2),
2169 CreateMockRead(*body, 3),
2170 MockRead(ASYNC, 0, 5) // EOF
[email protected]b3503002012-03-27 04:57:252171 };
2172
rch73e17422015-05-04 19:52:062173 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362174 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502175 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:572176 helper.RunToCompletion(&data);
[email protected]b3503002012-03-27 04:57:252177 TransactionHelperResult out = helper.output();
2178 EXPECT_EQ(OK, out.rv);
2179 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
2180 EXPECT_EQ("hello!", out.response_data);
2181
2182 helper.session()->spdy_session_pool()->CloseAllSessions();
2183 helper.VerifyDataConsumed();
2184}
2185
[email protected]513963e2013-06-15 01:53:042186TEST_P(SpdyNetworkTransactionTest, CancelledTransaction) {
[email protected]75f30cc22010-06-28 21:41:382187 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:462188 scoped_ptr<SpdyFrame> req(
2189 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]34437af82009-11-06 02:28:492190 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:132191 CreateMockWrite(*req),
[email protected]34437af82009-11-06 02:28:492192 };
2193
[email protected]513963e2013-06-15 01:53:042194 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]34437af82009-11-06 02:28:492195 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:132196 CreateMockRead(*resp),
[email protected]34437af82009-11-06 02:28:492197 // This following read isn't used by the test, except during the
[email protected]b4c62eb2012-11-14 18:36:512198 // RunUntilIdle() call at the end since the SpdySession survives the
[email protected]3caf5542010-07-16 15:19:472199 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
[email protected]34437af82009-11-06 02:28:492200 // MockRead will do here.
[email protected]8ddf8322012-02-23 18:08:062201 MockRead(ASYNC, 0, 0) // EOF
[email protected]34437af82009-11-06 02:28:492202 };
2203
[email protected]31a2bfe2010-02-09 08:03:392204 StaticSocketDataProvider data(reads, arraysize(reads),
2205 writes, arraysize(writes));
[email protected]3caf5542010-07-16 15:19:472206
[email protected]262eec82013-03-19 21:01:362207 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502208 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:472209 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:582210 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:472211 HttpNetworkTransaction* trans = helper.trans();
[email protected]34437af82009-11-06 02:28:492212
[email protected]49639fa2011-12-20 23:22:412213 TestCompletionCallback callback;
2214 int rv = trans->Start(
2215 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]34437af82009-11-06 02:28:492216 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3caf5542010-07-16 15:19:472217 helper.ResetTrans(); // Cancel the transaction.
[email protected]34437af82009-11-06 02:28:492218
[email protected]30c942b2010-07-21 16:59:592219 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]34437af82009-11-06 02:28:492220 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:172221 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:472222 helper.VerifyDataNotConsumed();
[email protected]34437af82009-11-06 02:28:492223}
[email protected]72552f02009-10-28 15:25:012224
[email protected]6c6ea172010-07-27 20:04:032225// Verify that the client sends a Rst Frame upon cancelling the stream.
[email protected]513963e2013-06-15 01:53:042226TEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
[email protected]cdf8f7e72013-05-23 10:56:462227 scoped_ptr<SpdyFrame> req(
2228 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]ff98d7f02012-03-22 21:44:192229 scoped_ptr<SpdyFrame> rst(
[email protected]c10b20852013-05-15 21:29:202230 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]6c6ea172010-07-27 20:04:032231 MockWrite writes[] = {
[email protected]8ddf8322012-02-23 18:08:062232 CreateMockWrite(*req, 0, SYNCHRONOUS),
2233 CreateMockWrite(*rst, 2, SYNCHRONOUS),
[email protected]6c6ea172010-07-27 20:04:032234 };
2235
[email protected]513963e2013-06-15 01:53:042236 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]6c6ea172010-07-27 20:04:032237 MockRead reads[] = {
[email protected]8ddf8322012-02-23 18:08:062238 CreateMockRead(*resp, 1, ASYNC),
2239 MockRead(ASYNC, 0, 0, 3) // EOF
[email protected]6c6ea172010-07-27 20:04:032240 };
2241
[email protected]dd54bd82012-07-19 23:44:572242 DeterministicSocketData data(reads, arraysize(reads),
[email protected]513963e2013-06-15 01:53:042243 writes, arraysize(writes));
[email protected]6c6ea172010-07-27 20:04:032244
[email protected]262eec82013-03-19 21:01:362245 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]6c6ea172010-07-27 20:04:032246 BoundNetLog(),
[email protected]61b4efc2012-04-27 18:12:502247 GetParam(), NULL);
[email protected]3b7828432010-08-18 18:33:272248 helper.SetDeterministic();
[email protected]6c6ea172010-07-27 20:04:032249 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572250 helper.AddDeterministicData(&data);
[email protected]6c6ea172010-07-27 20:04:032251 HttpNetworkTransaction* trans = helper.trans();
2252
[email protected]49639fa2011-12-20 23:22:412253 TestCompletionCallback callback;
[email protected]6c6ea172010-07-27 20:04:032254
[email protected]49639fa2011-12-20 23:22:412255 int rv = trans->Start(
2256 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]6c6ea172010-07-27 20:04:032257 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]6c6ea172010-07-27 20:04:032258
[email protected]dd54bd82012-07-19 23:44:572259 data.SetStop(2);
2260 data.Run();
[email protected]3b7828432010-08-18 18:33:272261 helper.ResetTrans();
[email protected]dd54bd82012-07-19 23:44:572262 data.SetStop(20);
2263 data.Run();
[email protected]3b7828432010-08-18 18:33:272264
[email protected]6c6ea172010-07-27 20:04:032265 helper.VerifyDataConsumed();
2266}
2267
[email protected]b278eb72010-07-09 20:17:002268// Verify that the client can correctly deal with the user callback attempting
2269// to start another transaction on a session that is closing down. See
2270// http://crbug.com/47455
[email protected]513963e2013-06-15 01:53:042271TEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
[email protected]cdf8f7e72013-05-23 10:56:462272 scoped_ptr<SpdyFrame> req(
2273 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch73e17422015-05-04 19:52:062274 MockWrite writes[] = {CreateMockWrite(*req)};
2275 MockWrite writes2[] = {CreateMockWrite(*req, 0)};
[email protected]b278eb72010-07-09 20:17:002276
[email protected]cbdd73162013-03-18 23:27:332277 // The indicated length of this frame is longer than its actual length. When
2278 // the session receives an empty frame after this one, it shuts down the
[email protected]b278eb72010-07-09 20:17:002279 // session, and calls the read callback with the incomplete data.
2280 const uint8 kGetBodyFrame2[] = {
2281 0x00, 0x00, 0x00, 0x01,
2282 0x01, 0x00, 0x00, 0x07,
2283 'h', 'e', 'l', 'l', 'o', '!',
2284 };
2285
[email protected]513963e2013-06-15 01:53:042286 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]b278eb72010-07-09 20:17:002287 MockRead reads[] = {
2288 CreateMockRead(*resp, 2),
[email protected]8ddf8322012-02-23 18:08:062289 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause
2290 MockRead(ASYNC, reinterpret_cast<const char*>(kGetBodyFrame2),
[email protected]b278eb72010-07-09 20:17:002291 arraysize(kGetBodyFrame2), 4),
[email protected]8ddf8322012-02-23 18:08:062292 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
2293 MockRead(ASYNC, 0, 0, 6), // EOF
[email protected]b278eb72010-07-09 20:17:002294 };
2295 MockRead reads2[] = {
rch73e17422015-05-04 19:52:062296 CreateMockRead(*resp, 1), MockRead(ASYNC, 0, 0, 2), // EOF
[email protected]b278eb72010-07-09 20:17:002297 };
2298
[email protected]dd54bd82012-07-19 23:44:572299 OrderedSocketData data(reads, arraysize(reads),
2300 writes, arraysize(writes));
rch73e17422015-05-04 19:52:062301 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
2302 arraysize(writes2));
[email protected]3caf5542010-07-16 15:19:472303
[email protected]262eec82013-03-19 21:01:362304 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502305 BoundNetLog(), GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:582306 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572307 helper.AddData(&data);
2308 helper.AddData(&data2);
[email protected]3caf5542010-07-16 15:19:472309 HttpNetworkTransaction* trans = helper.trans();
[email protected]b278eb72010-07-09 20:17:002310
2311 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412312 TestCompletionCallback callback;
2313 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
[email protected]b278eb72010-07-09 20:17:002314 EXPECT_EQ(ERR_IO_PENDING, rv);
2315 rv = callback.WaitForResult();
2316
[email protected]b278eb72010-07-09 20:17:002317 const int kSize = 3000;
bnc301745a2015-03-10 03:22:162318 scoped_refptr<IOBuffer> buf(new IOBuffer(kSize));
[email protected]49639fa2011-12-20 23:22:412319 rv = trans->Read(
rchebf12982015-04-10 01:15:002320 buf.get(), kSize,
[email protected]513963e2013-06-15 01:53:042321 base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback,
rchebf12982015-04-10 01:15:002322 helper.session(), GURL(GetDefaultUrl())));
[email protected]3caf5542010-07-16 15:19:472323 // This forces an err_IO_pending, which sets the callback.
[email protected]dd54bd82012-07-19 23:44:572324 data.CompleteRead();
[email protected]3caf5542010-07-16 15:19:472325 // This finishes the read.
[email protected]dd54bd82012-07-19 23:44:572326 data.CompleteRead();
[email protected]3caf5542010-07-16 15:19:472327 helper.VerifyDataConsumed();
[email protected]b278eb72010-07-09 20:17:002328}
2329
[email protected]9be804c82010-06-24 17:59:462330// Verify that the client can correctly deal with the user callback deleting the
2331// transaction. Failures will usually be valgrind errors. See
2332// http://crbug.com/46925
[email protected]513963e2013-06-15 01:53:042333TEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
[email protected]cdf8f7e72013-05-23 10:56:462334 scoped_ptr<SpdyFrame> req(
2335 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]e7f75092010-07-01 22:39:132336 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]9be804c82010-06-24 17:59:462337
[email protected]513963e2013-06-15 01:53:042338 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2339 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]9be804c82010-06-24 17:59:462340 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:132341 CreateMockRead(*resp.get(), 2),
[email protected]8ddf8322012-02-23 18:08:062342 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause
[email protected]e7f75092010-07-01 22:39:132343 CreateMockRead(*body.get(), 4),
[email protected]8ddf8322012-02-23 18:08:062344 MockRead(ASYNC, 0, 0, 5), // EOF
[email protected]9be804c82010-06-24 17:59:462345 };
2346
[email protected]dd54bd82012-07-19 23:44:572347 OrderedSocketData data(reads, arraysize(reads),
2348 writes, arraysize(writes));
[email protected]3caf5542010-07-16 15:19:472349
[email protected]262eec82013-03-19 21:01:362350 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502351 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:472352 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572353 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:472354 HttpNetworkTransaction* trans = helper.trans();
[email protected]9be804c82010-06-24 17:59:462355
2356 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412357 TestCompletionCallback callback;
2358 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
[email protected]9be804c82010-06-24 17:59:462359 EXPECT_EQ(ERR_IO_PENDING, rv);
2360 rv = callback.WaitForResult();
2361
2362 // Setup a user callback which will delete the session, and clear out the
2363 // memory holding the stream object. Note that the callback deletes trans.
[email protected]9be804c82010-06-24 17:59:462364 const int kSize = 3000;
bnc301745a2015-03-10 03:22:162365 scoped_refptr<IOBuffer> buf(new IOBuffer(kSize));
[email protected]49639fa2011-12-20 23:22:412366 rv = trans->Read(
[email protected]90499482013-06-01 00:39:502367 buf.get(),
2368 kSize,
[email protected]513963e2013-06-15 01:53:042369 base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback,
[email protected]49639fa2011-12-20 23:22:412370 base::Unretained(&helper)));
[email protected]9be804c82010-06-24 17:59:462371 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]dd54bd82012-07-19 23:44:572372 data.CompleteRead();
[email protected]9be804c82010-06-24 17:59:462373
2374 // Finish running rest of tasks.
[email protected]fc9d88472013-08-14 02:31:172375 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:472376 helper.VerifyDataConsumed();
[email protected]9be804c82010-06-24 17:59:462377}
2378
bncce36dca22015-04-21 22:11:232379// Send a spdy request to www.example.org that gets redirected to www.foo.com.
rchebf12982015-04-10 01:15:002380TEST_P(SpdyNetworkTransactionTest, DISABLED_RedirectGetRequest) {
[email protected]513963e2013-06-15 01:53:042381 scoped_ptr<SpdyHeaderBlock> headers(
rchebf12982015-04-10 01:15:002382 spdy_util_.ConstructGetHeaderBlock(GetDefaultUrl()));
[email protected]513963e2013-06-15 01:53:042383 (*headers)["user-agent"] = "";
jgraettinger8f00db8b2014-09-24 23:00:062384 (*headers)["accept-encoding"] = "gzip, deflate";
[email protected]513963e2013-06-15 01:53:042385 scoped_ptr<SpdyHeaderBlock> headers2(
2386 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2387 (*headers2)["user-agent"] = "";
jgraettinger8f00db8b2014-09-24 23:00:062388 (*headers2)["accept-encoding"] = "gzip, deflate";
[email protected]e3ebba0f2010-08-05 17:59:582389
bncce36dca22015-04-21 22:11:232390 // Setup writes/reads to www.example.org
[email protected]745aa9c2014-06-27 02:21:292391 scoped_ptr<SpdyFrame> req(
2392 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
2393 scoped_ptr<SpdyFrame> req2(
2394 spdy_util_.ConstructSpdySyn(1, *headers2, LOWEST, false, true));
[email protected]513963e2013-06-15 01:53:042395 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReplyRedirect(1));
[email protected]e3ebba0f2010-08-05 17:59:582396 MockWrite writes[] = {
2397 CreateMockWrite(*req, 1),
2398 };
2399 MockRead reads[] = {
2400 CreateMockRead(*resp, 2),
[email protected]8ddf8322012-02-23 18:08:062401 MockRead(ASYNC, 0, 0, 3) // EOF
[email protected]e3ebba0f2010-08-05 17:59:582402 };
2403
2404 // Setup writes/reads to www.foo.com
[email protected]513963e2013-06-15 01:53:042405 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2406 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582407 MockWrite writes2[] = {
2408 CreateMockWrite(*req2, 1),
2409 };
2410 MockRead reads2[] = {
2411 CreateMockRead(*resp2, 2),
2412 CreateMockRead(*body2, 3),
[email protected]8ddf8322012-02-23 18:08:062413 MockRead(ASYNC, 0, 0, 4) // EOF
[email protected]e3ebba0f2010-08-05 17:59:582414 };
rch73e17422015-05-04 19:52:062415 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2416 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
2417 arraysize(writes2));
[email protected]e3ebba0f2010-08-05 17:59:582418
2419 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
[email protected]e3ebba0f2010-08-05 17:59:582420 TestDelegate d;
2421 {
rchebf12982015-04-10 01:15:002422 SpdyURLRequestContext spdy_url_request_context(GetParam().protocol);
davidben151423e2015-03-23 18:48:362423 scoped_ptr<URLRequest> r(spdy_url_request_context.CreateRequest(
rchebf12982015-04-10 01:15:002424 GURL(GetDefaultUrl()), DEFAULT_PRIORITY, &d));
[email protected]ef2bf422012-05-11 03:27:092425 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572426 AddSocketDataProvider(&data);
[email protected]ef2bf422012-05-11 03:27:092427 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572428 AddSocketDataProvider(&data2);
[email protected]e3ebba0f2010-08-05 17:59:582429
2430 d.set_quit_on_redirect(true);
[email protected]f7022f32014-08-21 16:32:192431 r->Start();
[email protected]fc9d88472013-08-14 02:31:172432 base::RunLoop().Run();
[email protected]513963e2013-06-15 01:53:042433
[email protected]e3ebba0f2010-08-05 17:59:582434 EXPECT_EQ(1, d.received_redirect_count());
2435
[email protected]f7022f32014-08-21 16:32:192436 r->FollowDeferredRedirect();
[email protected]fc9d88472013-08-14 02:31:172437 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582438 EXPECT_EQ(1, d.response_started_count());
2439 EXPECT_FALSE(d.received_data_before_response());
bnc301745a2015-03-10 03:22:162440 EXPECT_EQ(URLRequestStatus::SUCCESS, r->status().status());
[email protected]e3ebba0f2010-08-05 17:59:582441 std::string contents("hello!");
2442 EXPECT_EQ(contents, d.data_received());
2443 }
rchbce10d972015-05-04 18:21:192444 EXPECT_TRUE(data.AllReadDataConsumed());
2445 EXPECT_TRUE(data.AllWriteDataConsumed());
2446 EXPECT_TRUE(data2.AllReadDataConsumed());
2447 EXPECT_TRUE(data2.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582448}
2449
bncce36dca22015-04-21 22:11:232450// Send a spdy request to www.example.org. Get a pushed stream that redirects to
[email protected]e3ebba0f2010-08-05 17:59:582451// www.foo.com.
rchebf12982015-04-10 01:15:002452TEST_P(SpdyNetworkTransactionTest, DISABLED_RedirectServerPush) {
[email protected]513963e2013-06-15 01:53:042453 scoped_ptr<SpdyHeaderBlock> headers(
rchebf12982015-04-10 01:15:002454 spdy_util_.ConstructGetHeaderBlock(GetDefaultUrl()));
[email protected]513963e2013-06-15 01:53:042455 (*headers)["user-agent"] = "";
jgraettinger8f00db8b2014-09-24 23:00:062456 (*headers)["accept-encoding"] = "gzip, deflate";
[email protected]3a8d6852011-03-11 23:43:442457
bncce36dca22015-04-21 22:11:232458 // Setup writes/reads to www.example.org
[email protected]ff98d7f02012-03-22 21:44:192459 scoped_ptr<SpdyFrame> req(
[email protected]745aa9c2014-06-27 02:21:292460 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
[email protected]513963e2013-06-15 01:53:042461 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002462 scoped_ptr<SpdyFrame> rep(spdy_util_.ConstructSpdyPush(
2463 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str(),
2464 "301 Moved Permanently", "http://www.foo.com/index.php"));
[email protected]513963e2013-06-15 01:53:042465 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c10b20852013-05-15 21:29:202466 scoped_ptr<SpdyFrame> rst(
2467 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
[email protected]3a8d6852011-03-11 23:43:442468 MockWrite writes[] = {
2469 CreateMockWrite(*req, 1),
2470 CreateMockWrite(*rst, 6),
2471 };
2472 MockRead reads[] = {
2473 CreateMockRead(*resp, 2),
2474 CreateMockRead(*rep, 3),
2475 CreateMockRead(*body, 4),
[email protected]8ddf8322012-02-23 18:08:062476 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
2477 MockRead(ASYNC, 0, 0, 7) // EOF
[email protected]3a8d6852011-03-11 23:43:442478 };
2479
2480 // Setup writes/reads to www.foo.com
[email protected]513963e2013-06-15 01:53:042481 scoped_ptr<SpdyHeaderBlock> headers2(
2482 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2483 (*headers2)["user-agent"] = "";
jgraettinger8f00db8b2014-09-24 23:00:062484 (*headers2)["accept-encoding"] = "gzip, deflate";
[email protected]ff98d7f02012-03-22 21:44:192485 scoped_ptr<SpdyFrame> req2(
[email protected]745aa9c2014-06-27 02:21:292486 spdy_util_.ConstructSpdySyn(1, *headers2, LOWEST, false, true));
[email protected]513963e2013-06-15 01:53:042487 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2488 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582489 MockWrite writes2[] = {
2490 CreateMockWrite(*req2, 1),
2491 };
2492 MockRead reads2[] = {
2493 CreateMockRead(*resp2, 2),
2494 CreateMockRead(*body2, 3),
[email protected]8ddf8322012-02-23 18:08:062495 MockRead(ASYNC, 0, 0, 5) // EOF
[email protected]e3ebba0f2010-08-05 17:59:582496 };
rch73e17422015-05-04 19:52:062497 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
2498 SequencedSocketData data2(reads2, arraysize(reads2), writes2,
2499 arraysize(writes2));
[email protected]e3ebba0f2010-08-05 17:59:582500
2501 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
[email protected]e3ebba0f2010-08-05 17:59:582502 TestDelegate d;
2503 TestDelegate d2;
rchebf12982015-04-10 01:15:002504 SpdyURLRequestContext spdy_url_request_context(GetParam().protocol);
[email protected]e3ebba0f2010-08-05 17:59:582505 {
davidben151423e2015-03-23 18:48:362506 scoped_ptr<URLRequest> r(spdy_url_request_context.CreateRequest(
rchebf12982015-04-10 01:15:002507 GURL(GetDefaultUrl()), DEFAULT_PRIORITY, &d));
[email protected]ef2bf422012-05-11 03:27:092508 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572509 AddSocketDataProvider(&data);
[email protected]e3ebba0f2010-08-05 17:59:582510
[email protected]f7022f32014-08-21 16:32:192511 r->Start();
[email protected]fc9d88472013-08-14 02:31:172512 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582513
2514 EXPECT_EQ(0, d.received_redirect_count());
2515 std::string contents("hello!");
2516 EXPECT_EQ(contents, d.data_received());
2517
davidben151423e2015-03-23 18:48:362518 scoped_ptr<URLRequest> r2(spdy_url_request_context.CreateRequest(
rchebf12982015-04-10 01:15:002519 GURL(GetDefaultUrlWithPath("/foo.dat")), DEFAULT_PRIORITY, &d2));
[email protected]ef2bf422012-05-11 03:27:092520 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572521 AddSocketDataProvider(&data2);
[email protected]e3ebba0f2010-08-05 17:59:582522
2523 d2.set_quit_on_redirect(true);
[email protected]f7022f32014-08-21 16:32:192524 r2->Start();
[email protected]fc9d88472013-08-14 02:31:172525 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582526 EXPECT_EQ(1, d2.received_redirect_count());
2527
[email protected]f7022f32014-08-21 16:32:192528 r2->FollowDeferredRedirect();
[email protected]fc9d88472013-08-14 02:31:172529 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582530 EXPECT_EQ(1, d2.response_started_count());
2531 EXPECT_FALSE(d2.received_data_before_response());
bnc301745a2015-03-10 03:22:162532 EXPECT_EQ(URLRequestStatus::SUCCESS, r2->status().status());
[email protected]e3ebba0f2010-08-05 17:59:582533 std::string contents2("hello!");
2534 EXPECT_EQ(contents2, d2.data_received());
2535 }
rchbce10d972015-05-04 18:21:192536 EXPECT_TRUE(data.AllReadDataConsumed());
2537 EXPECT_TRUE(data.AllWriteDataConsumed());
2538 EXPECT_TRUE(data2.AllReadDataConsumed());
2539 EXPECT_TRUE(data2.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582540}
2541
[email protected]513963e2013-06-15 01:53:042542TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
[email protected]cdf8f7e72013-05-23 10:56:462543 scoped_ptr<SpdyFrame> stream1_syn(
2544 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042545 scoped_ptr<SpdyFrame> stream1_body(
2546 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582547 MockWrite writes[] = {
rch73e17422015-05-04 19:52:062548 CreateMockWrite(*stream1_syn, 0),
[email protected]e3ebba0f2010-08-05 17:59:582549 };
2550
[email protected]ff98d7f02012-03-22 21:44:192551 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042552 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002553 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2554 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432555 const char kPushedData[] = "pushed";
2556 scoped_ptr<SpdyFrame> stream2_body(
2557 spdy_util_.ConstructSpdyBodyFrame(
2558 2, kPushedData, strlen(kPushedData), true));
[email protected]e3ebba0f2010-08-05 17:59:582559 MockRead reads[] = {
rch73e17422015-05-04 19:52:062560 CreateMockRead(*stream1_reply, 1),
2561 CreateMockRead(*stream2_syn, 2),
2562 CreateMockRead(*stream1_body, 3, SYNCHRONOUS),
2563 CreateMockRead(*stream2_body, 4),
2564 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582565 };
2566
2567 HttpResponseInfo response;
2568 HttpResponseInfo response2;
[email protected]19ec8a72010-08-23 03:38:232569 std::string expected_push_result("pushed");
rch73e17422015-05-04 19:52:062570 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572571 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:032572 &response,
2573 &response2,
2574 expected_push_result);
[email protected]e3ebba0f2010-08-05 17:59:582575
2576 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502577 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]e3ebba0f2010-08-05 17:59:582578 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2579
2580 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502581 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]e3ebba0f2010-08-05 17:59:582582 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2583}
2584
[email protected]513963e2013-06-15 01:53:042585TEST_P(SpdyNetworkTransactionTest, ServerPushBeforeSynReply) {
[email protected]cdf8f7e72013-05-23 10:56:462586 scoped_ptr<SpdyFrame> stream1_syn(
2587 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042588 scoped_ptr<SpdyFrame> stream1_body(
2589 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]a5b8eb29d2012-03-06 06:19:462590 MockWrite writes[] = {
rch73e17422015-05-04 19:52:062591 CreateMockWrite(*stream1_syn, 0),
[email protected]a5b8eb29d2012-03-06 06:19:462592 };
2593
[email protected]ff98d7f02012-03-22 21:44:192594 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042595 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002596 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2597 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432598 const char kPushedData[] = "pushed";
2599 scoped_ptr<SpdyFrame> stream2_body(
2600 spdy_util_.ConstructSpdyBodyFrame(
2601 2, kPushedData, strlen(kPushedData), true));
[email protected]a5b8eb29d2012-03-06 06:19:462602 MockRead reads[] = {
rch73e17422015-05-04 19:52:062603 CreateMockRead(*stream2_syn, 1),
2604 CreateMockRead(*stream1_reply, 2),
2605 CreateMockRead(*stream1_body, 3, SYNCHRONOUS),
2606 CreateMockRead(*stream2_body, 4),
2607 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]a5b8eb29d2012-03-06 06:19:462608 };
2609
2610 HttpResponseInfo response;
2611 HttpResponseInfo response2;
2612 std::string expected_push_result("pushed");
rch73e17422015-05-04 19:52:062613 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572614 RunServerPushTest(&data,
[email protected]a5b8eb29d2012-03-06 06:19:462615 &response,
2616 &response2,
2617 expected_push_result);
2618
2619 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502620 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]a5b8eb29d2012-03-06 06:19:462621 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2622
2623 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502624 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]a5b8eb29d2012-03-06 06:19:462625 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2626}
2627
[email protected]513963e2013-06-15 01:53:042628TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
[email protected]cdf8f7e72013-05-23 10:56:462629 scoped_ptr<SpdyFrame> stream1_syn(
2630 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch73e17422015-05-04 19:52:062631 MockWrite writes[] = {
2632 CreateMockWrite(*stream1_syn, 0),
2633 };
[email protected]82918cc2010-08-25 17:24:502634
[email protected]ff98d7f02012-03-22 21:44:192635 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042636 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002637 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2638 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432639 const char kPushedData[] = "pushed";
2640 scoped_ptr<SpdyFrame> stream2_body(
2641 spdy_util_.ConstructSpdyBodyFrame(
2642 2, kPushedData, strlen(kPushedData), true));
[email protected]ff98d7f02012-03-22 21:44:192643 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042644 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]82918cc2010-08-25 17:24:502645 MockRead reads[] = {
rch73e17422015-05-04 19:52:062646 CreateMockRead(*stream1_reply, 1),
2647 CreateMockRead(*stream2_syn, 2),
2648 CreateMockRead(*stream2_body, 3),
2649 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2650 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]82918cc2010-08-25 17:24:502651 };
2652
2653 HttpResponseInfo response;
2654 HttpResponseInfo response2;
2655 std::string expected_push_result("pushed");
rch73e17422015-05-04 19:52:062656 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572657 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:032658 &response,
2659 &response2,
2660 expected_push_result);
[email protected]82918cc2010-08-25 17:24:502661
2662 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502663 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]82918cc2010-08-25 17:24:502664 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2665
2666 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502667 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]82918cc2010-08-25 17:24:502668 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2669}
2670
[email protected]513963e2013-06-15 01:53:042671TEST_P(SpdyNetworkTransactionTest, ServerPushServerAborted) {
[email protected]cdf8f7e72013-05-23 10:56:462672 scoped_ptr<SpdyFrame> stream1_syn(
2673 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042674 scoped_ptr<SpdyFrame> stream1_body(
2675 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582676 MockWrite writes[] = {
rch73e17422015-05-04 19:52:062677 CreateMockWrite(*stream1_syn, 0),
[email protected]e3ebba0f2010-08-05 17:59:582678 };
2679
[email protected]ff98d7f02012-03-22 21:44:192680 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042681 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002682 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2683 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]c10b20852013-05-15 21:29:202684 scoped_ptr<SpdyFrame> stream2_rst(
2685 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
[email protected]e3ebba0f2010-08-05 17:59:582686 MockRead reads[] = {
rch73e17422015-05-04 19:52:062687 CreateMockRead(*stream1_reply, 1),
2688 CreateMockRead(*stream2_syn, 2),
2689 CreateMockRead(*stream2_rst, 3),
2690 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2691 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582692 };
2693
rch73e17422015-05-04 19:52:062694 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362695 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502696 BoundNetLog(), GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:582697
2698 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572699 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:582700
2701 HttpNetworkTransaction* trans = helper.trans();
2702
2703 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412704 TestCompletionCallback callback;
2705 int rv = trans->Start(
2706 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]e3ebba0f2010-08-05 17:59:582707 EXPECT_EQ(ERR_IO_PENDING, rv);
2708 rv = callback.WaitForResult();
[email protected]19ec8a72010-08-23 03:38:232709 EXPECT_EQ(OK, rv);
2710
2711 // Verify that we consumed all test data.
rch73e17422015-05-04 19:52:062712 EXPECT_TRUE(data.AllReadDataConsumed());
2713 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]19ec8a72010-08-23 03:38:232714
2715 // Verify the SYN_REPLY.
2716 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:502717 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]19ec8a72010-08-23 03:38:232718 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2719}
2720
[email protected]8a0fc822013-06-27 20:52:432721// Verify that we don't leak streams and that we properly send a reset
2722// if the server pushes the same stream twice.
[email protected]513963e2013-06-15 01:53:042723TEST_P(SpdyNetworkTransactionTest, ServerPushDuplicate) {
[email protected]cdf8f7e72013-05-23 10:56:462724 scoped_ptr<SpdyFrame> stream1_syn(
2725 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042726 scoped_ptr<SpdyFrame> stream1_body(
2727 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c10b20852013-05-15 21:29:202728 scoped_ptr<SpdyFrame> stream3_rst(
2729 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR));
[email protected]fdc165a2010-09-03 03:51:292730 MockWrite writes[] = {
rch73e17422015-05-04 19:52:062731 CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*stream3_rst, 4),
[email protected]fdc165a2010-09-03 03:51:292732 };
2733
[email protected]ff98d7f02012-03-22 21:44:192734 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042735 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002736 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2737 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432738 const char kPushedData[] = "pushed";
2739 scoped_ptr<SpdyFrame> stream2_body(
2740 spdy_util_.ConstructSpdyBodyFrame(
2741 2, kPushedData, strlen(kPushedData), true));
rchebf12982015-04-10 01:15:002742 scoped_ptr<SpdyFrame> stream3_syn(spdy_util_.ConstructSpdyPush(
2743 NULL, 0, 4, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]fdc165a2010-09-03 03:51:292744 MockRead reads[] = {
rch73e17422015-05-04 19:52:062745 CreateMockRead(*stream1_reply, 1),
2746 CreateMockRead(*stream2_syn, 2),
2747 CreateMockRead(*stream3_syn, 3),
2748 CreateMockRead(*stream1_body, 5),
2749 CreateMockRead(*stream2_body, 6),
2750 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 7), // Force a pause
[email protected]fdc165a2010-09-03 03:51:292751 };
2752
2753 HttpResponseInfo response;
2754 HttpResponseInfo response2;
2755 std::string expected_push_result("pushed");
rch73e17422015-05-04 19:52:062756 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:572757 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:032758 &response,
2759 &response2,
2760 expected_push_result);
[email protected]fdc165a2010-09-03 03:51:292761
2762 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502763 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]fdc165a2010-09-03 03:51:292764 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2765
2766 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502767 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]fdc165a2010-09-03 03:51:292768 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2769}
2770
[email protected]513963e2013-06-15 01:53:042771TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
[email protected]cdf8f7e72013-05-23 10:56:462772 scoped_ptr<SpdyFrame> stream1_syn(
2773 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042774 scoped_ptr<SpdyFrame> stream1_body(
2775 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]19ec8a72010-08-23 03:38:232776 MockWrite writes[] = {
rch73e17422015-05-04 19:52:062777 CreateMockWrite(*stream1_syn, 0),
[email protected]19ec8a72010-08-23 03:38:232778 };
2779
[email protected]ff98d7f02012-03-22 21:44:192780 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042781 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002782 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2783 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432784 static const char kPushedData[] = "pushed my darling hello my baby";
2785 scoped_ptr<SpdyFrame> stream2_body_base(
2786 spdy_util_.ConstructSpdyBodyFrame(
2787 2, kPushedData, strlen(kPushedData), true));
2788 const size_t kChunkSize = strlen(kPushedData) / 4;
2789 scoped_ptr<SpdyFrame> stream2_body1(
2790 new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
2791 scoped_ptr<SpdyFrame> stream2_body2(
2792 new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
2793 scoped_ptr<SpdyFrame> stream2_body3(
2794 new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
2795 kChunkSize, false));
2796 scoped_ptr<SpdyFrame> stream2_body4(
2797 new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
2798 stream2_body_base->size() - 3 * kChunkSize, false));
[email protected]19ec8a72010-08-23 03:38:232799 MockRead reads[] = {
rch73e17422015-05-04 19:52:062800 CreateMockRead(*stream1_reply, 1),
2801 CreateMockRead(*stream2_syn, 2),
2802 CreateMockRead(*stream2_body1, 3),
2803 CreateMockRead(*stream2_body2, 4),
2804 CreateMockRead(*stream2_body3, 5),
2805 CreateMockRead(*stream2_body4, 6),
2806 CreateMockRead(*stream1_body, 7, SYNCHRONOUS),
2807 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8), // Force a pause
[email protected]19ec8a72010-08-23 03:38:232808 };
2809
2810 HttpResponseInfo response;
2811 HttpResponseInfo response2;
2812 std::string expected_push_result("pushed my darling hello my baby");
rch73e17422015-05-04 19:52:062813 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8a0fc822013-06-27 20:52:432814 RunServerPushTest(&data, &response, &response2, kPushedData);
[email protected]19ec8a72010-08-23 03:38:232815
2816 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502817 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]19ec8a72010-08-23 03:38:232818 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2819
2820 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502821 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]19ec8a72010-08-23 03:38:232822 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2823}
2824
[email protected]513963e2013-06-15 01:53:042825TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
[email protected]cdf8f7e72013-05-23 10:56:462826 scoped_ptr<SpdyFrame> stream1_syn(
2827 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042828 scoped_ptr<SpdyFrame> stream1_body(
2829 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]19ec8a72010-08-23 03:38:232830 MockWrite writes[] = {
rch73e17422015-05-04 19:52:062831 CreateMockWrite(*stream1_syn, 0),
[email protected]19ec8a72010-08-23 03:38:232832 };
2833
[email protected]ff98d7f02012-03-22 21:44:192834 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042835 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002836 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2837 NULL, 0, 2, 1, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]8a0fc822013-06-27 20:52:432838 static const char kPushedData[] = "pushed my darling hello my baby";
2839 scoped_ptr<SpdyFrame> stream2_body_base(
2840 spdy_util_.ConstructSpdyBodyFrame(
2841 2, kPushedData, strlen(kPushedData), true));
2842 const size_t kChunkSize = strlen(kPushedData) / 4;
2843 scoped_ptr<SpdyFrame> stream2_body1(
2844 new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
2845 scoped_ptr<SpdyFrame> stream2_body2(
2846 new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
2847 scoped_ptr<SpdyFrame> stream2_body3(
2848 new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
2849 kChunkSize, false));
2850 scoped_ptr<SpdyFrame> stream2_body4(
2851 new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
2852 stream2_body_base->size() - 3 * kChunkSize, false));
[email protected]19ec8a72010-08-23 03:38:232853 MockRead reads[] = {
rch73e17422015-05-04 19:52:062854 CreateMockRead(*stream1_reply, 1),
2855 CreateMockRead(*stream2_syn, 2),
2856 CreateMockRead(*stream2_body1, 3),
2857 CreateMockRead(*stream2_body2, 4),
2858 CreateMockRead(*stream2_body3, 5),
2859 CreateMockRead(*stream2_body4, 6),
2860 CreateMockRead(*stream1_body.get(), 7, SYNCHRONOUS),
2861 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8) // Force a pause.
[email protected]19ec8a72010-08-23 03:38:232862 };
2863
2864 HttpResponseInfo response;
2865 HttpResponseInfo response2;
rch73e17422015-05-04 19:52:062866 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8a0fc822013-06-27 20:52:432867 RunServerPushTest(&data, &response, &response2, kPushedData);
[email protected]19ec8a72010-08-23 03:38:232868
2869 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502870 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]19ec8a72010-08-23 03:38:232871 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2872
2873 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502874 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]19ec8a72010-08-23 03:38:232875 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2876}
2877
[email protected]513963e2013-06-15 01:53:042878TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
[email protected]00b29472014-01-16 18:10:242879 if (spdy_util_.spdy_version() == SPDY4) {
[email protected]0338bc62014-06-20 17:09:562880 // PUSH_PROMISE with stream id 0 is connection-level error.
2881 // TODO(baranovich): Test session going away.
[email protected]00b29472014-01-16 18:10:242882 return;
2883 }
[email protected]0338bc62014-06-20 17:09:562884
[email protected]cdf8f7e72013-05-23 10:56:462885 scoped_ptr<SpdyFrame> stream1_syn(
2886 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042887 scoped_ptr<SpdyFrame> stream1_body(
2888 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c10b20852013-05-15 21:29:202889 scoped_ptr<SpdyFrame> stream2_rst(
2890 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
[email protected]19ec8a72010-08-23 03:38:232891 MockWrite writes[] = {
rch73e17422015-05-04 19:52:062892 CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*stream2_rst, 3),
[email protected]19ec8a72010-08-23 03:38:232893 };
2894
[email protected]ff98d7f02012-03-22 21:44:192895 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042896 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002897 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2898 NULL, 0, 2, 0, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]19ec8a72010-08-23 03:38:232899 MockRead reads[] = {
rch73e17422015-05-04 19:52:062900 CreateMockRead(*stream1_reply, 1),
2901 CreateMockRead(*stream2_syn, 2),
2902 CreateMockRead(*stream1_body, 4),
2903 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5) // Force a pause
[email protected]19ec8a72010-08-23 03:38:232904 };
2905
rch73e17422015-05-04 19:52:062906 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362907 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502908 BoundNetLog(), GetParam(), NULL);
[email protected]19ec8a72010-08-23 03:38:232909
2910 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572911 helper.AddData(&data);
[email protected]19ec8a72010-08-23 03:38:232912
2913 HttpNetworkTransaction* trans = helper.trans();
2914
2915 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412916 TestCompletionCallback callback;
2917 int rv = trans->Start(
2918 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]19ec8a72010-08-23 03:38:232919 EXPECT_EQ(ERR_IO_PENDING, rv);
2920 rv = callback.WaitForResult();
[email protected]e3ebba0f2010-08-05 17:59:582921 EXPECT_EQ(OK, rv);
2922
2923 // Verify that we consumed all test data.
rch73e17422015-05-04 19:52:062924 EXPECT_TRUE(data.AllReadDataConsumed());
2925 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582926
2927 // Verify the SYN_REPLY.
2928 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:502929 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]e3ebba0f2010-08-05 17:59:582930 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2931}
2932
[email protected]513963e2013-06-15 01:53:042933TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
[email protected]cdf8f7e72013-05-23 10:56:462934 scoped_ptr<SpdyFrame> stream1_syn(
2935 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042936 scoped_ptr<SpdyFrame> stream1_body(
2937 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c10b20852013-05-15 21:29:202938 scoped_ptr<SpdyFrame> stream2_rst(
2939 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM));
[email protected]e3ebba0f2010-08-05 17:59:582940 MockWrite writes[] = {
rch73e17422015-05-04 19:52:062941 CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*stream2_rst, 3),
[email protected]e3ebba0f2010-08-05 17:59:582942 };
2943
[email protected]ff98d7f02012-03-22 21:44:192944 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042945 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
rchebf12982015-04-10 01:15:002946 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructSpdyPush(
2947 NULL, 0, 2, 9, GetDefaultUrlWithPath("/foo.dat").c_str()));
[email protected]e3ebba0f2010-08-05 17:59:582948 MockRead reads[] = {
rch73e17422015-05-04 19:52:062949 CreateMockRead(*stream1_reply, 1),
2950 CreateMockRead(*stream2_syn, 2),
2951 CreateMockRead(*stream1_body, 4),
2952 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582953 };
2954
rch73e17422015-05-04 19:52:062955 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362956 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502957 BoundNetLog(), GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:582958
2959 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572960 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:582961
2962 HttpNetworkTransaction* trans = helper.trans();
2963
2964 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412965 TestCompletionCallback callback;
2966 int rv = trans->Start(
2967 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]e3ebba0f2010-08-05 17:59:582968 EXPECT_EQ(ERR_IO_PENDING, rv);
2969 rv = callback.WaitForResult();
[email protected]e3ebba0f2010-08-05 17:59:582970 EXPECT_EQ(OK, rv);
2971
2972 // Verify that we consumed all test data.
rch73e17422015-05-04 19:52:062973 EXPECT_TRUE(data.AllReadDataConsumed());
2974 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:582975
2976 // Verify the SYN_REPLY.
2977 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:502978 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]e3ebba0f2010-08-05 17:59:582979 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2980}
2981
[email protected]513963e2013-06-15 01:53:042982TEST_P(SpdyNetworkTransactionTest, ServerPushNoURL) {
[email protected]cdf8f7e72013-05-23 10:56:462983 scoped_ptr<SpdyFrame> stream1_syn(
2984 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042985 scoped_ptr<SpdyFrame> stream1_body(
2986 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c10b20852013-05-15 21:29:202987 scoped_ptr<SpdyFrame> stream2_rst(
2988 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
[email protected]e3ebba0f2010-08-05 17:59:582989 MockWrite writes[] = {
rch73e17422015-05-04 19:52:062990 CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*stream2_rst, 3),
[email protected]e3ebba0f2010-08-05 17:59:582991 };
2992
[email protected]ff98d7f02012-03-22 21:44:192993 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042994 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8b9211d2013-06-24 05:54:452995 scoped_ptr<SpdyHeaderBlock> incomplete_headers(new SpdyHeaderBlock());
2996 (*incomplete_headers)["hello"] = "bye";
2997 (*incomplete_headers)[spdy_util_.GetStatusKey()] = "200 OK";
2998 (*incomplete_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
[email protected]0338bc62014-06-20 17:09:562999 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
3000 incomplete_headers.Pass(), 2, 1));
[email protected]e3ebba0f2010-08-05 17:59:583001 MockRead reads[] = {
rch73e17422015-05-04 19:52:063002 CreateMockRead(*stream1_reply, 1),
3003 CreateMockRead(*stream2_syn, 2),
3004 CreateMockRead(*stream1_body, 4),
3005 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5) // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:583006 };
3007
rch73e17422015-05-04 19:52:063008 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:363009 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503010 BoundNetLog(), GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:583011
3012 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573013 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:583014
3015 HttpNetworkTransaction* trans = helper.trans();
3016
3017 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:413018 TestCompletionCallback callback;
3019 int rv = trans->Start(
3020 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]e3ebba0f2010-08-05 17:59:583021 EXPECT_EQ(ERR_IO_PENDING, rv);
3022 rv = callback.WaitForResult();
[email protected]e3ebba0f2010-08-05 17:59:583023 EXPECT_EQ(OK, rv);
rch73e17422015-05-04 19:52:063024
[email protected]e3ebba0f2010-08-05 17:59:583025 // Verify that we consumed all test data.
rch73e17422015-05-04 19:52:063026 EXPECT_TRUE(data.AllReadDataConsumed());
3027 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]e3ebba0f2010-08-05 17:59:583028
3029 // Verify the SYN_REPLY.
3030 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503031 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]e3ebba0f2010-08-05 17:59:583032 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3033}
3034
[email protected]8b070372009-11-16 22:01:253035// Verify that various SynReply headers parse correctly through the
3036// HTTP layer.
[email protected]513963e2013-06-15 01:53:043037TEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) {
[email protected]e7f75092010-07-01 22:39:133038 struct SynReplyHeadersTests {
3039 int num_headers;
3040 const char* extra_headers[5];
[email protected]513963e2013-06-15 01:53:043041 SpdyHeaderBlock expected_headers;
[email protected]8b070372009-11-16 22:01:253042 } test_cases[] = {
[email protected]e7f75092010-07-01 22:39:133043 // This uses a multi-valued cookie header.
3044 { 2,
3045 { "cookie", "val1",
3046 "cookie", "val2", // will get appended separated by NULL
3047 NULL
3048 },
[email protected]8b070372009-11-16 22:01:253049 },
[email protected]e7f75092010-07-01 22:39:133050 // This is the minimalist set of headers.
3051 { 0,
3052 { NULL },
[email protected]8b070372009-11-16 22:01:253053 },
[email protected]e7f75092010-07-01 22:39:133054 // Headers with a comma separated list.
3055 { 1,
3056 { "cookie", "val1,val2",
3057 NULL
3058 },
[email protected]8b070372009-11-16 22:01:253059 }
3060 };
3061
[email protected]513963e2013-06-15 01:53:043062 test_cases[0].expected_headers["cookie"] = "val1";
3063 test_cases[0].expected_headers["cookie"] += '\0';
3064 test_cases[0].expected_headers["cookie"] += "val2";
3065 test_cases[0].expected_headers["hello"] = "bye";
3066 test_cases[0].expected_headers["status"] = "200";
[email protected]513963e2013-06-15 01:53:043067
3068 test_cases[1].expected_headers["hello"] = "bye";
3069 test_cases[1].expected_headers["status"] = "200";
[email protected]513963e2013-06-15 01:53:043070
3071 test_cases[2].expected_headers["cookie"] = "val1,val2";
3072 test_cases[2].expected_headers["hello"] = "bye";
3073 test_cases[2].expected_headers["status"] = "200";
[email protected]601e03f12014-04-06 16:26:393074
3075 if (spdy_util_.spdy_version() < SPDY4) {
3076 // SPDY4/HTTP2 eliminates use of the :version header.
3077 test_cases[0].expected_headers["version"] = "HTTP/1.1";
3078 test_cases[1].expected_headers["version"] = "HTTP/1.1";
3079 test_cases[2].expected_headers["version"] = "HTTP/1.1";
3080 }
[email protected]513963e2013-06-15 01:53:043081
viettrungluue4a8b882014-10-16 06:17:383082 for (size_t i = 0; i < arraysize(test_cases); ++i) {
[email protected]ff98d7f02012-03-22 21:44:193083 scoped_ptr<SpdyFrame> req(
[email protected]cdf8f7e72013-05-23 10:56:463084 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch73e17422015-05-04 19:52:063085 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]8b070372009-11-16 22:01:253086
[email protected]ff98d7f02012-03-22 21:44:193087 scoped_ptr<SpdyFrame> resp(
[email protected]513963e2013-06-15 01:53:043088 spdy_util_.ConstructSpdyGetSynReply(test_cases[i].extra_headers,
[email protected]2bd93022010-07-17 00:58:443089 test_cases[i].num_headers,
3090 1));
[email protected]513963e2013-06-15 01:53:043091 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]8b070372009-11-16 22:01:253092 MockRead reads[] = {
rch73e17422015-05-04 19:52:063093 CreateMockRead(*resp, 1),
3094 CreateMockRead(*body, 2),
3095 MockRead(ASYNC, 0, 3) // EOF
[email protected]8b070372009-11-16 22:01:253096 };
3097
rch73e17422015-05-04 19:52:063098 SequencedSocketData data(reads, arraysize(reads), writes,
3099 arraysize(writes));
[email protected]262eec82013-03-19 21:01:363100 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503101 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573102 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473103 TransactionHelperResult out = helper.output();
3104
[email protected]8b070372009-11-16 22:01:253105 EXPECT_EQ(OK, out.rv);
3106 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3107 EXPECT_EQ("hello!", out.response_data);
3108
3109 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3110 EXPECT_TRUE(headers.get() != NULL);
3111 void* iter = NULL;
[email protected]513963e2013-06-15 01:53:043112 std::string name, value;
3113 SpdyHeaderBlock header_block;
[email protected]8b070372009-11-16 22:01:253114 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
[email protected]513963e2013-06-15 01:53:043115 if (header_block[name].empty()) {
3116 header_block[name] = value;
3117 } else {
3118 header_block[name] += '\0';
3119 header_block[name] += value;
3120 }
[email protected]8b070372009-11-16 22:01:253121 }
[email protected]513963e2013-06-15 01:53:043122 EXPECT_EQ(test_cases[i].expected_headers, header_block);
[email protected]8b070372009-11-16 22:01:253123 }
3124}
3125
[email protected]3f662f12010-03-25 19:56:123126// Verify that various SynReply headers parse vary fields correctly
3127// through the HTTP layer, and the response matches the request.
[email protected]513963e2013-06-15 01:53:043128TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) {
[email protected]3f662f12010-03-25 19:56:123129 // Modify the following data to change/add test cases:
3130 struct SynReplyTests {
[email protected]3f662f12010-03-25 19:56:123131 bool vary_matches;
3132 int num_headers[2];
3133 const char* extra_headers[2][16];
3134 } test_cases[] = {
3135 // Test the case of a multi-valued cookie. When the value is delimited
3136 // with NUL characters, it needs to be unfolded into multiple headers.
3137 {
[email protected]3f662f12010-03-25 19:56:123138 true,
[email protected]8c76ae22010-04-20 22:15:433139 { 1, 4 },
3140 { { "cookie", "val1,val2",
[email protected]3f662f12010-03-25 19:56:123141 NULL
3142 },
[email protected]513963e2013-06-15 01:53:043143 { "vary", "cookie",
3144 spdy_util_.GetStatusKey(), "200",
3145 spdy_util_.GetPathKey(), "/index.php",
3146 spdy_util_.GetVersionKey(), "HTTP/1.1",
[email protected]3f662f12010-03-25 19:56:123147 NULL
3148 }
3149 }
3150 }, { // Multiple vary fields.
[email protected]3f662f12010-03-25 19:56:123151 true,
3152 { 2, 5 },
3153 { { "friend", "barney",
3154 "enemy", "snaggletooth",
3155 NULL
3156 },
[email protected]513963e2013-06-15 01:53:043157 { "vary", "friend",
[email protected]3f662f12010-03-25 19:56:123158 "vary", "enemy",
[email protected]513963e2013-06-15 01:53:043159 spdy_util_.GetStatusKey(), "200",
3160 spdy_util_.GetPathKey(), "/index.php",
3161 spdy_util_.GetVersionKey(), "HTTP/1.1",
[email protected]3f662f12010-03-25 19:56:123162 NULL
3163 }
3164 }
3165 }, { // Test a '*' vary field.
[email protected]3f662f12010-03-25 19:56:123166 false,
3167 { 1, 4 },
3168 { { "cookie", "val1,val2",
3169 NULL
3170 },
[email protected]513963e2013-06-15 01:53:043171 { "vary", "*",
3172 spdy_util_.GetStatusKey(), "200",
3173 spdy_util_.GetPathKey(), "/index.php",
3174 spdy_util_.GetVersionKey(), "HTTP/1.1",
[email protected]3f662f12010-03-25 19:56:123175 NULL
3176 }
3177 }
3178 }, { // Multiple comma-separated vary fields.
[email protected]3f662f12010-03-25 19:56:123179 true,
3180 { 2, 4 },
3181 { { "friend", "barney",
3182 "enemy", "snaggletooth",
3183 NULL
3184 },
[email protected]513963e2013-06-15 01:53:043185 { "vary", "friend,enemy",
3186 spdy_util_.GetStatusKey(), "200",
3187 spdy_util_.GetPathKey(), "/index.php",
3188 spdy_util_.GetVersionKey(), "HTTP/1.1",
[email protected]3f662f12010-03-25 19:56:123189 NULL
3190 }
3191 }
3192 }
3193 };
3194
viettrungluue4a8b882014-10-16 06:17:383195 for (size_t i = 0; i < arraysize(test_cases); ++i) {
[email protected]3f662f12010-03-25 19:56:123196 // Construct the request.
[email protected]ff98d7f02012-03-22 21:44:193197 scoped_ptr<SpdyFrame> frame_req(
[email protected]cdf8f7e72013-05-23 10:56:463198 spdy_util_.ConstructSpdyGet(test_cases[i].extra_headers[0],
3199 test_cases[i].num_headers[0],
3200 false, 1, LOWEST, true));
[email protected]3f662f12010-03-25 19:56:123201
3202 MockWrite writes[] = {
rch73e17422015-05-04 19:52:063203 CreateMockWrite(*frame_req, 0),
[email protected]3f662f12010-03-25 19:56:123204 };
3205
3206 // Construct the reply.
[email protected]745aa9c2014-06-27 02:21:293207 SpdyHeaderBlock reply_headers;
3208 AppendToHeaderBlock(test_cases[i].extra_headers[1],
3209 test_cases[i].num_headers[1],
3210 &reply_headers);
[email protected]ff98d7f02012-03-22 21:44:193211 scoped_ptr<SpdyFrame> frame_reply(
[email protected]745aa9c2014-06-27 02:21:293212 spdy_util_.ConstructSpdyReply(1, reply_headers));
[email protected]3f662f12010-03-25 19:56:123213
[email protected]513963e2013-06-15 01:53:043214 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]3f662f12010-03-25 19:56:123215 MockRead reads[] = {
rch73e17422015-05-04 19:52:063216 CreateMockRead(*frame_reply, 1),
3217 CreateMockRead(*body, 2),
3218 MockRead(ASYNC, 0, 3) // EOF
[email protected]3f662f12010-03-25 19:56:123219 };
3220
[email protected]3f662f12010-03-25 19:56:123221 // Attach the headers to the request.
[email protected]8c76ae22010-04-20 22:15:433222 int header_count = test_cases[i].num_headers[0];
[email protected]3f662f12010-03-25 19:56:123223
[email protected]d3cee19d2010-06-22 18:42:183224 HttpRequestInfo request = CreateGetRequest();
[email protected]8c76ae22010-04-20 22:15:433225 for (int ct = 0; ct < header_count; ct++) {
3226 const char* header_key = test_cases[i].extra_headers[0][ct * 2];
3227 const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1];
3228 request.extra_headers.SetHeader(header_key, header_value);
[email protected]3f662f12010-03-25 19:56:123229 }
3230
rch73e17422015-05-04 19:52:063231 SequencedSocketData data(reads, arraysize(reads), writes,
3232 arraysize(writes));
[email protected]262eec82013-03-19 21:01:363233 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503234 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573235 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473236 TransactionHelperResult out = helper.output();
3237
[email protected]3f662f12010-03-25 19:56:123238 EXPECT_EQ(OK, out.rv) << i;
3239 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line) << i;
3240 EXPECT_EQ("hello!", out.response_data) << i;
3241
3242 // Test the response information.
3243 EXPECT_TRUE(out.response_info.response_time >
3244 out.response_info.request_time) << i;
3245 base::TimeDelta test_delay = out.response_info.response_time -
3246 out.response_info.request_time;
3247 base::TimeDelta min_expected_delay;
3248 min_expected_delay.FromMilliseconds(10);
3249 EXPECT_GT(test_delay.InMillisecondsF(),
3250 min_expected_delay.InMillisecondsF()) << i;
3251 EXPECT_EQ(out.response_info.vary_data.is_valid(),
3252 test_cases[i].vary_matches) << i;
3253
3254 // Check the headers.
3255 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3256 ASSERT_TRUE(headers.get() != NULL) << i;
3257 void* iter = NULL;
3258 std::string name, value, lines;
3259 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3260 lines.append(name);
3261 lines.append(": ");
3262 lines.append(value);
3263 lines.append("\n");
3264 }
3265
3266 // Construct the expected header reply string.
[email protected]9aa323192013-05-31 21:38:403267 std::string expected_reply =
3268 spdy_util_.ConstructSpdyReplyString(reply_headers);
3269 EXPECT_EQ(expected_reply, lines) << i;
[email protected]3f662f12010-03-25 19:56:123270 }
3271}
3272
[email protected]dd11b932009-11-30 19:39:483273// Verify that we don't crash on invalid SynReply responses.
[email protected]513963e2013-06-15 01:53:043274TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) {
[email protected]e7f75092010-07-01 22:39:133275 struct InvalidSynReplyTests {
3276 int num_headers;
3277 const char* headers[10];
[email protected]dd11b932009-11-30 19:39:483278 } test_cases[] = {
[email protected]e7f75092010-07-01 22:39:133279 // SYN_REPLY missing status header
3280 { 4,
3281 { "cookie", "val1",
3282 "cookie", "val2",
[email protected]513963e2013-06-15 01:53:043283 spdy_util_.GetPathKey(), "/index.php",
3284 spdy_util_.GetVersionKey(), "HTTP/1.1",
[email protected]e7f75092010-07-01 22:39:133285 NULL
3286 },
3287 },
3288 // SYN_REPLY missing version header
3289 { 2,
[email protected]513963e2013-06-15 01:53:043290 { "status", "200",
3291 spdy_util_.GetPathKey(), "/index.php",
[email protected]e7f75092010-07-01 22:39:133292 NULL
3293 },
3294 },
[email protected]0d384bb2010-07-14 01:51:123295 // SYN_REPLY with no headers
3296 { 0, { NULL }, },
[email protected]dd11b932009-11-30 19:39:483297 };
3298
viettrungluue4a8b882014-10-16 06:17:383299 for (size_t i = 0; i < arraysize(test_cases); ++i) {
[email protected]ff98d7f02012-03-22 21:44:193300 scoped_ptr<SpdyFrame> req(
[email protected]cdf8f7e72013-05-23 10:56:463301 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]b771bb72013-06-24 09:55:413302 scoped_ptr<SpdyFrame> rst(
3303 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
[email protected]dd11b932009-11-30 19:39:483304 MockWrite writes[] = {
rch73e17422015-05-04 19:52:063305 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 2),
[email protected]dd11b932009-11-30 19:39:483306 };
3307
[email protected]745aa9c2014-06-27 02:21:293308 // Construct the reply.
3309 SpdyHeaderBlock reply_headers;
3310 AppendToHeaderBlock(
3311 test_cases[i].headers, test_cases[i].num_headers, &reply_headers);
3312 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyReply(1, reply_headers));
[email protected]dd11b932009-11-30 19:39:483313 MockRead reads[] = {
rch73e17422015-05-04 19:52:063314 CreateMockRead(*resp, 1), MockRead(ASYNC, 0, 3) // EOF
[email protected]dd11b932009-11-30 19:39:483315 };
3316
rch73e17422015-05-04 19:52:063317 SequencedSocketData data(reads, arraysize(reads), writes,
3318 arraysize(writes));
[email protected]262eec82013-03-19 21:01:363319 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503320 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573321 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473322 TransactionHelperResult out = helper.output();
[email protected]b771bb72013-06-24 09:55:413323 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]dd11b932009-11-30 19:39:483324 }
3325}
3326
[email protected]94d78132010-01-22 00:53:003327// Verify that we don't crash on some corrupt frames.
[email protected]e3352df2014-03-19 05:55:423328// TODO(jgraettinger): SPDY4 and up treats a header decompression failure as a
3329// connection error. I'd like to backport this behavior to SPDY3 as well.
[email protected]513963e2013-06-15 01:53:043330TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
[email protected]e3352df2014-03-19 05:55:423331 if (spdy_util_.spdy_version() >= SPDY4) {
3332 return;
3333 }
[email protected]61c83f782011-01-27 21:00:243334 // This is the length field that's too short.
[email protected]ff98d7f02012-03-22 21:44:193335 scoped_ptr<SpdyFrame> syn_reply_wrong_length(
[email protected]513963e2013-06-15 01:53:043336 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:043337 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]8a0fc822013-06-27 20:52:433338 size_t right_size =
3339 (spdy_util_.spdy_version() < SPDY4) ?
3340 syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize() :
3341 syn_reply_wrong_length->size();
3342 size_t wrong_size = right_size - 4;
[email protected]a4bfdf72013-02-22 04:06:163343 test::SetFrameLength(syn_reply_wrong_length.get(),
[email protected]8a0fc822013-06-27 20:52:433344 wrong_size,
[email protected]513963e2013-06-15 01:53:043345 spdy_util_.spdy_version());
[email protected]94d78132010-01-22 00:53:003346
3347 struct SynReplyTests {
[email protected]ff98d7f02012-03-22 21:44:193348 const SpdyFrame* syn_reply;
[email protected]94d78132010-01-22 00:53:003349 } test_cases[] = {
[email protected]61c83f782011-01-27 21:00:243350 { syn_reply_wrong_length.get(), },
[email protected]94d78132010-01-22 00:53:003351 };
3352
viettrungluue4a8b882014-10-16 06:17:383353 for (size_t i = 0; i < arraysize(test_cases); ++i) {
[email protected]ff98d7f02012-03-22 21:44:193354 scoped_ptr<SpdyFrame> req(
[email protected]cdf8f7e72013-05-23 10:56:463355 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]099bc7e2013-07-18 04:19:163356 scoped_ptr<SpdyFrame> rst(
3357 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
3358 MockWrite writes[] = {
rch73e17422015-05-04 19:52:063359 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
[email protected]94d78132010-01-22 00:53:003360 };
3361
[email protected]513963e2013-06-15 01:53:043362 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]94d78132010-01-22 00:53:003363 MockRead reads[] = {
rch73e17422015-05-04 19:52:063364 MockRead(ASYNC, test_cases[i].syn_reply->data(), wrong_size, 1),
3365 CreateMockRead(*body, 2),
3366 MockRead(ASYNC, 0, 4) // EOF
[email protected]94d78132010-01-22 00:53:003367 };
3368
rch73e17422015-05-04 19:52:063369 SequencedSocketData data(reads, arraysize(reads), writes,
3370 arraysize(writes));
[email protected]262eec82013-03-19 21:01:363371 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503372 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573373 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473374 TransactionHelperResult out = helper.output();
[email protected]955fc2e72010-02-08 20:37:303375 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]94d78132010-01-22 00:53:003376 }
3377}
3378
[email protected]e3352df2014-03-19 05:55:423379// SPDY4 treats a header decompression failure as a connection-level error.
3380TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionErrorSpdy4) {
3381 if (spdy_util_.spdy_version() < SPDY4) {
3382 return;
3383 }
3384 // This is the length field that's too short.
3385 scoped_ptr<SpdyFrame> syn_reply_wrong_length(
3386 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3387 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3388 size_t right_size =
[email protected]c143f2742014-03-31 00:48:543389 syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize();
[email protected]e3352df2014-03-19 05:55:423390 size_t wrong_size = right_size - 4;
3391 test::SetFrameLength(syn_reply_wrong_length.get(),
3392 wrong_size,
3393 spdy_util_.spdy_version());
3394
[email protected]e3352df2014-03-19 05:55:423395 scoped_ptr<SpdyFrame> req(
3396 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]bdd1b222014-06-10 11:08:393397 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3398 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
rch73e17422015-05-04 19:52:063399 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2)};
[email protected]e3352df2014-03-19 05:55:423400
3401 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3402 MockRead reads[] = {
rch73e17422015-05-04 19:52:063403 MockRead(ASYNC, syn_reply_wrong_length->data(),
3404 syn_reply_wrong_length->size() - 4, 1),
[email protected]e3352df2014-03-19 05:55:423405 };
3406
rch73e17422015-05-04 19:52:063407 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]e3352df2014-03-19 05:55:423408 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3409 BoundNetLog(), GetParam(), NULL);
3410 helper.RunToCompletion(&data);
3411 TransactionHelperResult out = helper.output();
[email protected]bdd1b222014-06-10 11:08:393412 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
3413}
3414
3415TEST_P(SpdyNetworkTransactionTest, GoAwayOnDecompressionFailure) {
bnc5b3dce0d2014-11-13 19:57:463416 if (GetParam().protocol < kProtoSPDY4MinimumVersion) {
[email protected]bdd1b222014-06-10 11:08:393417 // Decompression failures are a stream error in SPDY3 and above.
3418 return;
3419 }
3420 scoped_ptr<SpdyFrame> req(
3421 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3422 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3423 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
rch73e17422015-05-04 19:52:063424 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2)};
[email protected]bdd1b222014-06-10 11:08:393425
3426 // Read HEADERS with corrupted payload.
3427 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3428 memset(resp->data() + 12, 0xff, resp->size() - 12);
rch73e17422015-05-04 19:52:063429 MockRead reads[] = {CreateMockRead(*resp, 1)};
[email protected]bdd1b222014-06-10 11:08:393430
rch73e17422015-05-04 19:52:063431 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]bdd1b222014-06-10 11:08:393432 NormalSpdyTransactionHelper helper(
3433 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
3434 helper.RunToCompletion(&data);
3435 TransactionHelperResult out = helper.output();
3436 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
3437}
3438
3439TEST_P(SpdyNetworkTransactionTest, GoAwayOnFrameSizeError) {
3440 scoped_ptr<SpdyFrame> req(
3441 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3442 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3443 0, GOAWAY_PROTOCOL_ERROR, "Framer error: 1 (INVALID_CONTROL_FRAME)."));
rch73e17422015-05-04 19:52:063444 MockWrite writes[] = {CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2)};
[email protected]bdd1b222014-06-10 11:08:393445
3446 // Read WINDOW_UPDATE with incorrectly-sized payload.
3447 // TODO(jgraettinger): SpdyFramer signals this as an INVALID_CONTROL_FRAME,
3448 // which is mapped to a protocol error, and not a frame size error.
3449 scoped_ptr<SpdyFrame> bad_window_update(
3450 spdy_util_.ConstructSpdyWindowUpdate(1, 1));
3451 test::SetFrameLength(bad_window_update.get(),
3452 bad_window_update->size() - 1,
3453 spdy_util_.spdy_version());
rch73e17422015-05-04 19:52:063454 MockRead reads[] = {CreateMockRead(*bad_window_update, 1)};
[email protected]bdd1b222014-06-10 11:08:393455
rch73e17422015-05-04 19:52:063456 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]bdd1b222014-06-10 11:08:393457 NormalSpdyTransactionHelper helper(
3458 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
3459 helper.RunToCompletion(&data);
3460 TransactionHelperResult out = helper.output();
[email protected]e3352df2014-03-19 05:55:423461 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3462}
3463
[email protected]bf2491a92009-11-29 16:39:483464// Test that we shutdown correctly on write errors.
[email protected]513963e2013-06-15 01:53:043465TEST_P(SpdyNetworkTransactionTest, WriteError) {
[email protected]cdf8f7e72013-05-23 10:56:463466 scoped_ptr<SpdyFrame> req(
3467 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]bf2491a92009-11-29 16:39:483468 MockWrite writes[] = {
[email protected]bdd1b222014-06-10 11:08:393469 // We'll write 10 bytes successfully
3470 MockWrite(ASYNC, req->data(), 10, 0),
3471 // Followed by ERROR!
3472 MockWrite(ASYNC, ERR_FAILED, 1),
3473 // Session drains and attempts to write a GOAWAY: Another ERROR!
3474 MockWrite(ASYNC, ERR_FAILED, 2),
[email protected]bf2491a92009-11-29 16:39:483475 };
3476
[email protected]238002d2013-10-17 02:01:403477 MockRead reads[] = {
[email protected]bdd1b222014-06-10 11:08:393478 MockRead(ASYNC, 0, 3) // EOF
[email protected]238002d2013-10-17 02:01:403479 };
3480
3481 DeterministicSocketData data(reads, arraysize(reads),
3482 writes, arraysize(writes));
3483
[email protected]262eec82013-03-19 21:01:363484 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503485 BoundNetLog(), GetParam(), NULL);
[email protected]238002d2013-10-17 02:01:403486 helper.SetDeterministic();
3487 helper.RunPreTestSetup();
3488 helper.AddDeterministicData(&data);
3489 EXPECT_TRUE(helper.StartDefaultTest());
3490 data.RunFor(2);
3491 helper.FinishDefaultTest();
rchbce10d972015-05-04 18:21:193492 EXPECT_TRUE(data.AllWriteDataConsumed());
3493 EXPECT_TRUE(!data.AllReadDataConsumed());
[email protected]3caf5542010-07-16 15:19:473494 TransactionHelperResult out = helper.output();
[email protected]bf2491a92009-11-29 16:39:483495 EXPECT_EQ(ERR_FAILED, out.rv);
3496}
3497
3498// Test that partial writes work.
[email protected]513963e2013-06-15 01:53:043499TEST_P(SpdyNetworkTransactionTest, PartialWrite) {
[email protected]bf2491a92009-11-29 16:39:483500 // Chop the SYN_STREAM frame into 5 chunks.
[email protected]cdf8f7e72013-05-23 10:56:463501 scoped_ptr<SpdyFrame> req(
3502 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]bf2491a92009-11-29 16:39:483503 const int kChunks = 5;
[email protected]4356f0f2013-04-07 00:58:173504 scoped_ptr<MockWrite[]> writes(ChopWriteFrame(*req.get(), kChunks));
rch73e17422015-05-04 19:52:063505 for (int i = 0; i < kChunks; ++i) {
3506 writes[i].sequence_number = i;
3507 }
[email protected]bf2491a92009-11-29 16:39:483508
[email protected]513963e2013-06-15 01:53:043509 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3510 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]bf2491a92009-11-29 16:39:483511 MockRead reads[] = {
rch73e17422015-05-04 19:52:063512 CreateMockRead(*resp, kChunks),
3513 CreateMockRead(*body, kChunks + 1),
3514 MockRead(ASYNC, 0, kChunks + 2) // EOF
[email protected]bf2491a92009-11-29 16:39:483515 };
3516
rch73e17422015-05-04 19:52:063517 SequencedSocketData data(reads, arraysize(reads), writes.get(), kChunks);
[email protected]262eec82013-03-19 21:01:363518 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503519 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573520 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473521 TransactionHelperResult out = helper.output();
[email protected]bf2491a92009-11-29 16:39:483522 EXPECT_EQ(OK, out.rv);
3523 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3524 EXPECT_EQ("hello!", out.response_data);
3525}
3526
[email protected]94d78132010-01-22 00:53:003527// In this test, we enable compression, but get a uncompressed SynReply from
3528// the server. Verify that teardown is all clean.
[email protected]513963e2013-06-15 01:53:043529TEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) {
[email protected]e3352df2014-03-19 05:55:423530 if (spdy_util_.spdy_version() >= SPDY4) {
3531 // HPACK doesn't use deflate compression.
3532 return;
3533 }
[email protected]ff98d7f02012-03-22 21:44:193534 scoped_ptr<SpdyFrame> compressed(
[email protected]cdf8f7e72013-05-23 10:56:463535 spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, LOWEST, true));
[email protected]bdd1b222014-06-10 11:08:393536 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3537 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
rch73e17422015-05-04 19:52:063538 MockWrite writes[] = {CreateMockWrite(*compressed, 0),
3539 CreateMockWrite(*goaway, 2)};
[email protected]94d78132010-01-22 00:53:003540
[email protected]513963e2013-06-15 01:53:043541 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3542 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]94d78132010-01-22 00:53:003543 MockRead reads[] = {
rch73e17422015-05-04 19:52:063544 CreateMockRead(*resp, 1),
[email protected]94d78132010-01-22 00:53:003545 };
3546
rch73e17422015-05-04 19:52:063547 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]513963e2013-06-15 01:53:043548 SpdySessionDependencies* session_deps =
3549 CreateSpdySessionDependencies(GetParam());
[email protected]f9cf5572012-12-04 15:52:093550 session_deps->enable_compression = true;
[email protected]262eec82013-03-19 21:01:363551 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]f9cf5572012-12-04 15:52:093552 BoundNetLog(), GetParam(), session_deps);
[email protected]dd54bd82012-07-19 23:44:573553 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473554 TransactionHelperResult out = helper.output();
[email protected]bdd1b222014-06-10 11:08:393555 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
[email protected]dd54bd82012-07-19 23:44:573556 data.Reset();
[email protected]94d78132010-01-22 00:53:003557}
3558
[email protected]9e743cd2010-03-16 07:03:533559// Test that the NetLog contains good data for a simple GET request.
[email protected]513963e2013-06-15 01:53:043560TEST_P(SpdyNetworkTransactionTest, NetLog) {
[email protected]3deb9a52010-11-11 00:24:403561 static const char* const kExtraHeaders[] = {
3562 "user-agent", "Chrome",
3563 };
[email protected]cdf8f7e72013-05-23 10:56:463564 scoped_ptr<SpdyFrame> req(
3565 spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, false, 1, LOWEST, true));
rch73e17422015-05-04 19:52:063566 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]dac358042009-12-18 02:07:483567
[email protected]513963e2013-06-15 01:53:043568 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3569 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]dac358042009-12-18 02:07:483570 MockRead reads[] = {
rch73e17422015-05-04 19:52:063571 CreateMockRead(*resp, 1),
3572 CreateMockRead(*body, 2),
3573 MockRead(ASYNC, 0, 3) // EOF
[email protected]dac358042009-12-18 02:07:483574 };
3575
vishal.b62985ca92015-04-17 08:45:513576 BoundTestNetLog log;
[email protected]dac358042009-12-18 02:07:483577
rch73e17422015-05-04 19:52:063578 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]3deb9a52010-11-11 00:24:403579 NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(),
[email protected]262eec82013-03-19 21:01:363580 DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503581 log.bound(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573582 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473583 TransactionHelperResult out = helper.output();
[email protected]dac358042009-12-18 02:07:483584 EXPECT_EQ(OK, out.rv);
3585 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3586 EXPECT_EQ("hello!", out.response_data);
3587
[email protected]9e743cd2010-03-16 07:03:533588 // Check that the NetLog was filled reasonably.
[email protected]3caf5542010-07-16 15:19:473589 // This test is intentionally non-specific about the exact ordering of the
3590 // log; instead we just check to make sure that certain events exist, and that
3591 // they are in the right order.
mmenke43758e62015-05-04 21:09:463592 TestNetLogEntry::List entries;
[email protected]b2fcd0e2010-12-01 15:19:403593 log.GetEntries(&entries);
3594
3595 EXPECT_LT(0u, entries.size());
[email protected]dac358042009-12-18 02:07:483596 int pos = 0;
bnc301745a2015-03-10 03:22:163597 pos = ExpectLogContainsSomewhere(entries, 0,
3598 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3599 NetLog::PHASE_BEGIN);
3600 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3601 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3602 NetLog::PHASE_END);
3603 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3604 NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3605 NetLog::PHASE_BEGIN);
3606 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3607 NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3608 NetLog::PHASE_END);
3609 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3610 NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3611 NetLog::PHASE_BEGIN);
3612 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3613 NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3614 NetLog::PHASE_END);
[email protected]3deb9a52010-11-11 00:24:403615
3616 // Check that we logged all the headers correctly
bnc301745a2015-03-10 03:22:163617 const NetLog::EventType type = (GetParam().protocol <= kProtoSPDY31)
3618 ? NetLog::TYPE_HTTP2_SESSION_SYN_STREAM
3619 : NetLog::TYPE_HTTP2_SESSION_SEND_HEADERS;
3620 pos = ExpectLogContainsSomewhere(entries, 0, type, NetLog::PHASE_NONE);
[email protected]3deb9a52010-11-11 00:24:403621
[email protected]ea5ef4c2013-06-13 22:50:273622 base::ListValue* header_list;
[email protected]f3da152d2012-06-02 01:00:573623 ASSERT_TRUE(entries[pos].params.get());
3624 ASSERT_TRUE(entries[pos].params->GetList("headers", &header_list));
3625
3626 std::vector<std::string> expected;
bncce36dca22015-04-21 22:11:233627 expected.push_back(std::string(spdy_util_.GetHostKey()) +
3628 ": www.example.org");
[email protected]513963e2013-06-15 01:53:043629 expected.push_back(std::string(spdy_util_.GetPathKey()) + ": /");
rchebf12982015-04-10 01:15:003630 expected.push_back(std::string(spdy_util_.GetSchemeKey()) + ": " +
3631 spdy_util_.default_url().scheme());
[email protected]513963e2013-06-15 01:53:043632 expected.push_back(std::string(spdy_util_.GetMethodKey()) + ": GET");
[email protected]f3da152d2012-06-02 01:00:573633 expected.push_back("user-agent: Chrome");
[email protected]601e03f12014-04-06 16:26:393634 if (spdy_util_.spdy_version() < SPDY4) {
3635 // SPDY4/HTTP2 eliminates use of the :version header.
3636 expected.push_back(std::string(spdy_util_.GetVersionKey()) + ": HTTP/1.1");
3637 }
[email protected]f3da152d2012-06-02 01:00:573638 EXPECT_EQ(expected.size(), header_list->GetSize());
3639 for (std::vector<std::string>::const_iterator it = expected.begin();
3640 it != expected.end();
3641 ++it) {
3642 base::StringValue header(*it);
3643 EXPECT_NE(header_list->end(), header_list->Find(header)) <<
3644 "Header not found: " << *it;
[email protected]3deb9a52010-11-11 00:24:403645 }
[email protected]dac358042009-12-18 02:07:483646}
3647
[email protected]79d84222010-02-26 00:01:443648// Since we buffer the IO from the stream to the renderer, this test verifies
3649// that when we read out the maximum amount of data (e.g. we received 50 bytes
3650// on the network, but issued a Read for only 5 of those bytes) that the data
3651// flow still works correctly.
[email protected]513963e2013-06-15 01:53:043652TEST_P(SpdyNetworkTransactionTest, BufferFull) {
[email protected]513963e2013-06-15 01:53:043653 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]20d005f2010-07-02 19:55:433654
[email protected]cdf8f7e72013-05-23 10:56:463655 scoped_ptr<SpdyFrame> req(
3656 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch73e17422015-05-04 19:52:063657 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]79d84222010-02-26 00:01:443658
[email protected]20d005f2010-07-02 19:55:433659 // 2 data frames in a single read.
[email protected]ff98d7f02012-03-22 21:44:193660 scoped_ptr<SpdyFrame> data_frame_1(
3661 framer.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE));
3662 scoped_ptr<SpdyFrame> data_frame_2(
3663 framer.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE));
3664 const SpdyFrame* data_frames[2] = {
[email protected]20d005f2010-07-02 19:55:433665 data_frame_1.get(),
3666 data_frame_2.get(),
[email protected]79d84222010-02-26 00:01:443667 };
[email protected]20d005f2010-07-02 19:55:433668 char combined_data_frames[100];
3669 int combined_data_frames_len =
3670 CombineFrames(data_frames, arraysize(data_frames),
3671 combined_data_frames, arraysize(combined_data_frames));
[email protected]ff98d7f02012-03-22 21:44:193672 scoped_ptr<SpdyFrame> last_frame(
3673 framer.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN));
[email protected]79d84222010-02-26 00:01:443674
[email protected]513963e2013-06-15 01:53:043675 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]79d84222010-02-26 00:01:443676 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133677 CreateMockRead(*resp),
[email protected]8ddf8322012-02-23 18:08:063678 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3679 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
3680 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
[email protected]20d005f2010-07-02 19:55:433681 CreateMockRead(*last_frame),
[email protected]8ddf8322012-02-23 18:08:063682 MockRead(ASYNC, 0, 0) // EOF
[email protected]79d84222010-02-26 00:01:443683 };
3684
[email protected]dd54bd82012-07-19 23:44:573685 DelayedSocketData data(1, reads, arraysize(reads),
3686 writes, arraysize(writes));
[email protected]79d84222010-02-26 00:01:443687
[email protected]49639fa2011-12-20 23:22:413688 TestCompletionCallback callback;
[email protected]79d84222010-02-26 00:01:443689
[email protected]262eec82013-03-19 21:01:363690 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503691 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:473692 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573693 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473694 HttpNetworkTransaction* trans = helper.trans();
[email protected]49639fa2011-12-20 23:22:413695 int rv = trans->Start(
3696 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]79d84222010-02-26 00:01:443697 EXPECT_EQ(ERR_IO_PENDING, rv);
3698
[email protected]3caf5542010-07-16 15:19:473699 TransactionHelperResult out = helper.output();
[email protected]79d84222010-02-26 00:01:443700 out.rv = callback.WaitForResult();
3701 EXPECT_EQ(out.rv, OK);
3702
3703 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503704 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]79d84222010-02-26 00:01:443705 EXPECT_TRUE(response->was_fetched_via_spdy);
3706 out.status_line = response->headers->GetStatusLine();
3707 out.response_info = *response; // Make a copy so we can verify.
3708
3709 // Read Data
[email protected]49639fa2011-12-20 23:22:413710 TestCompletionCallback read_callback;
[email protected]79d84222010-02-26 00:01:443711
3712 std::string content;
3713 do {
3714 // Read small chunks at a time.
3715 const int kSmallReadSize = 3;
bnc301745a2015-03-10 03:22:163716 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503717 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:163718 if (rv == ERR_IO_PENDING) {
[email protected]dd54bd82012-07-19 23:44:573719 data.CompleteRead();
[email protected]79d84222010-02-26 00:01:443720 rv = read_callback.WaitForResult();
3721 }
3722 if (rv > 0) {
3723 content.append(buf->data(), rv);
3724 } else if (rv < 0) {
3725 NOTREACHED();
3726 }
3727 } while (rv > 0);
3728
3729 out.response_data.swap(content);
3730
[email protected]30c942b2010-07-21 16:59:593731 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553732 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173733 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553734
[email protected]79d84222010-02-26 00:01:443735 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473736 helper.VerifyDataConsumed();
[email protected]79d84222010-02-26 00:01:443737
3738 EXPECT_EQ(OK, out.rv);
3739 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3740 EXPECT_EQ("goodbye world", out.response_data);
3741}
3742
[email protected]8918d282010-03-02 00:57:553743// Verify that basic buffering works; when multiple data frames arrive
3744// at the same time, ensure that we don't notify a read completion for
3745// each data frame individually.
[email protected]513963e2013-06-15 01:53:043746TEST_P(SpdyNetworkTransactionTest, Buffering) {
[email protected]513963e2013-06-15 01:53:043747 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]20d005f2010-07-02 19:55:433748
[email protected]cdf8f7e72013-05-23 10:56:463749 scoped_ptr<SpdyFrame> req(
3750 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]e7f75092010-07-01 22:39:133751 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]8918d282010-03-02 00:57:553752
3753 // 4 data frames in a single read.
[email protected]ff98d7f02012-03-22 21:44:193754 scoped_ptr<SpdyFrame> data_frame(
3755 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
3756 scoped_ptr<SpdyFrame> data_frame_fin(
3757 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
3758 const SpdyFrame* data_frames[4] = {
[email protected]20d005f2010-07-02 19:55:433759 data_frame.get(),
3760 data_frame.get(),
3761 data_frame.get(),
3762 data_frame_fin.get()
[email protected]8918d282010-03-02 00:57:553763 };
[email protected]20d005f2010-07-02 19:55:433764 char combined_data_frames[100];
3765 int combined_data_frames_len =
3766 CombineFrames(data_frames, arraysize(data_frames),
3767 combined_data_frames, arraysize(combined_data_frames));
[email protected]8918d282010-03-02 00:57:553768
[email protected]513963e2013-06-15 01:53:043769 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8918d282010-03-02 00:57:553770 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133771 CreateMockRead(*resp),
[email protected]8ddf8322012-02-23 18:08:063772 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3773 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
3774 MockRead(ASYNC, 0, 0) // EOF
[email protected]8918d282010-03-02 00:57:553775 };
3776
[email protected]dd54bd82012-07-19 23:44:573777 DelayedSocketData data(1, reads, arraysize(reads),
3778 writes, arraysize(writes));
[email protected]8918d282010-03-02 00:57:553779
[email protected]262eec82013-03-19 21:01:363780 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503781 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:473782 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573783 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473784 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:553785
[email protected]49639fa2011-12-20 23:22:413786 TestCompletionCallback callback;
3787 int rv = trans->Start(
3788 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]8918d282010-03-02 00:57:553789 EXPECT_EQ(ERR_IO_PENDING, rv);
3790
[email protected]3caf5542010-07-16 15:19:473791 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:553792 out.rv = callback.WaitForResult();
3793 EXPECT_EQ(out.rv, OK);
3794
3795 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503796 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]8918d282010-03-02 00:57:553797 EXPECT_TRUE(response->was_fetched_via_spdy);
3798 out.status_line = response->headers->GetStatusLine();
3799 out.response_info = *response; // Make a copy so we can verify.
3800
3801 // Read Data
[email protected]49639fa2011-12-20 23:22:413802 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:553803
3804 std::string content;
3805 int reads_completed = 0;
3806 do {
3807 // Read small chunks at a time.
3808 const int kSmallReadSize = 14;
bnc301745a2015-03-10 03:22:163809 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503810 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:163811 if (rv == ERR_IO_PENDING) {
[email protected]dd54bd82012-07-19 23:44:573812 data.CompleteRead();
[email protected]8918d282010-03-02 00:57:553813 rv = read_callback.WaitForResult();
3814 }
3815 if (rv > 0) {
3816 EXPECT_EQ(kSmallReadSize, rv);
3817 content.append(buf->data(), rv);
3818 } else if (rv < 0) {
3819 FAIL() << "Unexpected read error: " << rv;
3820 }
3821 reads_completed++;
3822 } while (rv > 0);
3823
3824 EXPECT_EQ(3, reads_completed); // Reads are: 14 bytes, 14 bytes, 0 bytes.
3825
3826 out.response_data.swap(content);
3827
[email protected]30c942b2010-07-21 16:59:593828 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553829 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173830 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553831
3832 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473833 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:553834
3835 EXPECT_EQ(OK, out.rv);
3836 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3837 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3838}
3839
3840// Verify the case where we buffer data but read it after it has been buffered.
[email protected]513963e2013-06-15 01:53:043841TEST_P(SpdyNetworkTransactionTest, BufferedAll) {
[email protected]513963e2013-06-15 01:53:043842 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]20d005f2010-07-02 19:55:433843
[email protected]cdf8f7e72013-05-23 10:56:463844 scoped_ptr<SpdyFrame> req(
3845 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch73e17422015-05-04 19:52:063846 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]8918d282010-03-02 00:57:553847
[email protected]20d005f2010-07-02 19:55:433848 // 5 data frames in a single read.
[email protected]745aa9c2014-06-27 02:21:293849 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]ff98d7f02012-03-22 21:44:193850 scoped_ptr<SpdyFrame> data_frame(
3851 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
3852 scoped_ptr<SpdyFrame> data_frame_fin(
3853 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
[email protected]745aa9c2014-06-27 02:21:293854 const SpdyFrame* frames[5] = {reply.get(), data_frame.get(), data_frame.get(),
3855 data_frame.get(), data_frame_fin.get()};
[email protected]20d005f2010-07-02 19:55:433856 char combined_frames[200];
3857 int combined_frames_len =
3858 CombineFrames(frames, arraysize(frames),
3859 combined_frames, arraysize(combined_frames));
[email protected]8918d282010-03-02 00:57:553860
3861 MockRead reads[] = {
rch73e17422015-05-04 19:52:063862 MockRead(ASYNC, combined_frames, combined_frames_len, 1),
3863 MockRead(ASYNC, 0, 2) // EOF
[email protected]8918d282010-03-02 00:57:553864 };
3865
rch73e17422015-05-04 19:52:063866 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]8918d282010-03-02 00:57:553867
[email protected]262eec82013-03-19 21:01:363868 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503869 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:473870 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573871 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473872 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:553873
[email protected]49639fa2011-12-20 23:22:413874 TestCompletionCallback callback;
3875 int rv = trans->Start(
3876 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]8918d282010-03-02 00:57:553877 EXPECT_EQ(ERR_IO_PENDING, rv);
3878
[email protected]3caf5542010-07-16 15:19:473879 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:553880 out.rv = callback.WaitForResult();
3881 EXPECT_EQ(out.rv, OK);
3882
3883 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503884 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]8918d282010-03-02 00:57:553885 EXPECT_TRUE(response->was_fetched_via_spdy);
3886 out.status_line = response->headers->GetStatusLine();
3887 out.response_info = *response; // Make a copy so we can verify.
3888
3889 // Read Data
[email protected]49639fa2011-12-20 23:22:413890 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:553891
3892 std::string content;
3893 int reads_completed = 0;
3894 do {
3895 // Read small chunks at a time.
3896 const int kSmallReadSize = 14;
bnc301745a2015-03-10 03:22:163897 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503898 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
[email protected]8918d282010-03-02 00:57:553899 if (rv > 0) {
3900 EXPECT_EQ(kSmallReadSize, rv);
3901 content.append(buf->data(), rv);
3902 } else if (rv < 0) {
3903 FAIL() << "Unexpected read error: " << rv;
3904 }
3905 reads_completed++;
3906 } while (rv > 0);
3907
3908 EXPECT_EQ(3, reads_completed);
3909
3910 out.response_data.swap(content);
3911
[email protected]30c942b2010-07-21 16:59:593912 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553913 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173914 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553915
3916 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473917 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:553918
3919 EXPECT_EQ(OK, out.rv);
3920 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3921 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3922}
3923
3924// Verify the case where we buffer data and close the connection.
[email protected]513963e2013-06-15 01:53:043925TEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
[email protected]513963e2013-06-15 01:53:043926 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]20d005f2010-07-02 19:55:433927
[email protected]cdf8f7e72013-05-23 10:56:463928 scoped_ptr<SpdyFrame> req(
3929 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]e7f75092010-07-01 22:39:133930 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]8918d282010-03-02 00:57:553931
3932 // All data frames in a single read.
[email protected]20d005f2010-07-02 19:55:433933 // NOTE: We don't FIN the stream.
[email protected]ff98d7f02012-03-22 21:44:193934 scoped_ptr<SpdyFrame> data_frame(
3935 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
3936 const SpdyFrame* data_frames[4] = {
[email protected]20d005f2010-07-02 19:55:433937 data_frame.get(),
3938 data_frame.get(),
3939 data_frame.get(),
3940 data_frame.get()
[email protected]8918d282010-03-02 00:57:553941 };
[email protected]20d005f2010-07-02 19:55:433942 char combined_data_frames[100];
3943 int combined_data_frames_len =
3944 CombineFrames(data_frames, arraysize(data_frames),
3945 combined_data_frames, arraysize(combined_data_frames));
[email protected]513963e2013-06-15 01:53:043946 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8918d282010-03-02 00:57:553947 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133948 CreateMockRead(*resp),
[email protected]8ddf8322012-02-23 18:08:063949 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait
3950 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
3951 MockRead(ASYNC, 0, 0) // EOF
[email protected]8918d282010-03-02 00:57:553952 };
3953
[email protected]dd54bd82012-07-19 23:44:573954 DelayedSocketData data(1, reads, arraysize(reads),
3955 writes, arraysize(writes));
[email protected]8918d282010-03-02 00:57:553956
[email protected]262eec82013-03-19 21:01:363957 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503958 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:473959 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573960 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473961 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:553962
[email protected]49639fa2011-12-20 23:22:413963 TestCompletionCallback callback;
[email protected]8918d282010-03-02 00:57:553964
[email protected]49639fa2011-12-20 23:22:413965 int rv = trans->Start(
3966 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]8918d282010-03-02 00:57:553967 EXPECT_EQ(ERR_IO_PENDING, rv);
3968
[email protected]3caf5542010-07-16 15:19:473969 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:553970 out.rv = callback.WaitForResult();
3971 EXPECT_EQ(out.rv, OK);
3972
3973 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503974 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]8918d282010-03-02 00:57:553975 EXPECT_TRUE(response->was_fetched_via_spdy);
3976 out.status_line = response->headers->GetStatusLine();
3977 out.response_info = *response; // Make a copy so we can verify.
3978
3979 // Read Data
[email protected]49639fa2011-12-20 23:22:413980 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:553981
3982 std::string content;
3983 int reads_completed = 0;
3984 do {
3985 // Read small chunks at a time.
3986 const int kSmallReadSize = 14;
bnc301745a2015-03-10 03:22:163987 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503988 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:163989 if (rv == ERR_IO_PENDING) {
[email protected]dd54bd82012-07-19 23:44:573990 data.CompleteRead();
[email protected]8918d282010-03-02 00:57:553991 rv = read_callback.WaitForResult();
3992 }
3993 if (rv > 0) {
3994 content.append(buf->data(), rv);
3995 } else if (rv < 0) {
3996 // This test intentionally closes the connection, and will get an error.
3997 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
3998 break;
3999 }
4000 reads_completed++;
4001 } while (rv > 0);
4002
4003 EXPECT_EQ(0, reads_completed);
4004
4005 out.response_data.swap(content);
4006
[email protected]30c942b2010-07-21 16:59:594007 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:554008 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:174009 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:554010
4011 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:474012 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:554013}
4014
[email protected]1ed7b3dc2010-03-04 05:41:454015// Verify the case where we buffer data and cancel the transaction.
[email protected]513963e2013-06-15 01:53:044016TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) {
[email protected]513963e2013-06-15 01:53:044017 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]20d005f2010-07-02 19:55:434018
[email protected]cdf8f7e72013-05-23 10:56:464019 scoped_ptr<SpdyFrame> req(
4020 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]975da41a2014-06-05 03:36:244021 scoped_ptr<SpdyFrame> rst(
4022 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
4023 MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*rst)};
[email protected]1ed7b3dc2010-03-04 05:41:454024
[email protected]20d005f2010-07-02 19:55:434025 // NOTE: We don't FIN the stream.
[email protected]ff98d7f02012-03-22 21:44:194026 scoped_ptr<SpdyFrame> data_frame(
4027 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
[email protected]1ed7b3dc2010-03-04 05:41:454028
[email protected]513963e2013-06-15 01:53:044029 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]1ed7b3dc2010-03-04 05:41:454030 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:134031 CreateMockRead(*resp),
[email protected]8ddf8322012-02-23 18:08:064032 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait
[email protected]20d005f2010-07-02 19:55:434033 CreateMockRead(*data_frame),
[email protected]8ddf8322012-02-23 18:08:064034 MockRead(ASYNC, 0, 0) // EOF
[email protected]1ed7b3dc2010-03-04 05:41:454035 };
4036
[email protected]dd54bd82012-07-19 23:44:574037 DelayedSocketData data(1, reads, arraysize(reads),
4038 writes, arraysize(writes));
[email protected]1ed7b3dc2010-03-04 05:41:454039
[email protected]262eec82013-03-19 21:01:364040 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504041 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:474042 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574043 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:474044 HttpNetworkTransaction* trans = helper.trans();
[email protected]49639fa2011-12-20 23:22:414045 TestCompletionCallback callback;
[email protected]1ed7b3dc2010-03-04 05:41:454046
[email protected]49639fa2011-12-20 23:22:414047 int rv = trans->Start(
4048 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]1ed7b3dc2010-03-04 05:41:454049 EXPECT_EQ(ERR_IO_PENDING, rv);
4050
[email protected]3caf5542010-07-16 15:19:474051 TransactionHelperResult out = helper.output();
[email protected]1ed7b3dc2010-03-04 05:41:454052 out.rv = callback.WaitForResult();
4053 EXPECT_EQ(out.rv, OK);
4054
4055 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:504056 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]1ed7b3dc2010-03-04 05:41:454057 EXPECT_TRUE(response->was_fetched_via_spdy);
4058 out.status_line = response->headers->GetStatusLine();
4059 out.response_info = *response; // Make a copy so we can verify.
4060
4061 // Read Data
[email protected]49639fa2011-12-20 23:22:414062 TestCompletionCallback read_callback;
[email protected]1ed7b3dc2010-03-04 05:41:454063
[email protected]88c7b4be2014-03-19 23:04:014064 const int kReadSize = 256;
bnc301745a2015-03-10 03:22:164065 scoped_refptr<IOBuffer> buf(new IOBuffer(kReadSize));
[email protected]88c7b4be2014-03-19 23:04:014066 rv = trans->Read(buf.get(), kReadSize, read_callback.callback());
bnc301745a2015-03-10 03:22:164067 ASSERT_EQ(ERR_IO_PENDING, rv) << "Unexpected read: " << rv;
[email protected]88c7b4be2014-03-19 23:04:014068
4069 // Complete the read now, which causes buffering to start.
4070 data.CompleteRead();
4071 // Destroy the transaction, causing the stream to get cancelled
4072 // and orphaning the buffered IO task.
4073 helper.ResetTrans();
[email protected]1ed7b3dc2010-03-04 05:41:454074
4075 // Flush the MessageLoop; this will cause the buffered IO task
4076 // to run for the final time.
[email protected]fc9d88472013-08-14 02:31:174077 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:474078
4079 // Verify that we consumed all test data.
4080 helper.VerifyDataConsumed();
[email protected]1ed7b3dc2010-03-04 05:41:454081}
4082
[email protected]74188f22010-04-09 20:18:504083// Test that if the server requests persistence of settings, that we save
[email protected]18b28ab2012-04-18 02:14:424084// the settings in the HttpServerProperties.
[email protected]513963e2013-06-15 01:53:044085TEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
[email protected]8a7bc7a2014-02-28 21:25:224086 if (spdy_util_.spdy_version() >= SPDY4) {
[email protected]745aa9c2014-06-27 02:21:294087 // SPDY4 doesn't support settings persistence.
[email protected]8a7bc7a2014-02-28 21:25:224088 return;
4089 }
[email protected]74188f22010-04-09 20:18:504090 static const SpdyHeaderInfo kSynReplyInfo = {
[email protected]ff98d7f02012-03-22 21:44:194091 SYN_REPLY, // Syn Reply
[email protected]e0935cc2012-03-24 14:12:484092 1, // Stream ID
4093 0, // Associated Stream ID
[email protected]513963e2013-06-15 01:53:044094 ConvertRequestPriorityToSpdyPriority(
4095 LOWEST, spdy_util_.spdy_version()),
4096 kSpdyCredentialSlotUnused,
[email protected]ff98d7f02012-03-22 21:44:194097 CONTROL_FLAG_NONE, // Control Flags
[email protected]e0935cc2012-03-24 14:12:484098 false, // Compressed
[email protected]5a7bb252013-02-09 00:21:054099 RST_STREAM_INVALID, // Status
[email protected]e0935cc2012-03-24 14:12:484100 NULL, // Data
4101 0, // Data Length
[email protected]ff98d7f02012-03-22 21:44:194102 DATA_FLAG_NONE // Data Flags
[email protected]74188f22010-04-09 20:18:504103 };
[email protected]74188f22010-04-09 20:18:504104
[email protected]c0168822011-12-10 01:24:274105 BoundNetLog net_log;
[email protected]262eec82013-03-19 21:01:364106 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4107 net_log, GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:584108 helper.RunPreTestSetup();
[email protected]74188f22010-04-09 20:18:504109
4110 // Verify that no settings exist initially.
bncce36dca22015-04-21 22:11:234111 HostPortPair host_port_pair("www.example.org", helper.port());
[email protected]102e27c2011-02-23 01:01:314112 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
[email protected]53bfa31c2011-11-15 19:20:314113 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4114 host_port_pair).empty());
[email protected]74188f22010-04-09 20:18:504115
4116 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:464117 scoped_ptr<SpdyFrame> req(
4118 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch73e17422015-05-04 19:52:064119 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]74188f22010-04-09 20:18:504120
4121 // Construct the reply.
[email protected]513963e2013-06-15 01:53:044122 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4123 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4124 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
[email protected]ff98d7f02012-03-22 21:44:194125 scoped_ptr<SpdyFrame> reply(
[email protected]513963e2013-06-15 01:53:044126 spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
[email protected]74188f22010-04-09 20:18:504127
[email protected]e0935cc2012-03-24 14:12:484128 const SpdySettingsIds kSampleId1 = SETTINGS_UPLOAD_BANDWIDTH;
[email protected]74188f22010-04-09 20:18:504129 unsigned int kSampleValue1 = 0x0a0a0a0a;
[email protected]e0935cc2012-03-24 14:12:484130 const SpdySettingsIds kSampleId2 = SETTINGS_DOWNLOAD_BANDWIDTH;
[email protected]74188f22010-04-09 20:18:504131 unsigned int kSampleValue2 = 0x0b0b0b0b;
[email protected]e0935cc2012-03-24 14:12:484132 const SpdySettingsIds kSampleId3 = SETTINGS_ROUND_TRIP_TIME;
[email protected]74188f22010-04-09 20:18:504133 unsigned int kSampleValue3 = 0x0c0c0c0c;
[email protected]ff98d7f02012-03-22 21:44:194134 scoped_ptr<SpdyFrame> settings_frame;
[email protected]74188f22010-04-09 20:18:504135 {
4136 // Construct the SETTINGS frame.
[email protected]18b28ab2012-04-18 02:14:424137 SettingsMap settings;
[email protected]e0935cc2012-03-24 14:12:484138 // First add a persisted setting.
[email protected]18b28ab2012-04-18 02:14:424139 settings[kSampleId1] =
4140 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue1);
[email protected]e0935cc2012-03-24 14:12:484141 // Next add a non-persisted setting.
[email protected]18b28ab2012-04-18 02:14:424142 settings[kSampleId2] =
4143 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kSampleValue2);
[email protected]e0935cc2012-03-24 14:12:484144 // Next add another persisted setting.
[email protected]18b28ab2012-04-18 02:14:424145 settings[kSampleId3] =
4146 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue3);
[email protected]c10b20852013-05-15 21:29:204147 settings_frame.reset(spdy_util_.ConstructSpdySettings(settings));
[email protected]74188f22010-04-09 20:18:504148 }
4149
[email protected]513963e2013-06-15 01:53:044150 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]74188f22010-04-09 20:18:504151 MockRead reads[] = {
rch73e17422015-05-04 19:52:064152 CreateMockRead(*reply, 1),
4153 CreateMockRead(*body, 2),
4154 CreateMockRead(*settings_frame, 3),
4155 MockRead(ASYNC, 0, 4) // EOF
[email protected]74188f22010-04-09 20:18:504156 };
4157
rch73e17422015-05-04 19:52:064158 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:574159 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:584160 helper.RunDefaultTest();
4161 helper.VerifyDataConsumed();
[email protected]3caf5542010-07-16 15:19:474162 TransactionHelperResult out = helper.output();
[email protected]74188f22010-04-09 20:18:504163 EXPECT_EQ(OK, out.rv);
4164 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4165 EXPECT_EQ("hello!", out.response_data);
4166
4167 {
4168 // Verify we had two persisted settings.
[email protected]e0935cc2012-03-24 14:12:484169 const SettingsMap& settings_map =
[email protected]53bfa31c2011-11-15 19:20:314170 spdy_session_pool->http_server_properties()->GetSpdySettings(
4171 host_port_pair);
[email protected]e0935cc2012-03-24 14:12:484172 ASSERT_EQ(2u, settings_map.size());
[email protected]74188f22010-04-09 20:18:504173
4174 // Verify the first persisted setting.
[email protected]e0935cc2012-03-24 14:12:484175 SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4176 EXPECT_TRUE(it1 != settings_map.end());
4177 SettingsFlagsAndValue flags_and_value1 = it1->second;
4178 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4179 EXPECT_EQ(kSampleValue1, flags_and_value1.second);
[email protected]74188f22010-04-09 20:18:504180
4181 // Verify the second persisted setting.
[email protected]e0935cc2012-03-24 14:12:484182 SettingsMap::const_iterator it3 = settings_map.find(kSampleId3);
4183 EXPECT_TRUE(it3 != settings_map.end());
4184 SettingsFlagsAndValue flags_and_value3 = it3->second;
4185 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value3.first);
4186 EXPECT_EQ(kSampleValue3, flags_and_value3.second);
[email protected]74188f22010-04-09 20:18:504187 }
4188}
4189
4190// Test that when there are settings saved that they are sent back to the
4191// server upon session establishment.
[email protected]513963e2013-06-15 01:53:044192TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) {
[email protected]745aa9c2014-06-27 02:21:294193 if (spdy_util_.spdy_version() >= SPDY4) {
4194 // SPDY4 doesn't support settings persistence.
4195 return;
4196 }
[email protected]74188f22010-04-09 20:18:504197 static const SpdyHeaderInfo kSynReplyInfo = {
[email protected]ff98d7f02012-03-22 21:44:194198 SYN_REPLY, // Syn Reply
[email protected]e0935cc2012-03-24 14:12:484199 1, // Stream ID
4200 0, // Associated Stream ID
[email protected]513963e2013-06-15 01:53:044201 ConvertRequestPriorityToSpdyPriority(
4202 LOWEST, spdy_util_.spdy_version()),
4203 kSpdyCredentialSlotUnused,
[email protected]ff98d7f02012-03-22 21:44:194204 CONTROL_FLAG_NONE, // Control Flags
[email protected]e0935cc2012-03-24 14:12:484205 false, // Compressed
[email protected]5a7bb252013-02-09 00:21:054206 RST_STREAM_INVALID, // Status
[email protected]e0935cc2012-03-24 14:12:484207 NULL, // Data
4208 0, // Data Length
[email protected]ff98d7f02012-03-22 21:44:194209 DATA_FLAG_NONE // Data Flags
[email protected]74188f22010-04-09 20:18:504210 };
[email protected]74188f22010-04-09 20:18:504211
[email protected]c0168822011-12-10 01:24:274212 BoundNetLog net_log;
[email protected]262eec82013-03-19 21:01:364213 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4214 net_log, GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:584215 helper.RunPreTestSetup();
[email protected]74188f22010-04-09 20:18:504216
[email protected]b40f7fa2013-08-01 16:13:054217 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4218
4219 SpdySessionPoolPeer pool_peer(spdy_session_pool);
4220 pool_peer.SetEnableSendingInitialData(true);
4221
[email protected]74188f22010-04-09 20:18:504222 // Verify that no settings exist initially.
bncce36dca22015-04-21 22:11:234223 HostPortPair host_port_pair("www.example.org", helper.port());
[email protected]53bfa31c2011-11-15 19:20:314224 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4225 host_port_pair).empty());
[email protected]74188f22010-04-09 20:18:504226
[email protected]c143f2742014-03-31 00:48:544227 const SpdySettingsIds kSampleId1 = SETTINGS_MAX_CONCURRENT_STREAMS;
[email protected]74188f22010-04-09 20:18:504228 unsigned int kSampleValue1 = 0x0a0a0a0a;
[email protected]c143f2742014-03-31 00:48:544229 const SpdySettingsIds kSampleId2 = SETTINGS_INITIAL_WINDOW_SIZE;
[email protected]74188f22010-04-09 20:18:504230 unsigned int kSampleValue2 = 0x0c0c0c0c;
[email protected]74188f22010-04-09 20:18:504231
[email protected]e0935cc2012-03-24 14:12:484232 // First add a persisted setting.
4233 spdy_session_pool->http_server_properties()->SetSpdySetting(
4234 host_port_pair,
4235 kSampleId1,
4236 SETTINGS_FLAG_PLEASE_PERSIST,
4237 kSampleValue1);
4238
4239 // Next add another persisted setting.
4240 spdy_session_pool->http_server_properties()->SetSpdySetting(
4241 host_port_pair,
4242 kSampleId2,
4243 SETTINGS_FLAG_PLEASE_PERSIST,
4244 kSampleValue2);
[email protected]74188f22010-04-09 20:18:504245
[email protected]53bfa31c2011-11-15 19:20:314246 EXPECT_EQ(2u, spdy_session_pool->http_server_properties()->GetSpdySettings(
4247 host_port_pair).size());
[email protected]74188f22010-04-09 20:18:504248
[email protected]b40f7fa2013-08-01 16:13:054249 // Construct the initial SETTINGS frame.
4250 SettingsMap initial_settings;
4251 initial_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4252 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
4253 scoped_ptr<SpdyFrame> initial_settings_frame(
4254 spdy_util_.ConstructSpdySettings(initial_settings));
4255
[email protected]b40f7fa2013-08-01 16:13:054256 // Construct the persisted SETTINGS frame.
[email protected]18b28ab2012-04-18 02:14:424257 const SettingsMap& settings =
[email protected]53bfa31c2011-11-15 19:20:314258 spdy_session_pool->http_server_properties()->GetSpdySettings(
4259 host_port_pair);
[email protected]c10b20852013-05-15 21:29:204260 scoped_ptr<SpdyFrame> settings_frame(
4261 spdy_util_.ConstructSpdySettings(settings));
[email protected]74188f22010-04-09 20:18:504262
4263 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:464264 scoped_ptr<SpdyFrame> req(
4265 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]74188f22010-04-09 20:18:504266
[email protected]b40f7fa2013-08-01 16:13:054267 std::vector<MockWrite> writes;
bnc5b3dce0d2014-11-13 19:57:464268 if ((GetParam().protocol >= kProtoSPDY4MinimumVersion) &&
4269 (GetParam().protocol <= kProtoSPDY4MaximumVersion)) {
[email protected]b40f7fa2013-08-01 16:13:054270 writes.push_back(
4271 MockWrite(ASYNC,
4272 kHttp2ConnectionHeaderPrefix,
4273 kHttp2ConnectionHeaderPrefixSize));
4274 }
4275 writes.push_back(CreateMockWrite(*initial_settings_frame));
[email protected]b40f7fa2013-08-01 16:13:054276 writes.push_back(CreateMockWrite(*settings_frame));
4277 writes.push_back(CreateMockWrite(*req));
[email protected]74188f22010-04-09 20:18:504278
4279 // Construct the reply.
[email protected]513963e2013-06-15 01:53:044280 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4281 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4282 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
[email protected]ff98d7f02012-03-22 21:44:194283 scoped_ptr<SpdyFrame> reply(
[email protected]513963e2013-06-15 01:53:044284 spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
[email protected]74188f22010-04-09 20:18:504285
[email protected]513963e2013-06-15 01:53:044286 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]74188f22010-04-09 20:18:504287 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:134288 CreateMockRead(*reply),
4289 CreateMockRead(*body),
[email protected]8ddf8322012-02-23 18:08:064290 MockRead(ASYNC, 0, 0) // EOF
[email protected]74188f22010-04-09 20:18:504291 };
4292
[email protected]dd54bd82012-07-19 23:44:574293 DelayedSocketData data(2, reads, arraysize(reads),
[email protected]b40f7fa2013-08-01 16:13:054294 vector_as_array(&writes), writes.size());
[email protected]dd54bd82012-07-19 23:44:574295 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:584296 helper.RunDefaultTest();
4297 helper.VerifyDataConsumed();
[email protected]3caf5542010-07-16 15:19:474298 TransactionHelperResult out = helper.output();
[email protected]74188f22010-04-09 20:18:504299 EXPECT_EQ(OK, out.rv);
4300 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4301 EXPECT_EQ("hello!", out.response_data);
4302
4303 {
4304 // Verify we had two persisted settings.
[email protected]e0935cc2012-03-24 14:12:484305 const SettingsMap& settings_map =
[email protected]53bfa31c2011-11-15 19:20:314306 spdy_session_pool->http_server_properties()->GetSpdySettings(
4307 host_port_pair);
[email protected]e0935cc2012-03-24 14:12:484308 ASSERT_EQ(2u, settings_map.size());
[email protected]74188f22010-04-09 20:18:504309
4310 // Verify the first persisted setting.
[email protected]e0935cc2012-03-24 14:12:484311 SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4312 EXPECT_TRUE(it1 != settings_map.end());
4313 SettingsFlagsAndValue flags_and_value1 = it1->second;
4314 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4315 EXPECT_EQ(kSampleValue1, flags_and_value1.second);
[email protected]74188f22010-04-09 20:18:504316
4317 // Verify the second persisted setting.
[email protected]e0935cc2012-03-24 14:12:484318 SettingsMap::const_iterator it2 = settings_map.find(kSampleId2);
4319 EXPECT_TRUE(it2 != settings_map.end());
4320 SettingsFlagsAndValue flags_and_value2 = it2->second;
4321 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value2.first);
4322 EXPECT_EQ(kSampleValue2, flags_and_value2.second);
[email protected]74188f22010-04-09 20:18:504323 }
4324}
4325
[email protected]513963e2013-06-15 01:53:044326TEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
[email protected]cdf8f7e72013-05-23 10:56:464327 scoped_ptr<SpdyFrame> req(
4328 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch73e17422015-05-04 19:52:064329 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]69d717bd2010-04-21 18:43:214330
[email protected]c10b20852013-05-15 21:29:204331 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway());
[email protected]69d717bd2010-04-21 18:43:214332 MockRead reads[] = {
rch73e17422015-05-04 19:52:064333 CreateMockRead(*go_away, 1),
[email protected]58cebf8f2010-07-31 19:20:164334 };
4335
rch73e17422015-05-04 19:52:064336 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:364337 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504338 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:574339 helper.AddData(&data);
4340 helper.RunToCompletion(&data);
[email protected]58cebf8f2010-07-31 19:20:164341 TransactionHelperResult out = helper.output();
[email protected]c9336d22010-08-10 00:04:184342 EXPECT_EQ(ERR_ABORTED, out.rv);
[email protected]69d717bd2010-04-21 18:43:214343}
4344
[email protected]513963e2013-06-15 01:53:044345TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) {
[email protected]cdf8f7e72013-05-23 10:56:464346 scoped_ptr<SpdyFrame> req(
4347 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch73e17422015-05-04 19:52:064348 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]f5ed21552010-05-04 18:39:544349
[email protected]513963e2013-06-15 01:53:044350 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]f5ed21552010-05-04 18:39:544351 MockRead reads[] = {
rch73e17422015-05-04 19:52:064352 CreateMockRead(*resp, 1), MockRead(SYNCHRONOUS, 0, 2) // EOF
[email protected]f5ed21552010-05-04 18:39:544353 };
4354
rch73e17422015-05-04 19:52:064355 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]f5ed21552010-05-04 18:39:544356 BoundNetLog log;
[email protected]262eec82013-03-19 21:01:364357 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504358 log, GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:474359 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574360 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:474361 HttpNetworkTransaction* trans = helper.trans();
[email protected]f5ed21552010-05-04 18:39:544362
[email protected]49639fa2011-12-20 23:22:414363 TestCompletionCallback callback;
[email protected]3caf5542010-07-16 15:19:474364 TransactionHelperResult out;
[email protected]49639fa2011-12-20 23:22:414365 out.rv = trans->Start(&CreateGetRequest(), callback.callback(), log);
[email protected]3caf5542010-07-16 15:19:474366
[email protected]f5ed21552010-05-04 18:39:544367 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4368 out.rv = callback.WaitForResult();
4369 EXPECT_EQ(out.rv, OK);
4370
4371 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:504372 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]f5ed21552010-05-04 18:39:544373 EXPECT_TRUE(response->was_fetched_via_spdy);
[email protected]3caf5542010-07-16 15:19:474374 out.rv = ReadTransaction(trans, &out.response_data);
[email protected]f5ed21552010-05-04 18:39:544375 EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv);
4376
4377 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:474378 helper.VerifyDataConsumed();
[email protected]f5ed21552010-05-04 18:39:544379}
[email protected]58cebf8f2010-07-31 19:20:164380
bnca7f994a2015-01-20 19:39:414381// HTTP_1_1_REQUIRED results in ERR_HTTP_1_1_REQUIRED.
4382TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredError) {
4383 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4384 if (spdy_util_.spdy_version() < SPDY4)
4385 return;
4386
4387 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4388 BoundNetLog(), GetParam(), nullptr);
4389
4390 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway(
4391 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
4392 MockRead reads[] = {
rch73e17422015-05-04 19:52:064393 CreateMockRead(*go_away, 0),
bnca7f994a2015-01-20 19:39:414394 };
rch73e17422015-05-04 19:52:064395 SequencedSocketData data(reads, arraysize(reads), nullptr, 0);
bnca7f994a2015-01-20 19:39:414396
4397 helper.RunToCompletion(&data);
4398 TransactionHelperResult out = helper.output();
4399 EXPECT_EQ(ERR_HTTP_1_1_REQUIRED, out.rv);
4400}
4401
bncfacdd852015-01-09 19:22:544402// Retry with HTTP/1.1 when receiving HTTP_1_1_REQUIRED. Note that no actual
4403// protocol negotiation happens, instead this test forces protocols for both
4404// sockets.
4405TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredRetry) {
4406 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4407 if (spdy_util_.spdy_version() < SPDY4)
4408 return;
4409 // HTTP_1_1_REQUIRED implementation relies on the assumption that HTTP/2 is
4410 // only spoken over SSL.
rchebf12982015-04-10 01:15:004411 if (GetParam().ssl_type != HTTPS_SPDY_VIA_NPN)
bncfacdd852015-01-09 19:22:544412 return;
4413
4414 HttpRequestInfo request;
4415 request.method = "GET";
bncce36dca22015-04-21 22:11:234416 request.url = GURL("https://www.example.org/");
bncfacdd852015-01-09 19:22:544417 scoped_ptr<SpdySessionDependencies> session_deps(
4418 CreateSpdySessionDependencies(GetParam()));
4419 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
bncfacdd852015-01-09 19:22:544420 session_deps->next_protos = SpdyNextProtos();
4421 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
4422 GetParam(), session_deps.release());
4423
4424 // First socket: HTTP/2 request rejected with HTTP_1_1_REQUIRED.
rchebf12982015-04-10 01:15:004425 const char* url = request.url.spec().c_str();
bncfacdd852015-01-09 19:22:544426 scoped_ptr<SpdyHeaderBlock> headers(spdy_util_.ConstructGetHeaderBlock(url));
4427 scoped_ptr<SpdyFrame> req(
4428 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
rch73e17422015-05-04 19:52:064429 MockWrite writes0[] = {CreateMockWrite(*req, 0)};
bncfacdd852015-01-09 19:22:544430 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway(
4431 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
rch73e17422015-05-04 19:52:064432 MockRead reads0[] = {CreateMockRead(*go_away, 1)};
4433 SequencedSocketData data0(reads0, arraysize(reads0), writes0,
4434 arraysize(writes0));
bncfacdd852015-01-09 19:22:544435
4436 scoped_ptr<SSLSocketDataProvider> ssl_provider0(
4437 new SSLSocketDataProvider(ASYNC, OK));
4438 // Expect HTTP/2 protocols too in SSLConfig.
4439 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4440 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY31);
4441 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY4_14);
bncbfa20e62015-03-09 23:29:224442 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY4);
bncfacdd852015-01-09 19:22:544443 // Force SPDY.
4444 ssl_provider0->SetNextProto(GetParam().protocol);
4445 helper.AddDataWithSSLSocketDataProvider(&data0, ssl_provider0.Pass());
4446
4447 // Second socket: falling back to HTTP/1.1.
rch73e17422015-05-04 19:52:064448 MockWrite writes1[] = {MockWrite(ASYNC, 0,
4449 "GET / HTTP/1.1\r\n"
4450 "Host: www.example.org\r\n"
4451 "Connection: keep-alive\r\n\r\n")};
4452 MockRead reads1[] = {MockRead(ASYNC, 1,
4453 "HTTP/1.1 200 OK\r\n"
4454 "Content-Length: 5\r\n\r\n"
4455 "hello")};
4456 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
4457 arraysize(writes1));
bncfacdd852015-01-09 19:22:544458
4459 scoped_ptr<SSLSocketDataProvider> ssl_provider1(
4460 new SSLSocketDataProvider(ASYNC, OK));
4461 // Expect only HTTP/1.1 protocol in SSLConfig.
4462 ssl_provider1->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4463 // Force HTTP/1.1.
4464 ssl_provider1->SetNextProto(kProtoHTTP11);
4465 helper.AddDataWithSSLSocketDataProvider(&data1, ssl_provider1.Pass());
4466
4467 base::WeakPtr<HttpServerProperties> http_server_properties =
4468 helper.session()->spdy_session_pool()->http_server_properties();
4469 const HostPortPair host_port_pair = HostPortPair::FromURL(GURL(url));
4470 EXPECT_FALSE(http_server_properties->RequiresHTTP11(host_port_pair));
4471
4472 helper.RunPreTestSetup();
4473 helper.StartDefaultTest();
4474 helper.FinishDefaultTestWithoutVerification();
4475 helper.VerifyDataConsumed();
4476 EXPECT_TRUE(http_server_properties->RequiresHTTP11(host_port_pair));
4477
4478 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
4479 ASSERT_TRUE(response != nullptr);
4480 ASSERT_TRUE(response->headers.get() != nullptr);
4481 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4482 EXPECT_FALSE(response->was_fetched_via_spdy);
4483 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1, response->connection_info);
4484 EXPECT_TRUE(response->was_npn_negotiated);
4485 EXPECT_TRUE(request.url.SchemeIs("https"));
4486 EXPECT_EQ("127.0.0.1", response->socket_address.host());
4487 EXPECT_EQ(443, response->socket_address.port());
4488 std::string response_data;
4489 ASSERT_EQ(OK, ReadTransaction(helper.trans(), &response_data));
4490 EXPECT_EQ("hello", response_data);
4491}
4492
4493// Retry with HTTP/1.1 to the proxy when receiving HTTP_1_1_REQUIRED from the
4494// proxy. Note that no actual protocol negotiation happens, instead this test
4495// forces protocols for both sockets.
4496TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredProxyRetry) {
4497 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4498 if (spdy_util_.spdy_version() < SPDY4)
4499 return;
4500 // HTTP_1_1_REQUIRED implementation relies on the assumption that HTTP/2 is
4501 // only spoken over SSL.
rchebf12982015-04-10 01:15:004502 if (GetParam().ssl_type != HTTPS_SPDY_VIA_NPN)
bncfacdd852015-01-09 19:22:544503 return;
4504
4505 HttpRequestInfo request;
4506 request.method = "GET";
bncce36dca22015-04-21 22:11:234507 request.url = GURL("https://www.example.org/");
bncfacdd852015-01-09 19:22:544508 scoped_ptr<SpdySessionDependencies> session_deps(
4509 CreateSpdySessionDependencies(
4510 GetParam(),
4511 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70")));
4512 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
bncfacdd852015-01-09 19:22:544513 session_deps->next_protos = SpdyNextProtos();
4514 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
4515 GetParam(), session_deps.release());
4516
4517 // First socket: HTTP/2 CONNECT rejected with HTTP_1_1_REQUIRED.
4518 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(
bncce36dca22015-04-21 22:11:234519 nullptr, 0, 1, LOWEST, HostPortPair("www.example.org", 443)));
rch73e17422015-05-04 19:52:064520 MockWrite writes0[] = {CreateMockWrite(*req, 0)};
bncfacdd852015-01-09 19:22:544521 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway(
4522 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
rch73e17422015-05-04 19:52:064523 MockRead reads0[] = {CreateMockRead(*go_away, 1)};
4524 SequencedSocketData data0(reads0, arraysize(reads0), writes0,
4525 arraysize(writes0));
bncfacdd852015-01-09 19:22:544526
4527 scoped_ptr<SSLSocketDataProvider> ssl_provider0(
4528 new SSLSocketDataProvider(ASYNC, OK));
4529 // Expect HTTP/2 protocols too in SSLConfig.
4530 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4531 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY31);
4532 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY4_14);
bncbfa20e62015-03-09 23:29:224533 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY4);
bncfacdd852015-01-09 19:22:544534 // Force SPDY.
4535 ssl_provider0->SetNextProto(GetParam().protocol);
4536 helper.AddDataWithSSLSocketDataProvider(&data0, ssl_provider0.Pass());
4537
4538 // Second socket: retry using HTTP/1.1.
4539 MockWrite writes1[] = {
rch73e17422015-05-04 19:52:064540 MockWrite(ASYNC, 0,
bncce36dca22015-04-21 22:11:234541 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4542 "Host: www.example.org\r\n"
bncfacdd852015-01-09 19:22:544543 "Proxy-Connection: keep-alive\r\n\r\n"),
rch73e17422015-05-04 19:52:064544 MockWrite(ASYNC, 2,
bncfacdd852015-01-09 19:22:544545 "GET / HTTP/1.1\r\n"
bncce36dca22015-04-21 22:11:234546 "Host: www.example.org\r\n"
bncfacdd852015-01-09 19:22:544547 "Connection: keep-alive\r\n\r\n"),
4548 };
4549
4550 MockRead reads1[] = {
rch73e17422015-05-04 19:52:064551 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
4552 MockRead(ASYNC, 3,
bncfacdd852015-01-09 19:22:544553 "HTTP/1.1 200 OK\r\n"
4554 "Content-Length: 5\r\n\r\n"
4555 "hello"),
4556 };
rch73e17422015-05-04 19:52:064557 SequencedSocketData data1(reads1, arraysize(reads1), writes1,
4558 arraysize(writes1));
bncfacdd852015-01-09 19:22:544559
4560 scoped_ptr<SSLSocketDataProvider> ssl_provider1(
4561 new SSLSocketDataProvider(ASYNC, OK));
4562 // Expect only HTTP/1.1 protocol in SSLConfig.
4563 ssl_provider1->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4564 // Force HTTP/1.1.
4565 ssl_provider1->SetNextProto(kProtoHTTP11);
4566 helper.AddDataWithSSLSocketDataProvider(&data1, ssl_provider1.Pass());
4567
4568 // A third socket is needed for the tunnelled connection.
4569 scoped_ptr<SSLSocketDataProvider> ssl_provider2(
4570 new SSLSocketDataProvider(ASYNC, OK));
4571 helper.session_deps()->socket_factory->AddSSLSocketDataProvider(
4572 ssl_provider2.get());
4573
4574 base::WeakPtr<HttpServerProperties> http_server_properties =
4575 helper.session()->spdy_session_pool()->http_server_properties();
4576 const HostPortPair proxy_host_port_pair = HostPortPair("myproxy", 70);
4577 EXPECT_FALSE(http_server_properties->RequiresHTTP11(proxy_host_port_pair));
4578
4579 helper.RunPreTestSetup();
4580 helper.StartDefaultTest();
4581 helper.FinishDefaultTestWithoutVerification();
4582 helper.VerifyDataConsumed();
4583 EXPECT_TRUE(http_server_properties->RequiresHTTP11(proxy_host_port_pair));
4584
4585 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
4586 ASSERT_TRUE(response != nullptr);
4587 ASSERT_TRUE(response->headers.get() != nullptr);
4588 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4589 EXPECT_FALSE(response->was_fetched_via_spdy);
4590 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1, response->connection_info);
4591 EXPECT_FALSE(response->was_npn_negotiated);
4592 EXPECT_TRUE(request.url.SchemeIs("https"));
4593 EXPECT_EQ("127.0.0.1", response->socket_address.host());
4594 EXPECT_EQ(70, response->socket_address.port());
4595 std::string response_data;
4596 ASSERT_EQ(OK, ReadTransaction(helper.trans(), &response_data));
4597 EXPECT_EQ("hello", response_data);
4598}
4599
[email protected]b261d0e2010-08-02 19:13:244600// Test to make sure we can correctly connect through a proxy.
[email protected]513963e2013-06-15 01:53:044601TEST_P(SpdyNetworkTransactionTest, ProxyConnect) {
[email protected]262eec82013-03-19 21:01:364602 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504603 BoundNetLog(), GetParam(), NULL);
[email protected]bb88e1d32013-05-03 23:11:074604 helper.session_deps().reset(CreateSpdySessionDependencies(
[email protected]513963e2013-06-15 01:53:044605 GetParam(),
[email protected]733b7a6d2010-08-25 01:38:434606 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
[email protected]00cd9c42010-11-02 20:15:574607 helper.SetSession(make_scoped_refptr(
4608 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
[email protected]b261d0e2010-08-02 19:13:244609 helper.RunPreTestSetup();
4610 HttpNetworkTransaction* trans = helper.trans();
4611
rchebf12982015-04-10 01:15:004612 const char kConnect443[] = {
bncce36dca22015-04-21 22:11:234613 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4614 "Host: www.example.org\r\n"
rchcb934f562015-04-07 16:25:124615 "Proxy-Connection: keep-alive\r\n\r\n"};
[email protected]b261d0e2010-08-02 19:13:244616 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
[email protected]cdf8f7e72013-05-23 10:56:464617 scoped_ptr<SpdyFrame> req(
4618 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:044619 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4620 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:244621
rchebf12982015-04-10 01:15:004622 MockWrite writes[] = {
4623 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4624 CreateMockWrite(*req, 2),
[email protected]b261d0e2010-08-02 19:13:244625 };
rchebf12982015-04-10 01:15:004626 MockRead reads[] = {
4627 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4628 CreateMockRead(*resp, 3),
4629 CreateMockRead(*body.get(), 4),
4630 MockRead(ASYNC, 0, 0, 5),
[email protected]b261d0e2010-08-02 19:13:244631 };
rch73e17422015-05-04 19:52:064632 scoped_ptr<SequencedSocketData> data(new SequencedSocketData(
rchebf12982015-04-10 01:15:004633 reads, arraysize(reads), writes, arraysize(writes)));
[email protected]b261d0e2010-08-02 19:13:244634
4635 helper.AddData(data.get());
[email protected]49639fa2011-12-20 23:22:414636 TestCompletionCallback callback;
[email protected]b261d0e2010-08-02 19:13:244637
[email protected]49639fa2011-12-20 23:22:414638 int rv = trans->Start(
4639 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]b261d0e2010-08-02 19:13:244640 EXPECT_EQ(ERR_IO_PENDING, rv);
4641
4642 rv = callback.WaitForResult();
4643 EXPECT_EQ(0, rv);
4644
4645 // Verify the SYN_REPLY.
4646 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:504647 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]b261d0e2010-08-02 19:13:244648 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
4649
4650 std::string response_data;
4651 ASSERT_EQ(OK, ReadTransaction(trans, &response_data));
4652 EXPECT_EQ("hello!", response_data);
4653 helper.VerifyDataConsumed();
4654}
4655
bncce36dca22015-04-21 22:11:234656// Test to make sure we can correctly connect through a proxy to
4657// www.example.org, if there already exists a direct spdy connection to
4658// www.example.org. See https://crbug.com/49874.
[email protected]513963e2013-06-15 01:53:044659TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
[email protected]b261d0e2010-08-02 19:13:244660 // When setting up the first transaction, we store the SpdySessionPool so that
4661 // we can use the same pool in the second transaction.
[email protected]262eec82013-03-19 21:01:364662 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504663 BoundNetLog(), GetParam(), NULL);
[email protected]733b7a6d2010-08-25 01:38:434664
4665 // Use a proxy service which returns a proxy fallback list from DIRECT to
4666 // myproxy:70. For this test there will be no fallback, so it is equivalent
4667 // to simply DIRECT. The reason for appending the second proxy is to verify
4668 // that the session pool key used does is just "DIRECT".
[email protected]bb88e1d32013-05-03 23:11:074669 helper.session_deps().reset(CreateSpdySessionDependencies(
[email protected]513963e2013-06-15 01:53:044670 GetParam(),
[email protected]733b7a6d2010-08-25 01:38:434671 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
[email protected]00cd9c42010-11-02 20:15:574672 helper.SetSession(make_scoped_refptr(
4673 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
[email protected]733b7a6d2010-08-25 01:38:434674
[email protected]87bfa3f2010-09-30 14:54:564675 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
[email protected]b261d0e2010-08-02 19:13:244676 helper.RunPreTestSetup();
4677
4678 // Construct and send a simple GET request.
[email protected]cdf8f7e72013-05-23 10:56:464679 scoped_ptr<SpdyFrame> req(
4680 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]b261d0e2010-08-02 19:13:244681 MockWrite writes[] = {
rch73e17422015-05-04 19:52:064682 CreateMockWrite(*req, 0),
[email protected]b261d0e2010-08-02 19:13:244683 };
4684
[email protected]513963e2013-06-15 01:53:044685 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4686 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:244687 MockRead reads[] = {
rch73e17422015-05-04 19:52:064688 CreateMockRead(*resp, 1),
4689 CreateMockRead(*body, 2),
4690 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3), // Force a pause
[email protected]b261d0e2010-08-02 19:13:244691 };
rch73e17422015-05-04 19:52:064692 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:574693 helper.AddData(&data);
[email protected]b261d0e2010-08-02 19:13:244694 HttpNetworkTransaction* trans = helper.trans();
4695
[email protected]49639fa2011-12-20 23:22:414696 TestCompletionCallback callback;
[email protected]b261d0e2010-08-02 19:13:244697 TransactionHelperResult out;
[email protected]49639fa2011-12-20 23:22:414698 out.rv = trans->Start(
4699 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]b261d0e2010-08-02 19:13:244700
4701 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4702 out.rv = callback.WaitForResult();
4703 EXPECT_EQ(out.rv, OK);
4704
4705 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:504706 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]b261d0e2010-08-02 19:13:244707 EXPECT_TRUE(response->was_fetched_via_spdy);
4708 out.rv = ReadTransaction(trans, &out.response_data);
4709 EXPECT_EQ(OK, out.rv);
4710 out.status_line = response->headers->GetStatusLine();
4711 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4712 EXPECT_EQ("hello!", out.response_data);
4713
4714 // Check that the SpdySession is still in the SpdySessionPool.
bncce36dca22015-04-21 22:11:234715 HostPortPair host_port_pair("www.example.org", helper.port());
[email protected]e6d017652013-05-17 18:01:404716 SpdySessionKey session_pool_key_direct(
[email protected]314b03992014-04-01 01:28:534717 host_port_pair, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
[email protected]41d64e82013-07-03 22:44:264718 EXPECT_TRUE(HasSpdySession(spdy_session_pool, session_pool_key_direct));
[email protected]e6d017652013-05-17 18:01:404719 SpdySessionKey session_pool_key_proxy(
[email protected]31e68d72010-08-25 06:36:584720 host_port_pair,
[email protected]e6d017652013-05-17 18:01:404721 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP),
[email protected]314b03992014-04-01 01:28:534722 PRIVACY_MODE_DISABLED);
[email protected]41d64e82013-07-03 22:44:264723 EXPECT_FALSE(HasSpdySession(spdy_session_pool, session_pool_key_proxy));
[email protected]b261d0e2010-08-02 19:13:244724
4725 // Set up data for the proxy connection.
bncce36dca22015-04-21 22:11:234726 const char kConnect443[] = {
4727 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4728 "Host: www.example.org\r\n"
4729 "Proxy-Connection: keep-alive\r\n\r\n"};
[email protected]b261d0e2010-08-02 19:13:244730 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
[email protected]cdf8f7e72013-05-23 10:56:464731 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyGet(
rchebf12982015-04-10 01:15:004732 GetDefaultUrlWithPath("/foo.dat").c_str(), false, 1, LOWEST));
[email protected]513963e2013-06-15 01:53:044733 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4734 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:244735
rchebf12982015-04-10 01:15:004736 MockWrite writes2[] = {
4737 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4738 CreateMockWrite(*req2, 2),
[email protected]b261d0e2010-08-02 19:13:244739 };
rchebf12982015-04-10 01:15:004740 MockRead reads2[] = {
4741 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4742 CreateMockRead(*resp2, 3),
4743 CreateMockRead(*body2, 4),
4744 MockRead(ASYNC, 0, 5) // EOF
[email protected]b261d0e2010-08-02 19:13:244745 };
4746
rch73e17422015-05-04 19:52:064747 scoped_ptr<SequencedSocketData> data_proxy(new SequencedSocketData(
rchebf12982015-04-10 01:15:004748 reads2, arraysize(reads2), writes2, arraysize(writes2)));
[email protected]b261d0e2010-08-02 19:13:244749
bncce36dca22015-04-21 22:11:234750 // Create another request to www.example.org, but this time through a proxy.
[email protected]b261d0e2010-08-02 19:13:244751 HttpRequestInfo request_proxy;
4752 request_proxy.method = "GET";
rchebf12982015-04-10 01:15:004753 request_proxy.url = GURL(GetDefaultUrlWithPath("/foo.dat"));
[email protected]b261d0e2010-08-02 19:13:244754 request_proxy.load_flags = 0;
[email protected]bb88e1d32013-05-03 23:11:074755 scoped_ptr<SpdySessionDependencies> ssd_proxy(
[email protected]513963e2013-06-15 01:53:044756 CreateSpdySessionDependencies(GetParam()));
[email protected]b261d0e2010-08-02 19:13:244757 // Ensure that this transaction uses the same SpdySessionPool.
[email protected]ad8e04a2010-11-01 04:16:274758 scoped_refptr<HttpNetworkSession> session_proxy(
4759 SpdySessionDependencies::SpdyCreateSession(ssd_proxy.get()));
[email protected]262eec82013-03-19 21:01:364760 NormalSpdyTransactionHelper helper_proxy(request_proxy, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504761 BoundNetLog(), GetParam(), NULL);
[email protected]87bfa3f2010-09-30 14:54:564762 HttpNetworkSessionPeer session_peer(session_proxy);
bnc301745a2015-03-10 03:22:164763 scoped_ptr<ProxyService> proxy_service(
4764 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
[email protected]6104ea5d2011-04-27 21:37:124765 session_peer.SetProxyService(proxy_service.get());
[email protected]b261d0e2010-08-02 19:13:244766 helper_proxy.session_deps().swap(ssd_proxy);
[email protected]19ec8a72010-08-23 03:38:234767 helper_proxy.SetSession(session_proxy);
[email protected]b261d0e2010-08-02 19:13:244768 helper_proxy.RunPreTestSetup();
4769 helper_proxy.AddData(data_proxy.get());
4770
4771 HttpNetworkTransaction* trans_proxy = helper_proxy.trans();
[email protected]49639fa2011-12-20 23:22:414772 TestCompletionCallback callback_proxy;
4773 int rv = trans_proxy->Start(
4774 &request_proxy, callback_proxy.callback(), BoundNetLog());
[email protected]b261d0e2010-08-02 19:13:244775 EXPECT_EQ(ERR_IO_PENDING, rv);
4776 rv = callback_proxy.WaitForResult();
4777 EXPECT_EQ(0, rv);
4778
4779 HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo();
[email protected]90499482013-06-01 00:39:504780 EXPECT_TRUE(response_proxy.headers.get() != NULL);
[email protected]b261d0e2010-08-02 19:13:244781 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy.headers->GetStatusLine());
4782
4783 std::string response_data;
4784 ASSERT_EQ(OK, ReadTransaction(trans_proxy, &response_data));
4785 EXPECT_EQ("hello!", response_data);
4786
[email protected]b261d0e2010-08-02 19:13:244787 helper_proxy.VerifyDataConsumed();
4788}
4789
[email protected]58cebf8f2010-07-31 19:20:164790// When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
4791// on a new connection, if the connection was previously known to be good.
4792// This can happen when a server reboots without saying goodbye, or when
4793// we're behind a NAT that masked the RST.
[email protected]513963e2013-06-15 01:53:044794TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
[email protected]513963e2013-06-15 01:53:044795 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4796 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]58cebf8f2010-07-31 19:20:164797 MockRead reads[] = {
rch73e17422015-05-04 19:52:064798 CreateMockRead(*resp, 0),
4799 CreateMockRead(*body, 1),
4800 MockRead(ASYNC, ERR_IO_PENDING, 2),
4801 MockRead(ASYNC, ERR_CONNECTION_RESET, 3),
[email protected]58cebf8f2010-07-31 19:20:164802 };
4803
4804 MockRead reads2[] = {
rch73e17422015-05-04 19:52:064805 CreateMockRead(*resp, 0),
4806 CreateMockRead(*body, 1),
4807 MockRead(ASYNC, 0, 2) // EOF
[email protected]58cebf8f2010-07-31 19:20:164808 };
4809
4810 // This test has a couple of variants.
4811 enum {
4812 // Induce the RST while waiting for our transaction to send.
4813 VARIANT_RST_DURING_SEND_COMPLETION,
4814 // Induce the RST while waiting for our transaction to read.
4815 // In this case, the send completed - everything copied into the SNDBUF.
4816 VARIANT_RST_DURING_READ_COMPLETION
4817 };
4818
4819 for (int variant = VARIANT_RST_DURING_SEND_COMPLETION;
4820 variant <= VARIANT_RST_DURING_READ_COMPLETION;
4821 ++variant) {
[email protected]dd54bd82012-07-19 23:44:574822 DelayedSocketData data1(1, reads, arraysize(reads), NULL, 0);
[email protected]58cebf8f2010-07-31 19:20:164823
[email protected]dd54bd82012-07-19 23:44:574824 DelayedSocketData data2(1, reads2, arraysize(reads2), NULL, 0);
[email protected]58cebf8f2010-07-31 19:20:164825
[email protected]262eec82013-03-19 21:01:364826 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504827 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:574828 helper.AddData(&data1);
4829 helper.AddData(&data2);
[email protected]58cebf8f2010-07-31 19:20:164830 helper.RunPreTestSetup();
4831
4832 for (int i = 0; i < 2; ++i) {
4833 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]90499482013-06-01 00:39:504834 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]58cebf8f2010-07-31 19:20:164835
[email protected]49639fa2011-12-20 23:22:414836 TestCompletionCallback callback;
4837 int rv = trans->Start(
4838 &helper.request(), callback.callback(), BoundNetLog());
[email protected]58cebf8f2010-07-31 19:20:164839 EXPECT_EQ(ERR_IO_PENDING, rv);
4840 // On the second transaction, we trigger the RST.
4841 if (i == 1) {
4842 if (variant == VARIANT_RST_DURING_READ_COMPLETION) {
4843 // Writes to the socket complete asynchronously on SPDY by running
4844 // through the message loop. Complete the write here.
[email protected]fc9d88472013-08-14 02:31:174845 base::RunLoop().RunUntilIdle();
[email protected]58cebf8f2010-07-31 19:20:164846 }
4847
4848 // Now schedule the ERR_CONNECTION_RESET.
[email protected]dd54bd82012-07-19 23:44:574849 EXPECT_EQ(3u, data1.read_index());
4850 data1.CompleteRead();
4851 EXPECT_EQ(4u, data1.read_index());
[email protected]58cebf8f2010-07-31 19:20:164852 }
4853 rv = callback.WaitForResult();
4854 EXPECT_EQ(OK, rv);
4855
4856 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]351ab642010-08-05 16:55:314857 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504858 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]58cebf8f2010-07-31 19:20:164859 EXPECT_TRUE(response->was_fetched_via_spdy);
4860 std::string response_data;
4861 rv = ReadTransaction(trans.get(), &response_data);
4862 EXPECT_EQ(OK, rv);
4863 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4864 EXPECT_EQ("hello!", response_data);
4865 }
4866
4867 helper.VerifyDataConsumed();
4868 }
4869}
[email protected]1f418ee2010-10-16 19:46:564870
4871// Test that turning SPDY on and off works properly.
[email protected]513963e2013-06-15 01:53:044872TEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) {
[email protected]d7599122014-05-24 03:37:234873 HttpStreamFactory::set_spdy_enabled(true);
[email protected]cdf8f7e72013-05-23 10:56:464874 scoped_ptr<SpdyFrame> req(
4875 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch73e17422015-05-04 19:52:064876 MockWrite spdy_writes[] = {CreateMockWrite(*req, 0)};
[email protected]1f418ee2010-10-16 19:46:564877
[email protected]513963e2013-06-15 01:53:044878 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4879 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]1f418ee2010-10-16 19:46:564880 MockRead spdy_reads[] = {
rch73e17422015-05-04 19:52:064881 CreateMockRead(*resp, 1),
4882 CreateMockRead(*body, 2),
4883 MockRead(ASYNC, 0, 3) // EOF
[email protected]1f418ee2010-10-16 19:46:564884 };
4885
rch73e17422015-05-04 19:52:064886 SequencedSocketData data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4887 arraysize(spdy_writes));
[email protected]262eec82013-03-19 21:01:364888 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504889 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:574890 helper.RunToCompletion(&data);
[email protected]1f418ee2010-10-16 19:46:564891 TransactionHelperResult out = helper.output();
4892 EXPECT_EQ(OK, out.rv);
4893 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4894 EXPECT_EQ("hello!", out.response_data);
4895
bnc301745a2015-03-10 03:22:164896 HttpStreamFactory::set_spdy_enabled(false);
rch73e17422015-05-04 19:52:064897 MockWrite http_writes[] = {
4898 MockWrite(SYNCHRONOUS, 0,
4899 "GET / HTTP/1.1\r\n"
4900 "Host: www.example.org\r\n"
4901 "Connection: keep-alive\r\n\r\n"),
[email protected]1f418ee2010-10-16 19:46:564902 };
rch73e17422015-05-04 19:52:064903
4904 MockRead http_reads[] = {
4905 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n\r\n"),
4906 MockRead(SYNCHRONOUS, 2, "hello from http"),
4907 MockRead(SYNCHRONOUS, OK, 3),
4908 };
4909 SequencedSocketData data2(http_reads, arraysize(http_reads), http_writes,
4910 arraysize(http_writes));
[email protected]262eec82013-03-19 21:01:364911 NormalSpdyTransactionHelper helper2(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504912 BoundNetLog(), GetParam(), NULL);
[email protected]1f418ee2010-10-16 19:46:564913 helper2.SetSpdyDisabled();
[email protected]dd54bd82012-07-19 23:44:574914 helper2.RunToCompletion(&data2);
[email protected]1f418ee2010-10-16 19:46:564915 TransactionHelperResult out2 = helper2.output();
4916 EXPECT_EQ(OK, out2.rv);
4917 EXPECT_EQ("HTTP/1.1 200 OK", out2.status_line);
4918 EXPECT_EQ("hello from http", out2.response_data);
4919
bnc301745a2015-03-10 03:22:164920 HttpStreamFactory::set_spdy_enabled(true);
[email protected]1f418ee2010-10-16 19:46:564921}
[email protected]018aabc2010-10-29 16:16:594922
4923// Tests that Basic authentication works over SPDY
[email protected]513963e2013-06-15 01:53:044924TEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) {
bnc301745a2015-03-10 03:22:164925 HttpStreamFactory::set_spdy_enabled(true);
[email protected]018aabc2010-10-29 16:16:594926
4927 // The first request will be a bare GET, the second request will be a
4928 // GET with an Authorization header.
[email protected]ff98d7f02012-03-22 21:44:194929 scoped_ptr<SpdyFrame> req_get(
[email protected]cdf8f7e72013-05-23 10:56:464930 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]018aabc2010-10-29 16:16:594931 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:464932 "authorization", "Basic Zm9vOmJhcg=="
[email protected]018aabc2010-10-29 16:16:594933 };
[email protected]ff98d7f02012-03-22 21:44:194934 scoped_ptr<SpdyFrame> req_get_authorization(
[email protected]cdf8f7e72013-05-23 10:56:464935 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
4936 arraysize(kExtraAuthorizationHeaders) / 2,
4937 false, 3, LOWEST, true));
[email protected]018aabc2010-10-29 16:16:594938 MockWrite spdy_writes[] = {
rch73e17422015-05-04 19:52:064939 CreateMockWrite(*req_get, 0), CreateMockWrite(*req_get_authorization, 3),
[email protected]018aabc2010-10-29 16:16:594940 };
4941
4942 // The first response is a 401 authentication challenge, and the second
4943 // response will be a 200 response since the second request includes a valid
4944 // Authorization header.
4945 const char* const kExtraAuthenticationHeaders[] = {
[email protected]fb9e4312012-02-17 06:27:264946 "www-authenticate",
[email protected]018aabc2010-10-29 16:16:594947 "Basic realm=\"MyRealm\""
4948 };
[email protected]ff98d7f02012-03-22 21:44:194949 scoped_ptr<SpdyFrame> resp_authentication(
[email protected]513963e2013-06-15 01:53:044950 spdy_util_.ConstructSpdySynReplyError(
[email protected]018aabc2010-10-29 16:16:594951 "401 Authentication Required",
[email protected]d08358502010-12-03 22:04:034952 kExtraAuthenticationHeaders,
4953 arraysize(kExtraAuthenticationHeaders) / 2,
[email protected]018aabc2010-10-29 16:16:594954 1));
[email protected]ff98d7f02012-03-22 21:44:194955 scoped_ptr<SpdyFrame> body_authentication(
[email protected]513963e2013-06-15 01:53:044956 spdy_util_.ConstructSpdyBodyFrame(1, true));
4957 scoped_ptr<SpdyFrame> resp_data(
4958 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4959 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]018aabc2010-10-29 16:16:594960 MockRead spdy_reads[] = {
rch73e17422015-05-04 19:52:064961 CreateMockRead(*resp_authentication, 1),
4962 CreateMockRead(*body_authentication, 2),
4963 CreateMockRead(*resp_data, 4),
4964 CreateMockRead(*body_data, 5),
4965 MockRead(ASYNC, 0, 6),
[email protected]018aabc2010-10-29 16:16:594966 };
4967
rch73e17422015-05-04 19:52:064968 SequencedSocketData data(spdy_reads, arraysize(spdy_reads), spdy_writes,
4969 arraysize(spdy_writes));
[email protected]018aabc2010-10-29 16:16:594970 HttpRequestInfo request(CreateGetRequest());
4971 BoundNetLog net_log;
[email protected]262eec82013-03-19 21:01:364972 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
4973 net_log, GetParam(), NULL);
[email protected]018aabc2010-10-29 16:16:594974
4975 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574976 helper.AddData(&data);
[email protected]018aabc2010-10-29 16:16:594977 HttpNetworkTransaction* trans = helper.trans();
[email protected]49639fa2011-12-20 23:22:414978 TestCompletionCallback callback;
4979 const int rv_start = trans->Start(&request, callback.callback(), net_log);
[email protected]018aabc2010-10-29 16:16:594980 EXPECT_EQ(ERR_IO_PENDING, rv_start);
[email protected]49639fa2011-12-20 23:22:414981 const int rv_start_complete = callback.WaitForResult();
[email protected]018aabc2010-10-29 16:16:594982 EXPECT_EQ(OK, rv_start_complete);
4983
4984 // Make sure the response has an auth challenge.
4985 const HttpResponseInfo* const response_start = trans->GetResponseInfo();
4986 ASSERT_TRUE(response_start != NULL);
[email protected]90499482013-06-01 00:39:504987 ASSERT_TRUE(response_start->headers.get() != NULL);
[email protected]018aabc2010-10-29 16:16:594988 EXPECT_EQ(401, response_start->headers->response_code());
4989 EXPECT_TRUE(response_start->was_fetched_via_spdy);
[email protected]79cb5c12011-09-12 13:12:044990 AuthChallengeInfo* auth_challenge = response_start->auth_challenge.get();
4991 ASSERT_TRUE(auth_challenge != NULL);
4992 EXPECT_FALSE(auth_challenge->is_proxy);
4993 EXPECT_EQ("basic", auth_challenge->scheme);
4994 EXPECT_EQ("MyRealm", auth_challenge->realm);
[email protected]018aabc2010-10-29 16:16:594995
4996 // Restart with a username/password.
[email protected]ad65a3e2013-12-25 18:18:014997 AuthCredentials credentials(base::ASCIIToUTF16("foo"),
4998 base::ASCIIToUTF16("bar"));
[email protected]49639fa2011-12-20 23:22:414999 TestCompletionCallback callback_restart;
5000 const int rv_restart = trans->RestartWithAuth(
5001 credentials, callback_restart.callback());
[email protected]018aabc2010-10-29 16:16:595002 EXPECT_EQ(ERR_IO_PENDING, rv_restart);
5003 const int rv_restart_complete = callback_restart.WaitForResult();
5004 EXPECT_EQ(OK, rv_restart_complete);
5005 // TODO(cbentzel): This is actually the same response object as before, but
5006 // data has changed.
5007 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
5008 ASSERT_TRUE(response_restart != NULL);
[email protected]90499482013-06-01 00:39:505009 ASSERT_TRUE(response_restart->headers.get() != NULL);
[email protected]018aabc2010-10-29 16:16:595010 EXPECT_EQ(200, response_restart->headers->response_code());
5011 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
5012}
5013
[email protected]513963e2013-06-15 01:53:045014TEST_P(SpdyNetworkTransactionTest, ServerPushWithHeaders) {
[email protected]cdf8f7e72013-05-23 10:56:465015 scoped_ptr<SpdyFrame> stream1_syn(
5016 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:045017 scoped_ptr<SpdyFrame> stream1_body(
5018 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d08358502010-12-03 22:04:035019 MockWrite writes[] = {
rch73e17422015-05-04 19:52:065020 CreateMockWrite(*stream1_syn, 0),
[email protected]d08358502010-12-03 22:04:035021 };
5022
[email protected]513963e2013-06-15 01:53:045023 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
rchebf12982015-04-10 01:15:005024 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
5025 initial_headers.get());
[email protected]4bd46222013-05-14 19:32:235026 scoped_ptr<SpdyFrame> stream2_syn(
[email protected]0338bc62014-06-20 17:09:565027 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
[email protected]513963e2013-06-15 01:53:045028
5029 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5030 (*late_headers)["hello"] = "bye";
5031 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5032 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
[email protected]4bd46222013-05-14 19:32:235033 scoped_ptr<SpdyFrame> stream2_headers(
[email protected]513963e2013-06-15 01:53:045034 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235035 false,
5036 2,
5037 LOWEST,
5038 HEADERS,
5039 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235040 0));
[email protected]d08358502010-12-03 22:04:035041
[email protected]ff98d7f02012-03-22 21:44:195042 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045043 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8a0fc822013-06-27 20:52:435044 const char kPushedData[] = "pushed";
5045 scoped_ptr<SpdyFrame> stream2_body(
5046 spdy_util_.ConstructSpdyBodyFrame(
5047 2, kPushedData, strlen(kPushedData), true));
[email protected]d08358502010-12-03 22:04:035048 MockRead reads[] = {
rch73e17422015-05-04 19:52:065049 CreateMockRead(*stream1_reply, 1),
5050 CreateMockRead(*stream2_syn, 2),
5051 CreateMockRead(*stream2_headers, 3),
5052 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
5053 CreateMockRead(*stream2_body, 5),
5054 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a pause
[email protected]d08358502010-12-03 22:04:035055 };
5056
5057 HttpResponseInfo response;
5058 HttpResponseInfo response2;
5059 std::string expected_push_result("pushed");
rch73e17422015-05-04 19:52:065060 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]dd54bd82012-07-19 23:44:575061 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:035062 &response,
5063 &response2,
5064 expected_push_result);
5065
5066 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:505067 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]d08358502010-12-03 22:04:035068 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5069
5070 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:505071 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]d08358502010-12-03 22:04:035072 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5073}
5074
[email protected]513963e2013-06-15 01:53:045075TEST_P(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
[email protected]d08358502010-12-03 22:04:035076 // We push a stream and attempt to claim it before the headers come down.
[email protected]cdf8f7e72013-05-23 10:56:465077 scoped_ptr<SpdyFrame> stream1_syn(
5078 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:045079 scoped_ptr<SpdyFrame> stream1_body(
5080 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d08358502010-12-03 22:04:035081 MockWrite writes[] = {
[email protected]8ddf8322012-02-23 18:08:065082 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
[email protected]d08358502010-12-03 22:04:035083 };
5084
[email protected]513963e2013-06-15 01:53:045085 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
rchebf12982015-04-10 01:15:005086 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
5087 initial_headers.get());
[email protected]4bd46222013-05-14 19:32:235088 scoped_ptr<SpdyFrame> stream2_syn(
[email protected]0338bc62014-06-20 17:09:565089 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
[email protected]513963e2013-06-15 01:53:045090
5091 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5092 (*late_headers)["hello"] = "bye";
5093 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5094 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
[email protected]4bd46222013-05-14 19:32:235095 scoped_ptr<SpdyFrame> stream2_headers(
[email protected]513963e2013-06-15 01:53:045096 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235097 false,
5098 2,
5099 LOWEST,
5100 HEADERS,
5101 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235102 0));
[email protected]d08358502010-12-03 22:04:035103
[email protected]ff98d7f02012-03-22 21:44:195104 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045105 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8a0fc822013-06-27 20:52:435106 const char kPushedData[] = "pushed";
5107 scoped_ptr<SpdyFrame> stream2_body(
5108 spdy_util_.ConstructSpdyBodyFrame(
5109 2, kPushedData, strlen(kPushedData), true));
[email protected]d08358502010-12-03 22:04:035110 MockRead reads[] = {
5111 CreateMockRead(*stream1_reply, 1),
5112 CreateMockRead(*stream2_syn, 2),
5113 CreateMockRead(*stream1_body, 3),
5114 CreateMockRead(*stream2_headers, 4),
[email protected]8a0fc822013-06-27 20:52:435115 CreateMockRead(*stream2_body, 5),
[email protected]d55b30a2012-07-21 00:35:395116 MockRead(ASYNC, 0, 6), // EOF
[email protected]d08358502010-12-03 22:04:035117 };
5118
5119 HttpResponseInfo response;
5120 HttpResponseInfo response2;
5121 std::string expected_push_result("pushed");
[email protected]dd54bd82012-07-19 23:44:575122 DeterministicSocketData data(reads, arraysize(reads),
5123 writes, arraysize(writes));
[email protected]d08358502010-12-03 22:04:035124
[email protected]262eec82013-03-19 21:01:365125 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505126 BoundNetLog(), GetParam(), NULL);
[email protected]d08358502010-12-03 22:04:035127 helper.SetDeterministic();
[email protected]dd54bd82012-07-19 23:44:575128 helper.AddDeterministicData(&data);
[email protected]d08358502010-12-03 22:04:035129 helper.RunPreTestSetup();
5130
5131 HttpNetworkTransaction* trans = helper.trans();
5132
5133 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5134 // and the body of the primary stream, but before we've received the HEADERS
5135 // for the pushed stream.
[email protected]dd54bd82012-07-19 23:44:575136 data.SetStop(3);
[email protected]d08358502010-12-03 22:04:035137
5138 // Start the transaction.
[email protected]49639fa2011-12-20 23:22:415139 TestCompletionCallback callback;
5140 int rv = trans->Start(
5141 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]d08358502010-12-03 22:04:035142 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]dd54bd82012-07-19 23:44:575143 data.Run();
[email protected]d08358502010-12-03 22:04:035144 rv = callback.WaitForResult();
5145 EXPECT_EQ(0, rv);
5146
5147 // Request the pushed path. At this point, we've received the push, but the
5148 // headers are not yet complete.
5149 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:505150 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]49639fa2011-12-20 23:22:415151 rv = trans2->Start(
5152 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
[email protected]d08358502010-12-03 22:04:035153 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]dd54bd82012-07-19 23:44:575154 data.RunFor(3);
[email protected]fc9d88472013-08-14 02:31:175155 base::RunLoop().RunUntilIdle();
[email protected]d08358502010-12-03 22:04:035156
5157 // Read the server push body.
5158 std::string result2;
[email protected]dd54bd82012-07-19 23:44:575159 ReadResult(trans2.get(), &data, &result2);
[email protected]d08358502010-12-03 22:04:035160 // Read the response body.
5161 std::string result;
[email protected]dd54bd82012-07-19 23:44:575162 ReadResult(trans, &data, &result);
[email protected]d08358502010-12-03 22:04:035163
[email protected]d08358502010-12-03 22:04:035164 // Verify that the received push data is same as the expected push data.
5165 EXPECT_EQ(result2.compare(expected_push_result), 0)
5166 << "Received data: "
5167 << result2
5168 << "||||| Expected data: "
5169 << expected_push_result;
5170
5171 // Verify the SYN_REPLY.
5172 // Copy the response info, because trans goes away.
5173 response = *trans->GetResponseInfo();
5174 response2 = *trans2->GetResponseInfo();
5175
5176 VerifyStreamsClosed(helper);
5177
5178 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:505179 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]d08358502010-12-03 22:04:035180 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5181
5182 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:505183 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]d08358502010-12-03 22:04:035184 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
[email protected]d55b30a2012-07-21 00:35:395185
5186 // Read the final EOF (which will close the session)
5187 data.RunFor(1);
5188
5189 // Verify that we consumed all test data.
rchbce10d972015-05-04 18:21:195190 EXPECT_TRUE(data.AllReadDataConsumed());
5191 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]d08358502010-12-03 22:04:035192}
5193
[email protected]6cd63ba2014-06-12 16:14:565194// TODO(baranovich): HTTP 2 does not allow multiple HEADERS frames
[email protected]513963e2013-06-15 01:53:045195TEST_P(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) {
[email protected]d08358502010-12-03 22:04:035196 // We push a stream and attempt to claim it before the headers come down.
[email protected]cdf8f7e72013-05-23 10:56:465197 scoped_ptr<SpdyFrame> stream1_syn(
5198 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:045199 scoped_ptr<SpdyFrame> stream1_body(
5200 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d08358502010-12-03 22:04:035201 MockWrite writes[] = {
[email protected]8ddf8322012-02-23 18:08:065202 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
[email protected]d08358502010-12-03 22:04:035203 };
5204
[email protected]513963e2013-06-15 01:53:045205 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
[email protected]0338bc62014-06-20 17:09:565206 if (spdy_util_.spdy_version() < SPDY4) {
5207 // In SPDY4 PUSH_PROMISE headers won't show up in the response headers.
5208 (*initial_headers)["alpha"] = "beta";
5209 }
rchebf12982015-04-10 01:15:005210 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
5211 initial_headers.get());
[email protected]4bd46222013-05-14 19:32:235212 scoped_ptr<SpdyFrame> stream2_syn(
[email protected]0338bc62014-06-20 17:09:565213 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
[email protected]513963e2013-06-15 01:53:045214
5215 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5216 (*middle_headers)["hello"] = "bye";
[email protected]4bd46222013-05-14 19:32:235217 scoped_ptr<SpdyFrame> stream2_headers1(
[email protected]513963e2013-06-15 01:53:045218 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235219 false,
5220 2,
5221 LOWEST,
5222 HEADERS,
5223 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235224 0));
[email protected]513963e2013-06-15 01:53:045225
5226 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5227 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
[email protected]601e03f12014-04-06 16:26:395228 if (spdy_util_.spdy_version() < SPDY4) {
5229 // SPDY4/HTTP2 eliminates use of the :version header.
5230 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5231 }
[email protected]4bd46222013-05-14 19:32:235232 scoped_ptr<SpdyFrame> stream2_headers2(
[email protected]513963e2013-06-15 01:53:045233 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235234 false,
5235 2,
5236 LOWEST,
5237 HEADERS,
5238 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235239 0));
[email protected]d08358502010-12-03 22:04:035240
[email protected]ff98d7f02012-03-22 21:44:195241 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045242 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8a0fc822013-06-27 20:52:435243 const char kPushedData[] = "pushed";
5244 scoped_ptr<SpdyFrame> stream2_body(
5245 spdy_util_.ConstructSpdyBodyFrame(
5246 2, kPushedData, strlen(kPushedData), true));
[email protected]d08358502010-12-03 22:04:035247 MockRead reads[] = {
5248 CreateMockRead(*stream1_reply, 1),
5249 CreateMockRead(*stream2_syn, 2),
5250 CreateMockRead(*stream1_body, 3),
5251 CreateMockRead(*stream2_headers1, 4),
5252 CreateMockRead(*stream2_headers2, 5),
[email protected]8a0fc822013-06-27 20:52:435253 CreateMockRead(*stream2_body, 6),
[email protected]d55b30a2012-07-21 00:35:395254 MockRead(ASYNC, 0, 7), // EOF
[email protected]d08358502010-12-03 22:04:035255 };
5256
5257 HttpResponseInfo response;
5258 HttpResponseInfo response2;
5259 std::string expected_push_result("pushed");
[email protected]dd54bd82012-07-19 23:44:575260 DeterministicSocketData data(reads, arraysize(reads),
5261 writes, arraysize(writes));
[email protected]d08358502010-12-03 22:04:035262
[email protected]262eec82013-03-19 21:01:365263 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505264 BoundNetLog(), GetParam(), NULL);
[email protected]d08358502010-12-03 22:04:035265 helper.SetDeterministic();
[email protected]dd54bd82012-07-19 23:44:575266 helper.AddDeterministicData(&data);
[email protected]d08358502010-12-03 22:04:035267 helper.RunPreTestSetup();
5268
5269 HttpNetworkTransaction* trans = helper.trans();
5270
5271 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5272 // the first HEADERS frame, and the body of the primary stream, but before
5273 // we've received the final HEADERS for the pushed stream.
[email protected]dd54bd82012-07-19 23:44:575274 data.SetStop(4);
[email protected]d08358502010-12-03 22:04:035275
5276 // Start the transaction.
[email protected]49639fa2011-12-20 23:22:415277 TestCompletionCallback callback;
5278 int rv = trans->Start(
5279 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]d08358502010-12-03 22:04:035280 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]dd54bd82012-07-19 23:44:575281 data.Run();
[email protected]d08358502010-12-03 22:04:035282 rv = callback.WaitForResult();
5283 EXPECT_EQ(0, rv);
5284
5285 // Request the pushed path. At this point, we've received the push, but the
5286 // headers are not yet complete.
5287 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:505288 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]49639fa2011-12-20 23:22:415289 rv = trans2->Start(
5290 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
[email protected]d08358502010-12-03 22:04:035291 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]dd54bd82012-07-19 23:44:575292 data.RunFor(3);
[email protected]fc9d88472013-08-14 02:31:175293 base::RunLoop().RunUntilIdle();
[email protected]d08358502010-12-03 22:04:035294
5295 // Read the server push body.
5296 std::string result2;
[email protected]dd54bd82012-07-19 23:44:575297 ReadResult(trans2.get(), &data, &result2);
[email protected]d08358502010-12-03 22:04:035298 // Read the response body.
5299 std::string result;
[email protected]dd54bd82012-07-19 23:44:575300 ReadResult(trans, &data, &result);
[email protected]d08358502010-12-03 22:04:035301
[email protected]d08358502010-12-03 22:04:035302 // Verify that the received push data is same as the expected push data.
[email protected]6d116e1a2013-06-24 07:42:155303 EXPECT_EQ(expected_push_result, result2);
[email protected]d08358502010-12-03 22:04:035304
5305 // Verify the SYN_REPLY.
5306 // Copy the response info, because trans goes away.
5307 response = *trans->GetResponseInfo();
5308 response2 = *trans2->GetResponseInfo();
5309
5310 VerifyStreamsClosed(helper);
5311
5312 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:505313 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]d08358502010-12-03 22:04:035314 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5315
5316 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:505317 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]d08358502010-12-03 22:04:035318 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5319
[email protected]6cd63ba2014-06-12 16:14:565320 // Verify we got all the headers from all header blocks.
[email protected]0338bc62014-06-20 17:09:565321 if (spdy_util_.spdy_version() < SPDY4)
5322 EXPECT_TRUE(response2.headers->HasHeaderValue("alpha", "beta"));
[email protected]d08358502010-12-03 22:04:035323 EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye"));
5324 EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200"));
[email protected]d55b30a2012-07-21 00:35:395325
5326 // Read the final EOF (which will close the session)
5327 data.RunFor(1);
5328
5329 // Verify that we consumed all test data.
rchbce10d972015-05-04 18:21:195330 EXPECT_TRUE(data.AllReadDataConsumed());
5331 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]d08358502010-12-03 22:04:035332}
5333
[email protected]513963e2013-06-15 01:53:045334TEST_P(SpdyNetworkTransactionTest, ServerPushWithNoStatusHeaderFrames) {
[email protected]5c6908e2012-08-06 18:53:475335 // We push a stream and attempt to claim it before the headers come down.
[email protected]cdf8f7e72013-05-23 10:56:465336 scoped_ptr<SpdyFrame> stream1_syn(
5337 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:045338 scoped_ptr<SpdyFrame> stream1_body(
5339 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]5c6908e2012-08-06 18:53:475340 MockWrite writes[] = {
5341 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5342 };
5343
[email protected]513963e2013-06-15 01:53:045344 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
rchebf12982015-04-10 01:15:005345 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/foo.dat"),
5346 initial_headers.get());
[email protected]4bd46222013-05-14 19:32:235347 scoped_ptr<SpdyFrame> stream2_syn(
[email protected]0338bc62014-06-20 17:09:565348 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
[email protected]513963e2013-06-15 01:53:045349
5350 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5351 (*middle_headers)["hello"] = "bye";
[email protected]4bd46222013-05-14 19:32:235352 scoped_ptr<SpdyFrame> stream2_headers1(
[email protected]513963e2013-06-15 01:53:045353 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235354 false,
5355 2,
5356 LOWEST,
5357 HEADERS,
5358 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235359 0));
[email protected]5c6908e2012-08-06 18:53:475360
5361 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045362 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8a0fc822013-06-27 20:52:435363 const char kPushedData[] = "pushed";
5364 scoped_ptr<SpdyFrame> stream2_body(
5365 spdy_util_.ConstructSpdyBodyFrame(
5366 2, kPushedData, strlen(kPushedData), true));
[email protected]5c6908e2012-08-06 18:53:475367 MockRead reads[] = {
5368 CreateMockRead(*stream1_reply, 1),
5369 CreateMockRead(*stream2_syn, 2),
5370 CreateMockRead(*stream1_body, 3),
5371 CreateMockRead(*stream2_headers1, 4),
[email protected]8a0fc822013-06-27 20:52:435372 CreateMockRead(*stream2_body, 5),
[email protected]5c6908e2012-08-06 18:53:475373 MockRead(ASYNC, 0, 6), // EOF
5374 };
5375
5376 DeterministicSocketData data(reads, arraysize(reads),
5377 writes, arraysize(writes));
5378
[email protected]262eec82013-03-19 21:01:365379 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]5c6908e2012-08-06 18:53:475380 BoundNetLog(), GetParam(), NULL);
5381 helper.SetDeterministic();
5382 helper.AddDeterministicData(&data);
5383 helper.RunPreTestSetup();
5384
5385 HttpNetworkTransaction* trans = helper.trans();
5386
5387 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5388 // the first HEADERS frame, and the body of the primary stream, but before
5389 // we've received the final HEADERS for the pushed stream.
5390 data.SetStop(4);
5391
5392 // Start the transaction.
5393 TestCompletionCallback callback;
5394 int rv = trans->Start(
5395 &CreateGetRequest(), callback.callback(), BoundNetLog());
5396 EXPECT_EQ(ERR_IO_PENDING, rv);
5397 data.Run();
5398 rv = callback.WaitForResult();
5399 EXPECT_EQ(0, rv);
5400
5401 // Request the pushed path. At this point, we've received the push, but the
5402 // headers are not yet complete.
5403 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:505404 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]5c6908e2012-08-06 18:53:475405 rv = trans2->Start(
5406 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5407 EXPECT_EQ(ERR_IO_PENDING, rv);
5408 data.RunFor(2);
[email protected]fc9d88472013-08-14 02:31:175409 base::RunLoop().RunUntilIdle();
[email protected]5c6908e2012-08-06 18:53:475410
5411 // Read the server push body.
5412 std::string result2;
5413 ReadResult(trans2.get(), &data, &result2);
5414 // Read the response body.
5415 std::string result;
5416 ReadResult(trans, &data, &result);
5417 EXPECT_EQ("hello!", result);
5418
5419 // Verify that we haven't received any push data.
5420 EXPECT_EQ("", result2);
5421
5422 // Verify the SYN_REPLY.
5423 // Copy the response info, because trans goes away.
5424 HttpResponseInfo response = *trans->GetResponseInfo();
5425 ASSERT_TRUE(trans2->GetResponseInfo() == NULL);
5426
5427 VerifyStreamsClosed(helper);
5428
5429 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:505430 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]5c6908e2012-08-06 18:53:475431 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5432
5433 // Read the final EOF (which will close the session).
5434 data.RunFor(1);
5435
5436 // Verify that we consumed all test data.
rchbce10d972015-05-04 18:21:195437 EXPECT_TRUE(data.AllReadDataConsumed());
5438 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]5c6908e2012-08-06 18:53:475439}
5440
[email protected]513963e2013-06-15 01:53:045441TEST_P(SpdyNetworkTransactionTest, SynReplyWithHeaders) {
[email protected]cdf8f7e72013-05-23 10:56:465442 scoped_ptr<SpdyFrame> req(
5443 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]b771bb72013-06-24 09:55:415444 scoped_ptr<SpdyFrame> rst(
5445 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
5446 MockWrite writes[] = {
rch73e17422015-05-04 19:52:065447 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
[email protected]745aa9c2014-06-27 02:21:295448 };
[email protected]d08358502010-12-03 22:04:035449
[email protected]4bd46222013-05-14 19:32:235450 scoped_ptr<SpdyFrame> stream1_reply(
[email protected]745aa9c2014-06-27 02:21:295451 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:045452
5453 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5454 (*late_headers)["hello"] = "bye";
[email protected]4bd46222013-05-14 19:32:235455 scoped_ptr<SpdyFrame> stream1_headers(
[email protected]513963e2013-06-15 01:53:045456 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235457 false,
5458 1,
5459 LOWEST,
5460 HEADERS,
5461 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235462 0));
[email protected]513963e2013-06-15 01:53:045463 scoped_ptr<SpdyFrame> stream1_body(
5464 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d08358502010-12-03 22:04:035465 MockRead reads[] = {
rch73e17422015-05-04 19:52:065466 CreateMockRead(*stream1_reply, 1),
5467 CreateMockRead(*stream1_headers, 2),
5468 CreateMockRead(*stream1_body, 3),
5469 MockRead(ASYNC, 0, 5) // EOF
[email protected]d08358502010-12-03 22:04:035470 };
5471
rch73e17422015-05-04 19:52:065472 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:365473 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505474 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:575475 helper.RunToCompletion(&data);
[email protected]d08358502010-12-03 22:04:035476 TransactionHelperResult out = helper.output();
[email protected]b771bb72013-06-24 09:55:415477 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]d08358502010-12-03 22:04:035478}
5479
[email protected]513963e2013-06-15 01:53:045480TEST_P(SpdyNetworkTransactionTest, SynReplyWithLateHeaders) {
[email protected]cdf8f7e72013-05-23 10:56:465481 scoped_ptr<SpdyFrame> req(
5482 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]b771bb72013-06-24 09:55:415483 scoped_ptr<SpdyFrame> rst(
5484 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
5485 MockWrite writes[] = {
rch73e17422015-05-04 19:52:065486 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
[email protected]b771bb72013-06-24 09:55:415487 };
[email protected]d08358502010-12-03 22:04:035488
[email protected]4bd46222013-05-14 19:32:235489 scoped_ptr<SpdyFrame> stream1_reply(
[email protected]745aa9c2014-06-27 02:21:295490 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:045491
5492 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5493 (*late_headers)["hello"] = "bye";
[email protected]4bd46222013-05-14 19:32:235494 scoped_ptr<SpdyFrame> stream1_headers(
[email protected]513963e2013-06-15 01:53:045495 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235496 false,
5497 1,
5498 LOWEST,
5499 HEADERS,
5500 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235501 0));
[email protected]513963e2013-06-15 01:53:045502 scoped_ptr<SpdyFrame> stream1_body(
5503 spdy_util_.ConstructSpdyBodyFrame(1, false));
5504 scoped_ptr<SpdyFrame> stream1_body2(
5505 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d08358502010-12-03 22:04:035506 MockRead reads[] = {
rch73e17422015-05-04 19:52:065507 CreateMockRead(*stream1_reply, 1),
5508 CreateMockRead(*stream1_body, 2),
5509 CreateMockRead(*stream1_headers, 3),
5510 CreateMockRead(*stream1_body2, 5),
5511 MockRead(ASYNC, 0, 6) // EOF
[email protected]d08358502010-12-03 22:04:035512 };
5513
[email protected]dd54bd82012-07-19 23:44:575514 DelayedSocketData data(1, reads, arraysize(reads),
5515 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:365516 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505517 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:575518 helper.RunToCompletion(&data);
[email protected]d08358502010-12-03 22:04:035519 TransactionHelperResult out = helper.output();
[email protected]b771bb72013-06-24 09:55:415520 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]d08358502010-12-03 22:04:035521}
5522
[email protected]513963e2013-06-15 01:53:045523TEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
rchebf12982015-04-10 01:15:005524 // Running these tests via Alt-Svc is too complicated to be worthwhile.
5525 if (GetParam().ssl_type != HTTPS_SPDY_VIA_NPN)
5526 return;
5527
[email protected]a7a265ef2010-12-08 18:05:575528 // In this test we want to verify that we can't accidentally push content
5529 // which can't be pushed by this content server.
5530 // This test assumes that:
5531 // - if we're requesting http://www.foo.com/barbaz
5532 // - the browser has made a connection to "www.foo.com".
5533
5534 // A list of the URL to fetch, followed by the URL being pushed.
5535 static const char* const kTestCases[] = {
bncce36dca22015-04-21 22:11:235536 "https://www.example.org/foo.html",
5537 "https://www.example.org:81/foo.js", // Bad port
[email protected]a7a265ef2010-12-08 18:05:575538
bncce36dca22015-04-21 22:11:235539 "https://www.example.org/foo.html",
5540 "http://www.example.org/foo.js", // Bad protocol
[email protected]a7a265ef2010-12-08 18:05:575541
bncce36dca22015-04-21 22:11:235542 "https://www.example.org/foo.html",
5543 "ftp://www.example.org/foo.js", // Invalid Protocol
[email protected]a7a265ef2010-12-08 18:05:575544
bncce36dca22015-04-21 22:11:235545 "https://www.example.org/foo.html",
5546 "https://blat.www.example.org/foo.js", // Cross subdomain
[email protected]a7a265ef2010-12-08 18:05:575547
bncce36dca22015-04-21 22:11:235548 "https://www.example.org/foo.html",
rchebf12982015-04-10 01:15:005549 "https://www.foo.com/foo.js", // Cross domain
[email protected]a7a265ef2010-12-08 18:05:575550 };
5551
[email protected]b3f899332010-12-08 18:20:445552 for (size_t index = 0; index < arraysize(kTestCases); index += 2) {
[email protected]a7a265ef2010-12-08 18:05:575553 const char* url_to_fetch = kTestCases[index];
5554 const char* url_to_push = kTestCases[index + 1];
5555
[email protected]cdf8f7e72013-05-23 10:56:465556 scoped_ptr<SpdyFrame> stream1_syn(
5557 spdy_util_.ConstructSpdyGet(url_to_fetch, false, 1, LOWEST));
[email protected]513963e2013-06-15 01:53:045558 scoped_ptr<SpdyFrame> stream1_body(
5559 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]ff98d7f02012-03-22 21:44:195560 scoped_ptr<SpdyFrame> push_rst(
[email protected]c10b20852013-05-15 21:29:205561 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
[email protected]a7a265ef2010-12-08 18:05:575562 MockWrite writes[] = {
rch73e17422015-05-04 19:52:065563 CreateMockWrite(*stream1_syn, 0), CreateMockWrite(*push_rst, 3),
[email protected]a7a265ef2010-12-08 18:05:575564 };
5565
[email protected]ff98d7f02012-03-22 21:44:195566 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045567 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]ff98d7f02012-03-22 21:44:195568 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045569 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
5570 0,
5571 2,
5572 1,
5573 url_to_push));
[email protected]8a0fc822013-06-27 20:52:435574 const char kPushedData[] = "pushed";
5575 scoped_ptr<SpdyFrame> stream2_body(
5576 spdy_util_.ConstructSpdyBodyFrame(
5577 2, kPushedData, strlen(kPushedData), true));
[email protected]ff98d7f02012-03-22 21:44:195578 scoped_ptr<SpdyFrame> rst(
[email protected]c10b20852013-05-15 21:29:205579 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
[email protected]a7a265ef2010-12-08 18:05:575580
5581 MockRead reads[] = {
rch73e17422015-05-04 19:52:065582 CreateMockRead(*stream1_reply, 1),
5583 CreateMockRead(*stream2_syn, 2),
5584 CreateMockRead(*stream1_body, 4),
5585 CreateMockRead(*stream2_body, 5),
5586 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6), // Force a pause
[email protected]a7a265ef2010-12-08 18:05:575587 };
5588
5589 HttpResponseInfo response;
rch73e17422015-05-04 19:52:065590 SequencedSocketData data(reads, arraysize(reads), writes,
5591 arraysize(writes));
[email protected]a7a265ef2010-12-08 18:05:575592
5593 HttpRequestInfo request;
5594 request.method = "GET";
5595 request.url = GURL(url_to_fetch);
5596 request.load_flags = 0;
[email protected]a7a265ef2010-12-08 18:05:575597
[email protected]7c6f7ba2012-04-03 04:09:295598 // Enable cross-origin push. Since we are not using a proxy, this should
5599 // not actually enable cross-origin SPDY push.
[email protected]61b4efc2012-04-27 18:12:505600 scoped_ptr<SpdySessionDependencies> session_deps(
[email protected]513963e2013-06-15 01:53:045601 CreateSpdySessionDependencies(GetParam()));
[email protected]61b4efc2012-04-27 18:12:505602 session_deps->trusted_spdy_proxy = "123.45.67.89:8080";
[email protected]262eec82013-03-19 21:01:365603 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505604 BoundNetLog(), GetParam(),
5605 session_deps.release());
5606 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:575607 helper.AddData(&data);
[email protected]7c6f7ba2012-04-03 04:09:295608
[email protected]a7a265ef2010-12-08 18:05:575609 HttpNetworkTransaction* trans = helper.trans();
5610
5611 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:415612 TestCompletionCallback callback;
[email protected]a7a265ef2010-12-08 18:05:575613
[email protected]49639fa2011-12-20 23:22:415614 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]a7a265ef2010-12-08 18:05:575615 EXPECT_EQ(ERR_IO_PENDING, rv);
5616 rv = callback.WaitForResult();
5617
5618 // Read the response body.
5619 std::string result;
[email protected]dd54bd82012-07-19 23:44:575620 ReadResult(trans, &data, &result);
[email protected]a7a265ef2010-12-08 18:05:575621
5622 // Verify that we consumed all test data.
rchbce10d972015-05-04 18:21:195623 EXPECT_TRUE(data.AllReadDataConsumed());
5624 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]a7a265ef2010-12-08 18:05:575625
5626 // Verify the SYN_REPLY.
5627 // Copy the response info, because trans goes away.
5628 response = *trans->GetResponseInfo();
5629
5630 VerifyStreamsClosed(helper);
5631
5632 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:505633 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]a7a265ef2010-12-08 18:05:575634 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5635 }
5636}
5637
[email protected]513963e2013-06-15 01:53:045638TEST_P(SpdyNetworkTransactionTest, RetryAfterRefused) {
[email protected]721c0ce2011-10-13 02:41:005639 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:465640 scoped_ptr<SpdyFrame> req(
5641 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5642 scoped_ptr<SpdyFrame> req2(
5643 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]721c0ce2011-10-13 02:41:005644 MockWrite writes[] = {
rch73e17422015-05-04 19:52:065645 CreateMockWrite(*req, 0), CreateMockWrite(*req2, 2),
[email protected]721c0ce2011-10-13 02:41:005646 };
5647
[email protected]ff98d7f02012-03-22 21:44:195648 scoped_ptr<SpdyFrame> refused(
[email protected]c10b20852013-05-15 21:29:205649 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
[email protected]513963e2013-06-15 01:53:045650 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5651 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]721c0ce2011-10-13 02:41:005652 MockRead reads[] = {
rch73e17422015-05-04 19:52:065653 CreateMockRead(*refused, 1),
5654 CreateMockRead(*resp, 3),
5655 CreateMockRead(*body, 4),
5656 MockRead(ASYNC, 0, 5) // EOF
[email protected]721c0ce2011-10-13 02:41:005657 };
5658
rch73e17422015-05-04 19:52:065659 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:365660 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505661 BoundNetLog(), GetParam(), NULL);
[email protected]721c0ce2011-10-13 02:41:005662
5663 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:575664 helper.AddData(&data);
[email protected]721c0ce2011-10-13 02:41:005665
5666 HttpNetworkTransaction* trans = helper.trans();
5667
5668 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:415669 TestCompletionCallback callback;
5670 int rv = trans->Start(
5671 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]721c0ce2011-10-13 02:41:005672 EXPECT_EQ(ERR_IO_PENDING, rv);
5673 rv = callback.WaitForResult();
5674 EXPECT_EQ(OK, rv);
5675
5676 // Verify that we consumed all test data.
rch73e17422015-05-04 19:52:065677 EXPECT_TRUE(data.AllReadDataConsumed());
5678 EXPECT_TRUE(data.AllWriteDataConsumed());
[email protected]721c0ce2011-10-13 02:41:005679
5680 // Verify the SYN_REPLY.
5681 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:505682 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]721c0ce2011-10-13 02:41:005683 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5684}
5685
[email protected]513963e2013-06-15 01:53:045686TEST_P(SpdyNetworkTransactionTest, OutOfOrderSynStream) {
[email protected]e1f58efa2012-05-15 18:23:405687 // This first request will start to establish the SpdySession.
5688 // Then we will start the second (MEDIUM priority) and then third
5689 // (HIGHEST priority) request in such a way that the third will actually
[email protected]c92f4b4542012-07-26 23:53:215690 // start before the second, causing the second to be numbered differently
[email protected]513963e2013-06-15 01:53:045691 // than the order they were created.
[email protected]cdf8f7e72013-05-23 10:56:465692 scoped_ptr<SpdyFrame> req1(
5693 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5694 scoped_ptr<SpdyFrame> req2(
5695 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, HIGHEST, true));
5696 scoped_ptr<SpdyFrame> req3(
5697 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, MEDIUM, true));
[email protected]e1f58efa2012-05-15 18:23:405698 MockWrite writes[] = {
5699 CreateMockWrite(*req1, 0),
5700 CreateMockWrite(*req2, 3),
5701 CreateMockWrite(*req3, 4),
5702 };
5703
[email protected]513963e2013-06-15 01:53:045704 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5705 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
5706 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5707 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
5708 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
5709 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
[email protected]e1f58efa2012-05-15 18:23:405710 MockRead reads[] = {
5711 CreateMockRead(*resp1, 1),
5712 CreateMockRead(*body1, 2),
5713 CreateMockRead(*resp2, 5),
5714 CreateMockRead(*body2, 6),
5715 CreateMockRead(*resp3, 7),
5716 CreateMockRead(*body3, 8),
5717 MockRead(ASYNC, 0, 9) // EOF
5718 };
5719
[email protected]dd54bd82012-07-19 23:44:575720 DeterministicSocketData data(reads, arraysize(reads),
[email protected]513963e2013-06-15 01:53:045721 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:365722 NormalSpdyTransactionHelper helper(CreateGetRequest(), LOWEST,
[email protected]e1f58efa2012-05-15 18:23:405723 BoundNetLog(), GetParam(), NULL);
5724 helper.SetDeterministic();
5725 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:575726 helper.AddDeterministicData(&data);
[email protected]e1f58efa2012-05-15 18:23:405727
5728 // Start the first transaction to set up the SpdySession
5729 HttpNetworkTransaction* trans = helper.trans();
5730 TestCompletionCallback callback;
5731 HttpRequestInfo info1 = CreateGetRequest();
[email protected]e1f58efa2012-05-15 18:23:405732 int rv = trans->Start(&info1, callback.callback(), BoundNetLog());
5733 EXPECT_EQ(ERR_IO_PENDING, rv);
5734
5735 // Run the message loop, but do not allow the write to complete.
5736 // This leaves the SpdySession with a write pending, which prevents
5737 // SpdySession from attempting subsequent writes until this write completes.
[email protected]fc9d88472013-08-14 02:31:175738 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:405739
5740 // Now, start both new transactions
5741 HttpRequestInfo info2 = CreateGetRequest();
[email protected]e1f58efa2012-05-15 18:23:405742 TestCompletionCallback callback2;
[email protected]90499482013-06-01 00:39:505743 scoped_ptr<HttpNetworkTransaction> trans2(
5744 new HttpNetworkTransaction(MEDIUM, helper.session().get()));
[email protected]e1f58efa2012-05-15 18:23:405745 rv = trans2->Start(&info2, callback2.callback(), BoundNetLog());
5746 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]fc9d88472013-08-14 02:31:175747 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:405748
5749 HttpRequestInfo info3 = CreateGetRequest();
[email protected]e1f58efa2012-05-15 18:23:405750 TestCompletionCallback callback3;
5751 scoped_ptr<HttpNetworkTransaction> trans3(
[email protected]90499482013-06-01 00:39:505752 new HttpNetworkTransaction(HIGHEST, helper.session().get()));
[email protected]e1f58efa2012-05-15 18:23:405753 rv = trans3->Start(&info3, callback3.callback(), BoundNetLog());
5754 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]fc9d88472013-08-14 02:31:175755 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:405756
5757 // We now have two SYN_STREAM frames queued up which will be
5758 // dequeued only once the first write completes, which we
5759 // now allow to happen.
[email protected]dd54bd82012-07-19 23:44:575760 data.RunFor(2);
[email protected]e1f58efa2012-05-15 18:23:405761 EXPECT_EQ(OK, callback.WaitForResult());
5762
5763 // And now we can allow everything else to run to completion.
[email protected]dd54bd82012-07-19 23:44:575764 data.SetStop(10);
5765 data.Run();
[email protected]e1f58efa2012-05-15 18:23:405766 EXPECT_EQ(OK, callback2.WaitForResult());
5767 EXPECT_EQ(OK, callback3.WaitForResult());
5768
5769 helper.VerifyDataConsumed();
5770}
5771
[email protected]d11b6912013-06-27 23:07:325772// The tests below are only for SPDY/3 and above.
5773
5774// Test that sent data frames and received WINDOW_UPDATE frames change
5775// the send_window_size_ correctly.
5776
5777// WINDOW_UPDATE is different than most other frames in that it can arrive
5778// while the client is still sending the request body. In order to enforce
5779// this scenario, we feed a couple of dummy frames and give a delay of 0 to
5780// socket data provider, so that initial read that is done as soon as the
5781// stream is created, succeeds and schedules another read. This way reads
5782// and writes are interleaved; after doing a full frame write, SpdyStream
5783// will break out of DoLoop and will read and process a WINDOW_UPDATE.
5784// Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
5785// since request has not been completely written, therefore we feed
5786// enough number of WINDOW_UPDATEs to finish the first read and cause a
5787// write, leading to a complete write of request body; after that we send
5788// a reply with a body, to cause a graceful shutdown.
5789
5790// TODO(agayev): develop a socket data provider where both, reads and
5791// writes are ordered so that writing tests like these are easy and rewrite
5792// all these tests using it. Right now we are working around the
5793// limitations as described above and it's not deterministic, tests may
5794// fail under specific circumstances.
5795TEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) {
[email protected]d11b6912013-06-27 23:07:325796 static int kFrameCount = 2;
5797 scoped_ptr<std::string> content(
5798 new std::string(kMaxSpdyFrameChunkSize, 'a'));
5799 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
rchebf12982015-04-10 01:15:005800 GetDefaultUrl(), 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL,
5801 0));
[email protected]d11b6912013-06-27 23:07:325802 scoped_ptr<SpdyFrame> body(
5803 spdy_util_.ConstructSpdyBodyFrame(
5804 1, content->c_str(), content->size(), false));
5805 scoped_ptr<SpdyFrame> body_end(
5806 spdy_util_.ConstructSpdyBodyFrame(
5807 1, content->c_str(), content->size(), true));
5808
5809 MockWrite writes[] = {
5810 CreateMockWrite(*req, 0),
5811 CreateMockWrite(*body, 1),
5812 CreateMockWrite(*body_end, 2),
5813 };
5814
5815 static const int32 kDeltaWindowSize = 0xff;
5816 static const int kDeltaCount = 4;
5817 scoped_ptr<SpdyFrame> window_update(
5818 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
5819 scoped_ptr<SpdyFrame> window_update_dummy(
5820 spdy_util_.ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
5821 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
5822 MockRead reads[] = {
5823 CreateMockRead(*window_update_dummy, 3),
5824 CreateMockRead(*window_update_dummy, 4),
5825 CreateMockRead(*window_update_dummy, 5),
5826 CreateMockRead(*window_update, 6), // Four updates, therefore window
5827 CreateMockRead(*window_update, 7), // size should increase by
5828 CreateMockRead(*window_update, 8), // kDeltaWindowSize * 4
5829 CreateMockRead(*window_update, 9),
5830 CreateMockRead(*resp, 10),
5831 CreateMockRead(*body_end, 11),
5832 MockRead(ASYNC, 0, 0, 12) // EOF
5833 };
5834
5835 DeterministicSocketData data(reads, arraysize(reads),
5836 writes, arraysize(writes));
5837
5838 ScopedVector<UploadElementReader> element_readers;
5839 for (int i = 0; i < kFrameCount; ++i) {
5840 element_readers.push_back(
5841 new UploadBytesElementReader(content->c_str(), content->size()));
5842 }
mmenkecbc2b712014-10-09 20:29:075843 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]d11b6912013-06-27 23:07:325844
5845 // Setup the request
5846 HttpRequestInfo request;
5847 request.method = "POST";
rchebf12982015-04-10 01:15:005848 request.url = GURL(GetDefaultUrl());
[email protected]d11b6912013-06-27 23:07:325849 request.upload_data_stream = &upload_data_stream;
5850
5851 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5852 BoundNetLog(), GetParam(), NULL);
5853 helper.SetDeterministic();
5854 helper.AddDeterministicData(&data);
5855 helper.RunPreTestSetup();
5856
5857 HttpNetworkTransaction* trans = helper.trans();
5858
5859 TestCompletionCallback callback;
5860 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5861
5862 EXPECT_EQ(ERR_IO_PENDING, rv);
5863
5864 data.RunFor(11);
5865
5866 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
5867 ASSERT_TRUE(stream != NULL);
5868 ASSERT_TRUE(stream->stream() != NULL);
bnc638c4702015-04-09 18:01:185869 EXPECT_EQ(static_cast<int>(
5870 SpdySession::GetDefaultInitialWindowSize(GetParam().protocol)) +
5871 kDeltaWindowSize * kDeltaCount -
5872 kMaxSpdyFrameChunkSize * kFrameCount,
5873 stream->stream()->send_window_size());
[email protected]d11b6912013-06-27 23:07:325874
5875 data.RunFor(1);
5876
5877 rv = callback.WaitForResult();
5878 EXPECT_EQ(OK, rv);
5879
5880 helper.VerifyDataConsumed();
5881}
5882
5883// Test that received data frames and sent WINDOW_UPDATE frames change
5884// the recv_window_size_ correctly.
5885TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) {
bnc8f0f3b62015-04-08 04:37:235886 const int32 default_initial_window_size =
bnc638c4702015-04-09 18:01:185887 SpdySession::GetDefaultInitialWindowSize(GetParam().protocol);
bnc8f0f3b62015-04-08 04:37:235888 // Session level maximum window size that is more than twice the default
5889 // initial window size so that an initial window update is sent.
5890 const int32 session_max_recv_window_size = 5 * 64 * 1024;
5891 ASSERT_LT(2 * default_initial_window_size, session_max_recv_window_size);
5892 // Stream level maximum window size that is less than the session level
5893 // maximum window size so that we test for confusion between the two.
5894 const int32 stream_max_recv_window_size = 4 * 64 * 1024;
5895 ASSERT_GT(session_max_recv_window_size, stream_max_recv_window_size);
5896 // Size of body to be sent. Has to be less than or equal to both window sizes
5897 // so that we do not run out of receiving window. Also has to be greater than
5898 // half of them so that it triggers both a session level and a stream level
5899 // window update frame.
5900 const int32 kTargetSize = 3 * 64 * 1024;
5901 ASSERT_GE(session_max_recv_window_size, kTargetSize);
5902 ASSERT_GE(stream_max_recv_window_size, kTargetSize);
5903 ASSERT_LT(session_max_recv_window_size / 2, kTargetSize);
5904 ASSERT_LT(stream_max_recv_window_size / 2, kTargetSize);
5905 // Size of each DATA frame.
5906 const int32 kChunkSize = 4096;
5907 // Size of window updates.
5908 ASSERT_EQ(0, session_max_recv_window_size / 2 % kChunkSize);
5909 const int32 session_window_update_delta =
5910 session_max_recv_window_size / 2 + kChunkSize;
5911 ASSERT_EQ(0, stream_max_recv_window_size / 2 % kChunkSize);
5912 const int32 stream_window_update_delta =
5913 stream_max_recv_window_size / 2 + kChunkSize;
[email protected]d11b6912013-06-27 23:07:325914
bnc8f0f3b62015-04-08 04:37:235915 SettingsMap initial_settings;
5916 initial_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
5917 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
5918 initial_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
5919 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, stream_max_recv_window_size);
5920 scoped_ptr<SpdyFrame> initial_settings_frame(
5921 spdy_util_.ConstructSpdySettings(initial_settings));
5922 scoped_ptr<SpdyFrame> initial_window_update(
5923 spdy_util_.ConstructSpdyWindowUpdate(
5924 kSessionFlowControlStreamId,
5925 session_max_recv_window_size - default_initial_window_size));
[email protected]d11b6912013-06-27 23:07:325926 scoped_ptr<SpdyFrame> req(
5927 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5928 scoped_ptr<SpdyFrame> session_window_update(
bnc8f0f3b62015-04-08 04:37:235929 spdy_util_.ConstructSpdyWindowUpdate(0, session_window_update_delta));
5930 scoped_ptr<SpdyFrame> stream_window_update(
5931 spdy_util_.ConstructSpdyWindowUpdate(1, stream_window_update_delta));
[email protected]d11b6912013-06-27 23:07:325932
5933 std::vector<MockWrite> writes;
bnc8f0f3b62015-04-08 04:37:235934 if ((GetParam().protocol >= kProtoSPDY4MinimumVersion) &&
5935 (GetParam().protocol <= kProtoSPDY4MaximumVersion)) {
5936 writes.push_back(MockWrite(ASYNC, kHttp2ConnectionHeaderPrefix,
5937 kHttp2ConnectionHeaderPrefixSize, 0));
5938 }
5939 writes.push_back(CreateMockWrite(*initial_settings_frame));
5940 writes.push_back(CreateMockWrite(*initial_window_update));
[email protected]d11b6912013-06-27 23:07:325941 writes.push_back(CreateMockWrite(*req));
bnc8f0f3b62015-04-08 04:37:235942 writes.push_back(CreateMockWrite(*session_window_update));
5943 writes.push_back(CreateMockWrite(*stream_window_update));
[email protected]d11b6912013-06-27 23:07:325944
[email protected]251029e2014-03-19 06:04:405945 std::vector<MockRead> reads;
[email protected]d11b6912013-06-27 23:07:325946 scoped_ptr<SpdyFrame> resp(
5947 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]251029e2014-03-19 06:04:405948 reads.push_back(CreateMockRead(*resp));
[email protected]d11b6912013-06-27 23:07:325949
[email protected]251029e2014-03-19 06:04:405950 ScopedVector<SpdyFrame> body_frames;
bnc8f0f3b62015-04-08 04:37:235951 const std::string body_data(kChunkSize, 'x');
[email protected]251029e2014-03-19 06:04:405952 for (size_t remaining = kTargetSize; remaining != 0;) {
5953 size_t frame_size = std::min(remaining, body_data.size());
5954 body_frames.push_back(spdy_util_.ConstructSpdyBodyFrame(
5955 1, body_data.data(), frame_size, false));
5956 reads.push_back(CreateMockRead(*body_frames.back()));
5957 remaining -= frame_size;
5958 }
bnc2f54c832014-12-01 13:31:195959 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, 0)); // Yield.
[email protected]251029e2014-03-19 06:04:405960
bnc8f0f3b62015-04-08 04:37:235961 DelayedSocketData data(2, vector_as_array(&reads), reads.size(),
[email protected]d11b6912013-06-27 23:07:325962 vector_as_array(&writes), writes.size());
5963
5964 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5965 BoundNetLog(), GetParam(), NULL);
5966 helper.AddData(&data);
5967 helper.RunPreTestSetup();
[email protected]d11b6912013-06-27 23:07:325968
bnc8f0f3b62015-04-08 04:37:235969 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
5970 SpdySessionPoolPeer pool_peer(spdy_session_pool);
5971 pool_peer.SetEnableSendingInitialData(true);
5972 pool_peer.SetSessionMaxRecvWindowSize(session_max_recv_window_size);
5973 pool_peer.SetStreamInitialRecvWindowSize(stream_max_recv_window_size);
5974
5975 HttpNetworkTransaction* trans = helper.trans();
[email protected]d11b6912013-06-27 23:07:325976 TestCompletionCallback callback;
5977 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5978
5979 EXPECT_EQ(ERR_IO_PENDING, rv);
5980 rv = callback.WaitForResult();
5981 EXPECT_EQ(OK, rv);
5982
5983 SpdyHttpStream* stream =
5984 static_cast<SpdyHttpStream*>(trans->stream_.get());
5985 ASSERT_TRUE(stream != NULL);
5986 ASSERT_TRUE(stream->stream() != NULL);
5987
[email protected]251029e2014-03-19 06:04:405988 // All data has been read, but not consumed. The window reflects this.
bnc8f0f3b62015-04-08 04:37:235989 EXPECT_EQ(static_cast<int>(stream_max_recv_window_size - kTargetSize),
[email protected]251029e2014-03-19 06:04:405990 stream->stream()->recv_window_size());
[email protected]d11b6912013-06-27 23:07:325991
5992 const HttpResponseInfo* response = trans->GetResponseInfo();
5993 ASSERT_TRUE(response != NULL);
5994 ASSERT_TRUE(response->headers.get() != NULL);
5995 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5996 EXPECT_TRUE(response->was_fetched_via_spdy);
5997
5998 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
5999 // size increased to default.
bnc301745a2015-03-10 03:22:166000 scoped_refptr<IOBuffer> buf(new IOBuffer(kTargetSize));
[email protected]251029e2014-03-19 06:04:406001 EXPECT_EQ(static_cast<int>(kTargetSize),
6002 trans->Read(buf.get(), kTargetSize, CompletionCallback()));
bnc8f0f3b62015-04-08 04:37:236003 EXPECT_EQ(static_cast<int>(stream_max_recv_window_size),
[email protected]251029e2014-03-19 06:04:406004 stream->stream()->recv_window_size());
6005 EXPECT_THAT(base::StringPiece(buf->data(), kTargetSize), Each(Eq('x')));
[email protected]d11b6912013-06-27 23:07:326006
[email protected]251029e2014-03-19 06:04:406007 // Allow scheduled WINDOW_UPDATE frames to write.
[email protected]fc9d88472013-08-14 02:31:176008 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:326009 helper.VerifyDataConsumed();
6010}
6011
6012// Test that WINDOW_UPDATE frame causing overflow is handled correctly.
6013TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
[email protected]d11b6912013-06-27 23:07:326014 // Number of full frames we hope to write (but will not, used to
6015 // set content-length header correctly)
6016 static int kFrameCount = 3;
6017
6018 scoped_ptr<std::string> content(
6019 new std::string(kMaxSpdyFrameChunkSize, 'a'));
6020 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
rchebf12982015-04-10 01:15:006021 GetDefaultUrl(), 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL,
6022 0));
[email protected]d11b6912013-06-27 23:07:326023 scoped_ptr<SpdyFrame> body(
6024 spdy_util_.ConstructSpdyBodyFrame(
6025 1, content->c_str(), content->size(), false));
6026 scoped_ptr<SpdyFrame> rst(
6027 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
6028
6029 // We're not going to write a data frame with FIN, we'll receive a bad
6030 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
6031 MockWrite writes[] = {
6032 CreateMockWrite(*req, 0),
6033 CreateMockWrite(*body, 2),
6034 CreateMockWrite(*rst, 3),
6035 };
6036
6037 static const int32 kDeltaWindowSize = 0x7fffffff; // cause an overflow
6038 scoped_ptr<SpdyFrame> window_update(
6039 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
6040 MockRead reads[] = {
6041 CreateMockRead(*window_update, 1),
6042 MockRead(ASYNC, 0, 4) // EOF
6043 };
6044
6045 DeterministicSocketData data(reads, arraysize(reads),
6046 writes, arraysize(writes));
6047
6048 ScopedVector<UploadElementReader> element_readers;
6049 for (int i = 0; i < kFrameCount; ++i) {
6050 element_readers.push_back(
6051 new UploadBytesElementReader(content->c_str(), content->size()));
6052 }
mmenkecbc2b712014-10-09 20:29:076053 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]d11b6912013-06-27 23:07:326054
6055 // Setup the request
6056 HttpRequestInfo request;
6057 request.method = "POST";
rchebf12982015-04-10 01:15:006058 request.url = GURL(GetDefaultUrl());
[email protected]d11b6912013-06-27 23:07:326059 request.upload_data_stream = &upload_data_stream;
6060
6061 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6062 BoundNetLog(), GetParam(), NULL);
6063 helper.SetDeterministic();
6064 helper.RunPreTestSetup();
6065 helper.AddDeterministicData(&data);
6066 HttpNetworkTransaction* trans = helper.trans();
6067
6068 TestCompletionCallback callback;
6069 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6070 ASSERT_EQ(ERR_IO_PENDING, rv);
6071
6072 data.RunFor(5);
6073 ASSERT_TRUE(callback.have_result());
6074 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, callback.WaitForResult());
6075 helper.VerifyDataConsumed();
6076}
6077
6078// Test that after hitting a send window size of 0, the write process
6079// stalls and upon receiving WINDOW_UPDATE frame write resumes.
6080
6081// This test constructs a POST request followed by enough data frames
6082// containing 'a' that would make the window size 0, followed by another
6083// data frame containing default content (which is "hello!") and this frame
6084// also contains a FIN flag. DelayedSocketData is used to enforce all
6085// writes go through before a read could happen. However, the last frame
6086// ("hello!") is not supposed to go through since by the time its turn
6087// arrives, window size is 0. At this point MessageLoop::Run() called via
6088// callback would block. Therefore we call MessageLoop::RunUntilIdle()
6089// which returns after performing all possible writes. We use DCHECKS to
6090// ensure that last data frame is still there and stream has stalled.
6091// After that, next read is artifically enforced, which causes a
6092// WINDOW_UPDATE to be read and I/O process resumes.
6093TEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) {
bnc2f54c832014-12-01 13:31:196094 const int32 initial_window_size =
bnc638c4702015-04-09 18:01:186095 SpdySession::GetDefaultInitialWindowSize(GetParam().protocol);
[email protected]d11b6912013-06-27 23:07:326096 // Number of frames we need to send to zero out the window size: data
6097 // frames plus SYN_STREAM plus the last data frame; also we need another
6098 // data frame that we will send once the WINDOW_UPDATE is received,
6099 // therefore +3.
bnc2f54c832014-12-01 13:31:196100 size_t num_writes = initial_window_size / kMaxSpdyFrameChunkSize + 3;
[email protected]d11b6912013-06-27 23:07:326101
6102 // Calculate last frame's size; 0 size data frame is legal.
bnc2f54c832014-12-01 13:31:196103 size_t last_frame_size = initial_window_size % kMaxSpdyFrameChunkSize;
[email protected]d11b6912013-06-27 23:07:326104
6105 // Construct content for a data frame of maximum size.
6106 std::string content(kMaxSpdyFrameChunkSize, 'a');
6107
6108 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
rchebf12982015-04-10 01:15:006109 GetDefaultUrl(), 1, initial_window_size + kUploadDataSize, LOWEST, NULL,
6110 0));
[email protected]d11b6912013-06-27 23:07:326111
6112 // Full frames.
6113 scoped_ptr<SpdyFrame> body1(
6114 spdy_util_.ConstructSpdyBodyFrame(
6115 1, content.c_str(), content.size(), false));
6116
6117 // Last frame to zero out the window size.
6118 scoped_ptr<SpdyFrame> body2(
6119 spdy_util_.ConstructSpdyBodyFrame(
6120 1, content.c_str(), last_frame_size, false));
6121
6122 // Data frame to be sent once WINDOW_UPDATE frame is received.
6123 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6124
6125 // Fill in mock writes.
6126 scoped_ptr<MockWrite[]> writes(new MockWrite[num_writes]);
6127 size_t i = 0;
6128 writes[i] = CreateMockWrite(*req);
6129 for (i = 1; i < num_writes - 2; i++)
6130 writes[i] = CreateMockWrite(*body1);
6131 writes[i++] = CreateMockWrite(*body2);
6132 writes[i] = CreateMockWrite(*body3);
6133
6134 // Construct read frame, give enough space to upload the rest of the
6135 // data.
6136 scoped_ptr<SpdyFrame> session_window_update(
6137 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6138 scoped_ptr<SpdyFrame> window_update(
6139 spdy_util_.ConstructSpdyWindowUpdate(1, kUploadDataSize));
6140 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6141 MockRead reads[] = {
6142 CreateMockRead(*session_window_update),
6143 CreateMockRead(*session_window_update),
6144 CreateMockRead(*window_update),
6145 CreateMockRead(*window_update),
6146 CreateMockRead(*reply),
6147 CreateMockRead(*body2),
6148 CreateMockRead(*body3),
6149 MockRead(ASYNC, 0, 0) // EOF
6150 };
6151
6152 // Skip the session window updates unless we're using SPDY/3.1 and
6153 // above.
6154 size_t read_offset = (GetParam().protocol >= kProtoSPDY31) ? 0 : 2;
6155 size_t num_reads = arraysize(reads) - read_offset;
6156
6157 // Force all writes to happen before any read, last write will not
6158 // actually queue a frame, due to window size being 0.
6159 DelayedSocketData data(num_writes, reads + read_offset, num_reads,
6160 writes.get(), num_writes);
6161
6162 ScopedVector<UploadElementReader> element_readers;
bnc2f54c832014-12-01 13:31:196163 std::string upload_data_string(initial_window_size, 'a');
[email protected]d11b6912013-06-27 23:07:326164 upload_data_string.append(kUploadData, kUploadDataSize);
6165 element_readers.push_back(new UploadBytesElementReader(
6166 upload_data_string.c_str(), upload_data_string.size()));
mmenkecbc2b712014-10-09 20:29:076167 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]d11b6912013-06-27 23:07:326168
6169 HttpRequestInfo request;
6170 request.method = "POST";
rchebf12982015-04-10 01:15:006171 request.url = GURL(GetDefaultUrl());
[email protected]d11b6912013-06-27 23:07:326172 request.upload_data_stream = &upload_data_stream;
6173 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6174 BoundNetLog(), GetParam(), NULL);
6175 helper.AddData(&data);
6176 helper.RunPreTestSetup();
6177
6178 HttpNetworkTransaction* trans = helper.trans();
6179
6180 TestCompletionCallback callback;
6181 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6182 EXPECT_EQ(ERR_IO_PENDING, rv);
6183
[email protected]fc9d88472013-08-14 02:31:176184 base::RunLoop().RunUntilIdle(); // Write as much as we can.
[email protected]d11b6912013-06-27 23:07:326185
6186 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6187 ASSERT_TRUE(stream != NULL);
6188 ASSERT_TRUE(stream->stream() != NULL);
6189 EXPECT_EQ(0, stream->stream()->send_window_size());
6190 // All the body data should have been read.
6191 // TODO(satorux): This is because of the weirdness in reading the request
6192 // body in OnSendBodyComplete(). See crbug.com/113107.
6193 EXPECT_TRUE(upload_data_stream.IsEOF());
6194 // But the body is not yet fully sent (kUploadData is not yet sent)
6195 // since we're send-stalled.
6196 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6197
6198 data.ForceNextRead(); // Read in WINDOW_UPDATE frame.
6199 rv = callback.WaitForResult();
6200 helper.VerifyDataConsumed();
6201}
6202
6203// Test we correctly handle the case where the SETTINGS frame results in
6204// unstalling the send window.
6205TEST_P(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
bnc2f54c832014-12-01 13:31:196206 const int32 initial_window_size =
bnc638c4702015-04-09 18:01:186207 SpdySession::GetDefaultInitialWindowSize(GetParam().protocol);
bnc2f54c832014-12-01 13:31:196208
[email protected]d11b6912013-06-27 23:07:326209 // Number of frames we need to send to zero out the window size: data
6210 // frames plus SYN_STREAM plus the last data frame; also we need another
6211 // data frame that we will send once the SETTING is received, therefore +3.
bnc2f54c832014-12-01 13:31:196212 size_t num_writes = initial_window_size / kMaxSpdyFrameChunkSize + 3;
[email protected]d11b6912013-06-27 23:07:326213
6214 // Calculate last frame's size; 0 size data frame is legal.
bnc2f54c832014-12-01 13:31:196215 size_t last_frame_size = initial_window_size % kMaxSpdyFrameChunkSize;
[email protected]d11b6912013-06-27 23:07:326216
6217 // Construct content for a data frame of maximum size.
6218 std::string content(kMaxSpdyFrameChunkSize, 'a');
6219
6220 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
rchebf12982015-04-10 01:15:006221 GetDefaultUrl(), 1, initial_window_size + kUploadDataSize, LOWEST, NULL,
6222 0));
[email protected]d11b6912013-06-27 23:07:326223
6224 // Full frames.
6225 scoped_ptr<SpdyFrame> body1(
6226 spdy_util_.ConstructSpdyBodyFrame(
6227 1, content.c_str(), content.size(), false));
6228
6229 // Last frame to zero out the window size.
6230 scoped_ptr<SpdyFrame> body2(
6231 spdy_util_.ConstructSpdyBodyFrame(
6232 1, content.c_str(), last_frame_size, false));
6233
6234 // Data frame to be sent once SETTINGS frame is received.
6235 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6236
6237 // Fill in mock reads/writes.
6238 std::vector<MockRead> reads;
6239 std::vector<MockWrite> writes;
6240 size_t i = 0;
6241 writes.push_back(CreateMockWrite(*req, i++));
6242 while (i < num_writes - 2)
6243 writes.push_back(CreateMockWrite(*body1, i++));
6244 writes.push_back(CreateMockWrite(*body2, i++));
6245
6246 // Construct read frame for SETTINGS that gives enough space to upload the
6247 // rest of the data.
6248 SettingsMap settings;
6249 settings[SETTINGS_INITIAL_WINDOW_SIZE] =
bnc2f54c832014-12-01 13:31:196250 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_window_size * 2);
[email protected]d11b6912013-06-27 23:07:326251 scoped_ptr<SpdyFrame> settings_frame_large(
6252 spdy_util_.ConstructSpdySettings(settings));
6253
6254 reads.push_back(CreateMockRead(*settings_frame_large, i++));
6255
6256 scoped_ptr<SpdyFrame> session_window_update(
6257 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6258 if (GetParam().protocol >= kProtoSPDY31)
6259 reads.push_back(CreateMockRead(*session_window_update, i++));
6260
[email protected]d4a77c12014-05-15 20:45:216261 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
6262 writes.push_back(CreateMockWrite(*settings_ack, i++));
6263
[email protected]d11b6912013-06-27 23:07:326264 writes.push_back(CreateMockWrite(*body3, i++));
6265
6266 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6267 reads.push_back(CreateMockRead(*reply, i++));
6268 reads.push_back(CreateMockRead(*body2, i++));
6269 reads.push_back(CreateMockRead(*body3, i++));
6270 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6271
6272 // Force all writes to happen before any read, last write will not
6273 // actually queue a frame, due to window size being 0.
6274 DeterministicSocketData data(vector_as_array(&reads), reads.size(),
6275 vector_as_array(&writes), writes.size());
6276
6277 ScopedVector<UploadElementReader> element_readers;
bnc2f54c832014-12-01 13:31:196278 std::string upload_data_string(initial_window_size, 'a');
[email protected]d11b6912013-06-27 23:07:326279 upload_data_string.append(kUploadData, kUploadDataSize);
6280 element_readers.push_back(new UploadBytesElementReader(
6281 upload_data_string.c_str(), upload_data_string.size()));
mmenkecbc2b712014-10-09 20:29:076282 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]d11b6912013-06-27 23:07:326283
6284 HttpRequestInfo request;
6285 request.method = "POST";
rchebf12982015-04-10 01:15:006286 request.url = GURL(GetDefaultUrl());
[email protected]d11b6912013-06-27 23:07:326287 request.upload_data_stream = &upload_data_stream;
6288 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6289 BoundNetLog(), GetParam(), NULL);
6290 helper.SetDeterministic();
6291 helper.RunPreTestSetup();
6292 helper.AddDeterministicData(&data);
6293
6294 HttpNetworkTransaction* trans = helper.trans();
6295
6296 TestCompletionCallback callback;
6297 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6298 EXPECT_EQ(ERR_IO_PENDING, rv);
6299
6300 data.RunFor(num_writes - 1); // Write as much as we can.
6301
6302 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6303 ASSERT_TRUE(stream != NULL);
6304 ASSERT_TRUE(stream->stream() != NULL);
6305 EXPECT_EQ(0, stream->stream()->send_window_size());
6306
6307 // All the body data should have been read.
6308 // TODO(satorux): This is because of the weirdness in reading the request
6309 // body in OnSendBodyComplete(). See crbug.com/113107.
6310 EXPECT_TRUE(upload_data_stream.IsEOF());
6311 // But the body is not yet fully sent (kUploadData is not yet sent)
6312 // since we're send-stalled.
6313 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6314
[email protected]d4a77c12014-05-15 20:45:216315 data.RunFor(7); // Read in SETTINGS frame to unstall.
[email protected]d11b6912013-06-27 23:07:326316 rv = callback.WaitForResult();
6317 helper.VerifyDataConsumed();
6318 // If stream is NULL, that means it was unstalled and closed.
6319 EXPECT_TRUE(stream->stream() == NULL);
6320}
6321
6322// Test we correctly handle the case where the SETTINGS frame results in a
6323// negative send window size.
6324TEST_P(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
bnc2f54c832014-12-01 13:31:196325 const int32 initial_window_size =
bnc638c4702015-04-09 18:01:186326 SpdySession::GetDefaultInitialWindowSize(GetParam().protocol);
[email protected]d11b6912013-06-27 23:07:326327 // Number of frames we need to send to zero out the window size: data
6328 // frames plus SYN_STREAM plus the last data frame; also we need another
6329 // data frame that we will send once the SETTING is received, therefore +3.
bnc2f54c832014-12-01 13:31:196330 size_t num_writes = initial_window_size / kMaxSpdyFrameChunkSize + 3;
[email protected]d11b6912013-06-27 23:07:326331
6332 // Calculate last frame's size; 0 size data frame is legal.
bnc2f54c832014-12-01 13:31:196333 size_t last_frame_size = initial_window_size % kMaxSpdyFrameChunkSize;
[email protected]d11b6912013-06-27 23:07:326334
6335 // Construct content for a data frame of maximum size.
6336 std::string content(kMaxSpdyFrameChunkSize, 'a');
6337
6338 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
rchebf12982015-04-10 01:15:006339 GetDefaultUrl(), 1, initial_window_size + kUploadDataSize, LOWEST, NULL,
6340 0));
[email protected]d11b6912013-06-27 23:07:326341
6342 // Full frames.
6343 scoped_ptr<SpdyFrame> body1(
6344 spdy_util_.ConstructSpdyBodyFrame(
6345 1, content.c_str(), content.size(), false));
6346
6347 // Last frame to zero out the window size.
6348 scoped_ptr<SpdyFrame> body2(
6349 spdy_util_.ConstructSpdyBodyFrame(
6350 1, content.c_str(), last_frame_size, false));
6351
6352 // Data frame to be sent once SETTINGS frame is received.
6353 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6354
6355 // Fill in mock reads/writes.
6356 std::vector<MockRead> reads;
6357 std::vector<MockWrite> writes;
6358 size_t i = 0;
6359 writes.push_back(CreateMockWrite(*req, i++));
6360 while (i < num_writes - 2)
6361 writes.push_back(CreateMockWrite(*body1, i++));
6362 writes.push_back(CreateMockWrite(*body2, i++));
6363
6364 // Construct read frame for SETTINGS that makes the send_window_size
6365 // negative.
6366 SettingsMap new_settings;
6367 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
bnc2f54c832014-12-01 13:31:196368 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_window_size / 2);
[email protected]d11b6912013-06-27 23:07:326369 scoped_ptr<SpdyFrame> settings_frame_small(
6370 spdy_util_.ConstructSpdySettings(new_settings));
6371 // Construct read frames for WINDOW_UPDATE that makes the send_window_size
6372 // positive.
6373 scoped_ptr<SpdyFrame> session_window_update_init_size(
bnc2f54c832014-12-01 13:31:196374 spdy_util_.ConstructSpdyWindowUpdate(0, initial_window_size));
[email protected]d11b6912013-06-27 23:07:326375 scoped_ptr<SpdyFrame> window_update_init_size(
bnc2f54c832014-12-01 13:31:196376 spdy_util_.ConstructSpdyWindowUpdate(1, initial_window_size));
[email protected]d11b6912013-06-27 23:07:326377
6378 reads.push_back(CreateMockRead(*settings_frame_small, i++));
bnc33b8cef42014-11-19 17:30:386379 reads.push_back(CreateMockRead(*session_window_update_init_size, i++));
[email protected]d11b6912013-06-27 23:07:326380 reads.push_back(CreateMockRead(*window_update_init_size, i++));
6381
[email protected]d4a77c12014-05-15 20:45:216382 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
6383 writes.push_back(CreateMockWrite(*settings_ack, i++));
6384
[email protected]d11b6912013-06-27 23:07:326385 writes.push_back(CreateMockWrite(*body3, i++));
6386
6387 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6388 reads.push_back(CreateMockRead(*reply, i++));
6389 reads.push_back(CreateMockRead(*body2, i++));
6390 reads.push_back(CreateMockRead(*body3, i++));
6391 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6392
6393 // Force all writes to happen before any read, last write will not
6394 // actually queue a frame, due to window size being 0.
6395 DeterministicSocketData data(vector_as_array(&reads), reads.size(),
6396 vector_as_array(&writes), writes.size());
6397
6398 ScopedVector<UploadElementReader> element_readers;
bnc2f54c832014-12-01 13:31:196399 std::string upload_data_string(initial_window_size, 'a');
[email protected]d11b6912013-06-27 23:07:326400 upload_data_string.append(kUploadData, kUploadDataSize);
6401 element_readers.push_back(new UploadBytesElementReader(
6402 upload_data_string.c_str(), upload_data_string.size()));
mmenkecbc2b712014-10-09 20:29:076403 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]d11b6912013-06-27 23:07:326404
6405 HttpRequestInfo request;
6406 request.method = "POST";
rchebf12982015-04-10 01:15:006407 request.url = GURL(GetDefaultUrl());
[email protected]d11b6912013-06-27 23:07:326408 request.upload_data_stream = &upload_data_stream;
6409 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6410 BoundNetLog(), GetParam(), NULL);
6411 helper.SetDeterministic();
6412 helper.RunPreTestSetup();
6413 helper.AddDeterministicData(&data);
6414
6415 HttpNetworkTransaction* trans = helper.trans();
6416
6417 TestCompletionCallback callback;
6418 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6419 EXPECT_EQ(ERR_IO_PENDING, rv);
6420
6421 data.RunFor(num_writes - 1); // Write as much as we can.
6422
6423 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6424 ASSERT_TRUE(stream != NULL);
6425 ASSERT_TRUE(stream->stream() != NULL);
6426 EXPECT_EQ(0, stream->stream()->send_window_size());
6427
6428 // All the body data should have been read.
6429 // TODO(satorux): This is because of the weirdness in reading the request
6430 // body in OnSendBodyComplete(). See crbug.com/113107.
6431 EXPECT_TRUE(upload_data_stream.IsEOF());
6432 // But the body is not yet fully sent (kUploadData is not yet sent)
6433 // since we're send-stalled.
6434 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6435
6436 // Read in WINDOW_UPDATE or SETTINGS frame.
[email protected]d4a77c12014-05-15 20:45:216437 data.RunFor((GetParam().protocol >= kProtoSPDY31) ? 9 : 8);
[email protected]d11b6912013-06-27 23:07:326438 rv = callback.WaitForResult();
6439 helper.VerifyDataConsumed();
6440}
6441
baranovich212a1292014-09-02 21:45:316442TEST_P(SpdyNetworkTransactionTest, GoAwayOnOddPushStreamId) {
6443 if (spdy_util_.spdy_version() < SPDY3)
6444 return;
6445
6446 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
bncce36dca22015-04-21 22:11:236447 spdy_util_.AddUrlToHeaderBlock("http://www.example.org/a.dat",
baranovich212a1292014-09-02 21:45:316448 push_headers.get());
6449 scoped_ptr<SpdyFrame> push(
6450 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 3, 1));
6451 MockRead reads[] = {CreateMockRead(*push, 1)};
6452
6453 scoped_ptr<SpdyFrame> req(
6454 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
6455 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
6456 0, GOAWAY_PROTOCOL_ERROR, "Odd push stream id."));
6457 MockWrite writes[] = {
6458 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2),
6459 };
6460
rch73e17422015-05-04 19:52:066461 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
baranovich212a1292014-09-02 21:45:316462 NormalSpdyTransactionHelper helper(
6463 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6464 helper.RunToCompletion(&data);
6465 TransactionHelperResult out = helper.output();
6466 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
6467}
6468
6469TEST_P(SpdyNetworkTransactionTest,
6470 GoAwayOnPushStreamIdLesserOrEqualThanLastAccepted) {
6471 if (spdy_util_.spdy_version() < SPDY3)
6472 return;
6473
6474 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
rchebf12982015-04-10 01:15:006475 NULL, 0, 4, 1, GetDefaultUrlWithPath("/a.dat").c_str()));
baranovich212a1292014-09-02 21:45:316476 scoped_ptr<SpdyHeaderBlock> push_b_headers(new SpdyHeaderBlock);
rchebf12982015-04-10 01:15:006477 spdy_util_.AddUrlToHeaderBlock(GetDefaultUrlWithPath("/b.dat"),
baranovich212a1292014-09-02 21:45:316478 push_b_headers.get());
6479 scoped_ptr<SpdyFrame> push_b(
6480 spdy_util_.ConstructInitialSpdyPushFrame(push_b_headers.Pass(), 2, 1));
6481 MockRead reads[] = {
6482 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
6483 };
6484
6485 scoped_ptr<SpdyFrame> req(
6486 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
6487 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
6488 4,
6489 GOAWAY_PROTOCOL_ERROR,
6490 "New push stream id must be greater than the last accepted."));
6491 MockWrite writes[] = {
6492 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 3),
6493 };
6494
rch73e17422015-05-04 19:52:066495 SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes));
baranovich212a1292014-09-02 21:45:316496 NormalSpdyTransactionHelper helper(
6497 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6498 helper.RunToCompletion(&data);
6499 TransactionHelperResult out = helper.output();
6500 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
6501}
6502
[email protected]514aeaf2014-05-23 10:31:516503class SpdyNetworkTransactionNoTLSUsageCheckTest
6504 : public SpdyNetworkTransactionTest {
6505 protected:
6506 void RunNoTLSUsageCheckTest(scoped_ptr<SSLSocketDataProvider> ssl_provider) {
6507 // Construct the request.
rchebf12982015-04-10 01:15:006508 scoped_ptr<SpdyFrame> req(
6509 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
rch73e17422015-05-04 19:52:066510 MockWrite writes[] = {CreateMockWrite(*req, 0)};
[email protected]514aeaf2014-05-23 10:31:516511
6512 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6513 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6514 MockRead reads[] = {
rch73e17422015-05-04 19:52:066515 CreateMockRead(*resp, 1),
6516 CreateMockRead(*body, 2),
6517 MockRead(ASYNC, 0, 3) // EOF
[email protected]514aeaf2014-05-23 10:31:516518 };
6519
rch73e17422015-05-04 19:52:066520 SequencedSocketData data(reads, arraysize(reads), writes,
6521 arraysize(writes));
[email protected]514aeaf2014-05-23 10:31:516522 HttpRequestInfo request;
6523 request.method = "GET";
bncce36dca22015-04-21 22:11:236524 request.url = GURL("https://www.example.org/");
[email protected]514aeaf2014-05-23 10:31:516525 NormalSpdyTransactionHelper helper(
6526 request, DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6527 helper.RunToCompletionWithSSLData(&data, ssl_provider.Pass());
6528 TransactionHelperResult out = helper.output();
6529 EXPECT_EQ(OK, out.rv);
6530 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
6531 EXPECT_EQ("hello!", out.response_data);
6532 }
6533};
6534
6535//-----------------------------------------------------------------------------
6536// All tests are run with three different connection types: SPDY after NPN
6537// negotiation, SPDY without SSL, and SPDY with SSL.
6538//
6539// TODO(akalin): Use ::testing::Combine() when we are able to use
6540// <tr1/tuple>.
6541INSTANTIATE_TEST_CASE_P(
6542 Spdy,
6543 SpdyNetworkTransactionNoTLSUsageCheckTest,
rchebf12982015-04-10 01:15:006544 ::testing::Values(SpdyNetworkTransactionTestParams(kProtoSPDY31,
6545 HTTPS_SPDY_VIA_NPN)));
[email protected]514aeaf2014-05-23 10:31:516546
6547TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest, TLSVersionTooOld) {
6548 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6549 new SSLSocketDataProvider(ASYNC, OK));
6550 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6551 &ssl_provider->connection_status);
6552
6553 RunNoTLSUsageCheckTest(ssl_provider.Pass());
6554}
6555
6556TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest, TLSCipherSuiteSucky) {
6557 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6558 new SSLSocketDataProvider(ASYNC, OK));
6559 // Set to TLS_RSA_WITH_NULL_MD5
6560 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider->connection_status);
6561
6562 RunNoTLSUsageCheckTest(ssl_provider.Pass());
6563}
6564
6565class SpdyNetworkTransactionTLSUsageCheckTest
6566 : public SpdyNetworkTransactionTest {
6567 protected:
6568 void RunTLSUsageCheckTest(scoped_ptr<SSLSocketDataProvider> ssl_provider) {
[email protected]bdd1b222014-06-10 11:08:396569 scoped_ptr<SpdyFrame> goaway(
6570 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_INADEQUATE_SECURITY, ""));
6571 MockWrite writes[] = {CreateMockWrite(*goaway)};
[email protected]514aeaf2014-05-23 10:31:516572
rch73e17422015-05-04 19:52:066573 StaticSocketDataProvider data(NULL, 0, writes, arraysize(writes));
[email protected]514aeaf2014-05-23 10:31:516574 HttpRequestInfo request;
6575 request.method = "GET";
bncce36dca22015-04-21 22:11:236576 request.url = GURL("https://www.example.org/");
[email protected]514aeaf2014-05-23 10:31:516577 NormalSpdyTransactionHelper helper(
6578 request, DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6579 helper.RunToCompletionWithSSLData(&data, ssl_provider.Pass());
6580 TransactionHelperResult out = helper.output();
6581 EXPECT_EQ(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY, out.rv);
6582 }
6583};
6584
6585INSTANTIATE_TEST_CASE_P(
6586 Spdy,
6587 SpdyNetworkTransactionTLSUsageCheckTest,
rchebf12982015-04-10 01:15:006588 ::testing::Values(
6589 SpdyNetworkTransactionTestParams(kProtoSPDY4_14, HTTPS_SPDY_VIA_NPN),
6590 SpdyNetworkTransactionTestParams(kProtoSPDY4, HTTPS_SPDY_VIA_NPN)));
[email protected]514aeaf2014-05-23 10:31:516591
6592TEST_P(SpdyNetworkTransactionTLSUsageCheckTest, TLSVersionTooOld) {
6593 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6594 new SSLSocketDataProvider(ASYNC, OK));
6595 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6596 &ssl_provider->connection_status);
6597
6598 RunTLSUsageCheckTest(ssl_provider.Pass());
6599}
6600
6601TEST_P(SpdyNetworkTransactionTLSUsageCheckTest, TLSCipherSuiteSucky) {
6602 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6603 new SSLSocketDataProvider(ASYNC, OK));
6604 // Set to TLS_RSA_WITH_NULL_MD5
6605 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider->connection_status);
6606
6607 RunTLSUsageCheckTest(ssl_provider.Pass());
6608}
6609
[email protected]aea80602009-09-18 00:55:086610} // namespace net