blob: a68615f8acd4e0c4cf8a2b3f50f0f87bab6ae83f [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]9e743cd2010-03-16 07:03:5320#include "net/base/net_log_unittest.h"
[email protected]262eec82013-03-19 21:01:3621#include "net/base/request_priority.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"
[email protected]2d6728692011-03-12 01:39:5528#include "net/socket/client_socket_pool_base.h"
[email protected]bb88e1d32013-05-03 23:11:0729#include "net/socket/next_proto.h"
[email protected]f54c85792012-03-08 19:06:4130#include "net/spdy/buffered_spdy_framer.h"
[email protected]9be804c82010-06-24 17:59:4631#include "net/spdy/spdy_http_stream.h"
[email protected]9e1bdd32011-02-03 21:48:3432#include "net/spdy/spdy_http_utils.h"
[email protected]bdebd1b2010-08-09 20:18:0833#include "net/spdy/spdy_session.h"
[email protected]19ec8a72010-08-23 03:38:2334#include "net/spdy/spdy_session_pool.h"
[email protected]86aa87b2013-02-15 01:10:0335#include "net/spdy/spdy_test_util_common.h"
[email protected]a4bfdf72013-02-22 04:06:1636#include "net/spdy/spdy_test_utils.h"
[email protected]514aeaf2014-05-23 10:31:5137#include "net/ssl/ssl_connection_status_flags.h"
[email protected]d2db0292011-01-26 20:23:4438#include "net/url_request/url_request_test_util.h"
[email protected]251029e2014-03-19 06:04:4039#include "testing/gmock/include/gmock/gmock.h"
[email protected]aea80602009-09-18 00:55:0840#include "testing/platform_test.h"
41
42//-----------------------------------------------------------------------------
43
[email protected]d1eda932009-11-04 01:03:1044namespace net {
[email protected]dae22c52010-07-30 02:16:3545
[email protected]cbdd73162013-03-18 23:27:3346namespace {
[email protected]251029e2014-03-19 06:04:4047
48using testing::Each;
49using testing::Eq;
50
[email protected]cbdd73162013-03-18 23:27:3351const char kRequestUrl[] = "http://www.google.com/";
[email protected]cbdd73162013-03-18 23:27:3352
[email protected]513963e2013-06-15 01:53:0453enum SpdyNetworkTransactionTestSSLType {
[email protected]9e9e842e2010-07-23 23:09:1554 SPDYNPN,
55 SPDYNOSSL,
[email protected]1f418ee2010-10-16 19:46:5656 SPDYSSL,
[email protected]9e9e842e2010-07-23 23:09:1557};
[email protected]ca6459f862012-04-11 19:43:2058
[email protected]513963e2013-06-15 01:53:0459struct SpdyNetworkTransactionTestParams {
60 SpdyNetworkTransactionTestParams()
[email protected]b05bcaa32013-10-06 05:26:0261 : protocol(kProtoSPDY3),
[email protected]513963e2013-06-15 01:53:0462 ssl_type(SPDYNPN) {}
63
64 SpdyNetworkTransactionTestParams(
65 NextProto protocol,
66 SpdyNetworkTransactionTestSSLType ssl_type)
67 : protocol(protocol),
68 ssl_type(ssl_type) {}
69
70 NextProto protocol;
71 SpdyNetworkTransactionTestSSLType ssl_type;
72};
73
[email protected]d7599122014-05-24 03:37:2374void UpdateSpdySessionDependencies(
75 SpdyNetworkTransactionTestParams test_params,
76 SpdySessionDependencies* session_deps) {
77 switch (test_params.ssl_type) {
78 case SPDYNPN:
79 session_deps->http_server_properties.SetAlternateProtocol(
80 HostPortPair("www.google.com", 80), 443,
[email protected]287d9412014-07-08 23:01:0081 AlternateProtocolFromNextProto(test_params.protocol), 1);
[email protected]d7599122014-05-24 03:37:2382 session_deps->use_alternate_protocols = true;
83 session_deps->next_protos = SpdyNextProtos();
84 break;
85 case SPDYNOSSL:
86 session_deps->force_spdy_over_ssl = false;
87 session_deps->force_spdy_always = true;
88 break;
89 case SPDYSSL:
90 session_deps->force_spdy_over_ssl = true;
91 session_deps->force_spdy_always = true;
92 break;
93 default:
94 NOTREACHED();
95 }
96}
97
[email protected]513963e2013-06-15 01:53:0498SpdySessionDependencies* CreateSpdySessionDependencies(
99 SpdyNetworkTransactionTestParams test_params) {
[email protected]d7599122014-05-24 03:37:23100 SpdySessionDependencies* session_deps =
101 new SpdySessionDependencies(test_params.protocol);
102 UpdateSpdySessionDependencies(test_params, session_deps);
103 return session_deps;
[email protected]513963e2013-06-15 01:53:04104}
105
106SpdySessionDependencies* CreateSpdySessionDependencies(
107 SpdyNetworkTransactionTestParams test_params,
[email protected]bb88e1d32013-05-03 23:11:07108 ProxyService* proxy_service) {
[email protected]d7599122014-05-24 03:37:23109 SpdySessionDependencies* session_deps =
110 new SpdySessionDependencies(test_params.protocol, proxy_service);
111 UpdateSpdySessionDependencies(test_params, session_deps);
112 return session_deps;
[email protected]bb88e1d32013-05-03 23:11:07113}
114
[email protected]513963e2013-06-15 01:53:04115} // namespace
116
117class SpdyNetworkTransactionTest
118 : public ::testing::TestWithParam<SpdyNetworkTransactionTestParams> {
[email protected]34437af82009-11-06 02:28:49119 protected:
[email protected]513963e2013-06-15 01:53:04120 SpdyNetworkTransactionTest() : spdy_util_(GetParam().protocol) {
[email protected]9ec54f82013-05-10 02:53:05121 }
[email protected]2d6728692011-03-12 01:39:55122
[email protected]fc9d88472013-08-14 02:31:17123 virtual ~SpdyNetworkTransactionTest() {
mmenkecbc2b712014-10-09 20:29:07124 // UploadDataStream may post a deletion tasks back to the message loop on
[email protected]fc9d88472013-08-14 02:31:17125 // destruction.
126 upload_data_stream_.reset();
127 base::RunLoop().RunUntilIdle();
[email protected]fc9d88472013-08-14 02:31:17128 }
129
dcheng67be2b1f2014-10-27 21:47:29130 void SetUp() override {
[email protected]d3cee19d2010-06-22 18:42:18131 google_get_request_initialized_ = false;
[email protected]310240592010-08-05 21:04:19132 google_post_request_initialized_ = false;
[email protected]0c9bf872011-03-04 17:53:22133 google_chunked_post_request_initialized_ = false;
[email protected]69e6b4a2012-10-18 08:03:01134 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
[email protected]aea80602009-09-18 00:55:08135 }
136
[email protected]72552f02009-10-28 15:25:01137 struct TransactionHelperResult {
[email protected]aea80602009-09-18 00:55:08138 int rv;
139 std::string status_line;
140 std::string response_data;
[email protected]8b070372009-11-16 22:01:25141 HttpResponseInfo response_info;
[email protected]aea80602009-09-18 00:55:08142 };
143
[email protected]3caf5542010-07-16 15:19:47144 // A helper class that handles all the initial npn/ssl setup.
145 class NormalSpdyTransactionHelper {
146 public:
147 NormalSpdyTransactionHelper(const HttpRequestInfo& request,
[email protected]262eec82013-03-19 21:01:36148 RequestPriority priority,
[email protected]9e9e842e2010-07-23 23:09:15149 const BoundNetLog& log,
[email protected]513963e2013-06-15 01:53:04150 SpdyNetworkTransactionTestParams test_params,
[email protected]61b4efc2012-04-27 18:12:50151 SpdySessionDependencies* session_deps)
[email protected]30c942b2010-07-21 16:59:59152 : request_(request),
[email protected]262eec82013-03-19 21:01:36153 priority_(priority),
[email protected]61b4efc2012-04-27 18:12:50154 session_deps_(session_deps == NULL ?
[email protected]513963e2013-06-15 01:53:04155 CreateSpdySessionDependencies(test_params) :
156 session_deps),
[email protected]b261d0e2010-08-02 19:13:24157 session_(SpdySessionDependencies::SpdyCreateSession(
[email protected]80a09a82012-11-16 17:40:06158 session_deps_.get())),
[email protected]9e9e842e2010-07-23 23:09:15159 log_(log),
[email protected]513963e2013-06-15 01:53:04160 test_params_(test_params),
[email protected]1f418ee2010-10-16 19:46:56161 deterministic_(false),
162 spdy_enabled_(true) {
[email protected]513963e2013-06-15 01:53:04163 switch (test_params_.ssl_type) {
[email protected]80a09a82012-11-16 17:40:06164 case SPDYNOSSL:
165 case SPDYSSL:
166 port_ = 80;
167 break;
168 case SPDYNPN:
169 port_ = 443;
170 break;
171 default:
172 NOTREACHED();
173 }
[email protected]e37ce372012-07-12 01:00:40174 }
[email protected]61b4efc2012-04-27 18:12:50175
[email protected]19ec8a72010-08-23 03:38:23176 ~NormalSpdyTransactionHelper() {
177 // Any test which doesn't close the socket by sending it an EOF will
178 // have a valid session left open, which leaks the entire session pool.
179 // This is just fine - in fact, some of our tests intentionally do this
180 // so that we can check consistency of the SpdySessionPool as the test
181 // finishes. If we had put an EOF on the socket, the SpdySession would
182 // have closed and we wouldn't be able to check the consistency.
183
184 // Forcefully close existing sessions here.
185 session()->spdy_session_pool()->CloseAllSessions();
186 }
187
[email protected]3b7828432010-08-18 18:33:27188 void SetDeterministic() {
189 session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
190 session_deps_.get());
191 deterministic_ = true;
192 }
193
[email protected]1f418ee2010-10-16 19:46:56194 void SetSpdyDisabled() {
195 spdy_enabled_ = false;
[email protected]80a09a82012-11-16 17:40:06196 port_ = 80;
[email protected]1f418ee2010-10-16 19:46:56197 }
198
[email protected]3caf5542010-07-16 15:19:47199 void RunPreTestSetup() {
[email protected]b261d0e2010-08-02 19:13:24200 if (!session_deps_.get())
[email protected]513963e2013-06-15 01:53:04201 session_deps_.reset(CreateSpdySessionDependencies(test_params_));
[email protected]d7599122014-05-24 03:37:23202 if (!session_.get()) {
[email protected]b261d0e2010-08-02 19:13:24203 session_ = SpdySessionDependencies::SpdyCreateSession(
204 session_deps_.get());
[email protected]3caf5542010-07-16 15:19:47205 }
[email protected]aea80602009-09-18 00:55:08206
[email protected]3caf5542010-07-16 15:19:47207 // We're now ready to use SSL-npn SPDY.
[email protected]90499482013-06-01 00:39:50208 trans_.reset(new HttpNetworkTransaction(priority_, session_.get()));
[email protected]cb54b3b22010-06-03 16:28:55209 }
[email protected]aea80602009-09-18 00:55:08210
[email protected]3caf5542010-07-16 15:19:47211 // Start the transaction, read some data, finish.
212 void RunDefaultTest() {
[email protected]34b345f92013-02-22 03:27:26213 if (!StartDefaultTest())
214 return;
215 FinishDefaultTest();
[email protected]34b345f92013-02-22 03:27:26216 }
217
218 bool StartDefaultTest() {
[email protected]514aeaf2014-05-23 10:31:51219 output_.rv = trans_->Start(&request_, callback_.callback(), log_);
[email protected]aea80602009-09-18 00:55:08220
[email protected]3caf5542010-07-16 15:19:47221 // We expect an IO Pending or some sort of error.
222 EXPECT_LT(output_.rv, 0);
[email protected]34b345f92013-02-22 03:27:26223 return output_.rv == ERR_IO_PENDING;
224 }
[email protected]aea80602009-09-18 00:55:08225
[email protected]34b345f92013-02-22 03:27:26226 void FinishDefaultTest() {
[email protected]514aeaf2014-05-23 10:31:51227 output_.rv = callback_.WaitForResult();
[email protected]3caf5542010-07-16 15:19:47228 if (output_.rv != OK) {
[email protected]7af985a2012-12-14 22:40:42229 session_->spdy_session_pool()->CloseCurrentSessions(net::ERR_ABORTED);
[email protected]3caf5542010-07-16 15:19:47230 return;
231 }
[email protected]ff57bb82009-11-12 06:52:14232
[email protected]3caf5542010-07-16 15:19:47233 // Verify responses.
234 const HttpResponseInfo* response = trans_->GetResponseInfo();
235 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:50236 ASSERT_TRUE(response->headers.get() != NULL);
[email protected]3caf5542010-07-16 15:19:47237 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]1f418ee2010-10-16 19:46:56238 EXPECT_EQ(spdy_enabled_, response->was_fetched_via_spdy);
[email protected]808957c2013-03-13 03:51:27239 if (HttpStreamFactory::spdy_enabled()) {
[email protected]88a332622013-07-30 07:13:32240 EXPECT_EQ(
241 HttpResponseInfo::ConnectionInfoFromNextProto(
242 test_params_.protocol),
243 response->connection_info);
[email protected]808957c2013-03-13 03:51:27244 } else {
245 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1,
246 response->connection_info);
247 }
[email protected]513963e2013-06-15 01:53:04248 if (test_params_.ssl_type == SPDYNPN && spdy_enabled_) {
[email protected]9e9e842e2010-07-23 23:09:15249 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]a33cad2b62010-07-30 22:24:39250 } else {
[email protected]9e9e842e2010-07-23 23:09:15251 EXPECT_TRUE(!response->was_npn_negotiated);
[email protected]9e9e842e2010-07-23 23:09:15252 }
[email protected]1f418ee2010-10-16 19:46:56253 // If SPDY is not enabled, a HTTP request should not be diverted
254 // over a SSL session.
255 if (!spdy_enabled_) {
256 EXPECT_EQ(request_.url.SchemeIs("https"),
257 response->was_npn_negotiated);
258 }
[email protected]80a09a82012-11-16 17:40:06259 EXPECT_EQ("127.0.0.1", response->socket_address.host());
260 EXPECT_EQ(port_, response->socket_address.port());
[email protected]3caf5542010-07-16 15:19:47261 output_.status_line = response->headers->GetStatusLine();
262 output_.response_info = *response; // Make a copy so we can verify.
263 output_.rv = ReadTransaction(trans_.get(), &output_.response_data);
[email protected]3caf5542010-07-16 15:19:47264 }
265
266 // Most tests will want to call this function. In particular, the MockReads
267 // should end with an empty read, and that read needs to be processed to
268 // ensure proper deletion of the spdy_session_pool.
269 void VerifyDataConsumed() {
[email protected]a33cad2b62010-07-30 22:24:39270 for (DataVector::iterator it = data_vector_.begin();
[email protected]3caf5542010-07-16 15:19:47271 it != data_vector_.end(); ++it) {
272 EXPECT_TRUE((*it)->at_read_eof()) << "Read count: "
273 << (*it)->read_count()
274 << " Read index: "
275 << (*it)->read_index();
276 EXPECT_TRUE((*it)->at_write_eof()) << "Write count: "
277 << (*it)->write_count()
278 << " Write index: "
279 << (*it)->write_index();
280 }
281 }
282
283 // Occasionally a test will expect to error out before certain reads are
284 // processed. In that case we want to explicitly ensure that the reads were
285 // not processed.
286 void VerifyDataNotConsumed() {
[email protected]a33cad2b62010-07-30 22:24:39287 for (DataVector::iterator it = data_vector_.begin();
[email protected]3caf5542010-07-16 15:19:47288 it != data_vector_.end(); ++it) {
289 EXPECT_TRUE(!(*it)->at_read_eof()) << "Read count: "
290 << (*it)->read_count()
291 << " Read index: "
292 << (*it)->read_index();
293 EXPECT_TRUE(!(*it)->at_write_eof()) << "Write count: "
294 << (*it)->write_count()
295 << " Write index: "
296 << (*it)->write_index();
[email protected]3caf5542010-07-16 15:19:47297 }
298 }
299
300 void RunToCompletion(StaticSocketDataProvider* data) {
[email protected]3caf5542010-07-16 15:19:47301 RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:58302 AddData(data);
[email protected]3caf5542010-07-16 15:19:47303 RunDefaultTest();
304 VerifyDataConsumed();
305 }
[email protected]e6b06862010-07-20 16:32:58306
[email protected]514aeaf2014-05-23 10:31:51307 void RunToCompletionWithSSLData(
308 StaticSocketDataProvider* data,
309 scoped_ptr<SSLSocketDataProvider> ssl_provider) {
310 RunPreTestSetup();
311 AddDataWithSSLSocketDataProvider(data, ssl_provider.Pass());
312 RunDefaultTest();
313 VerifyDataConsumed();
314 }
315
[email protected]3caf5542010-07-16 15:19:47316 void AddData(StaticSocketDataProvider* data) {
[email protected]514aeaf2014-05-23 10:31:51317 scoped_ptr<SSLSocketDataProvider> ssl_provider(
318 new SSLSocketDataProvider(ASYNC, OK));
319 AddDataWithSSLSocketDataProvider(data, ssl_provider.Pass());
320 }
321
322 void AddDataWithSSLSocketDataProvider(
323 StaticSocketDataProvider* data,
324 scoped_ptr<SSLSocketDataProvider> ssl_provider) {
[email protected]3b7828432010-08-18 18:33:27325 DCHECK(!deterministic_);
[email protected]3caf5542010-07-16 15:19:47326 data_vector_.push_back(data);
[email protected]513963e2013-06-15 01:53:04327 if (test_params_.ssl_type == SPDYNPN)
328 ssl_provider->SetNextProto(test_params_.protocol);
[email protected]d4f00222012-07-10 06:24:51329
[email protected]514aeaf2014-05-23 10:31:51330 if (test_params_.ssl_type == SPDYNPN ||
331 test_params_.ssl_type == SPDYSSL) {
332 session_deps_->socket_factory->AddSSLSocketDataProvider(
333 ssl_provider.get());
334 }
335 ssl_vector_.push_back(ssl_provider.release());
[email protected]d4f00222012-07-10 06:24:51336
[email protected]3b7828432010-08-18 18:33:27337 session_deps_->socket_factory->AddSocketDataProvider(data);
[email protected]513963e2013-06-15 01:53:04338 if (test_params_.ssl_type == SPDYNPN) {
[email protected]d973e99a2012-02-17 21:02:36339 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]d4f00222012-07-10 06:24:51340 StaticSocketDataProvider* hanging_non_alternate_protocol_socket =
[email protected]513963e2013-06-15 01:53:04341 new StaticSocketDataProvider(NULL, 0, NULL, 0);
[email protected]2d6728692011-03-12 01:39:55342 hanging_non_alternate_protocol_socket->set_connect_data(
343 never_finishing_connect);
344 session_deps_->socket_factory->AddSocketDataProvider(
[email protected]d4f00222012-07-10 06:24:51345 hanging_non_alternate_protocol_socket);
[email protected]2d6728692011-03-12 01:39:55346 alternate_vector_.push_back(hanging_non_alternate_protocol_socket);
347 }
[email protected]3b7828432010-08-18 18:33:27348 }
349
350 void AddDeterministicData(DeterministicSocketData* data) {
351 DCHECK(deterministic_);
352 data_vector_.push_back(data);
[email protected]d4f00222012-07-10 06:24:51353 SSLSocketDataProvider* ssl_provider =
354 new SSLSocketDataProvider(ASYNC, OK);
[email protected]513963e2013-06-15 01:53:04355 if (test_params_.ssl_type == SPDYNPN)
356 ssl_provider->SetNextProto(test_params_.protocol);
[email protected]d4f00222012-07-10 06:24:51357
358 ssl_vector_.push_back(ssl_provider);
[email protected]513963e2013-06-15 01:53:04359 if (test_params_.ssl_type == SPDYNPN ||
360 test_params_.ssl_type == SPDYSSL) {
[email protected]3b7828432010-08-18 18:33:27361 session_deps_->deterministic_socket_factory->
[email protected]d4f00222012-07-10 06:24:51362 AddSSLSocketDataProvider(ssl_provider);
[email protected]2d6728692011-03-12 01:39:55363 }
[email protected]3b7828432010-08-18 18:33:27364 session_deps_->deterministic_socket_factory->AddSocketDataProvider(data);
[email protected]513963e2013-06-15 01:53:04365 if (test_params_.ssl_type == SPDYNPN) {
[email protected]d973e99a2012-02-17 21:02:36366 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]d4f00222012-07-10 06:24:51367 DeterministicSocketData* hanging_non_alternate_protocol_socket =
368 new DeterministicSocketData(NULL, 0, NULL, 0);
[email protected]2d6728692011-03-12 01:39:55369 hanging_non_alternate_protocol_socket->set_connect_data(
370 never_finishing_connect);
371 session_deps_->deterministic_socket_factory->AddSocketDataProvider(
372 hanging_non_alternate_protocol_socket);
373 alternate_deterministic_vector_.push_back(
374 hanging_non_alternate_protocol_socket);
375 }
[email protected]3caf5542010-07-16 15:19:47376 }
377
[email protected]a33cad2b62010-07-30 22:24:39378 void SetSession(const scoped_refptr<HttpNetworkSession>& session) {
[email protected]3caf5542010-07-16 15:19:47379 session_ = session;
380 }
381 HttpNetworkTransaction* trans() { return trans_.get(); }
382 void ResetTrans() { trans_.reset(); }
383 TransactionHelperResult& output() { return output_; }
[email protected]19ec8a72010-08-23 03:38:23384 const HttpRequestInfo& request() const { return request_; }
385 const scoped_refptr<HttpNetworkSession>& session() const {
386 return session_;
387 }
[email protected]b261d0e2010-08-02 19:13:24388 scoped_ptr<SpdySessionDependencies>& session_deps() {
389 return session_deps_;
390 }
[email protected]19ec8a72010-08-23 03:38:23391 int port() const { return port_; }
[email protected]513963e2013-06-15 01:53:04392 SpdyNetworkTransactionTestParams test_params() const {
393 return test_params_;
[email protected]448d4ca52012-03-04 04:12:23394 }
[email protected]3caf5542010-07-16 15:19:47395
396 private:
397 typedef std::vector<StaticSocketDataProvider*> DataVector;
[email protected]d4f00222012-07-10 06:24:51398 typedef ScopedVector<SSLSocketDataProvider> SSLVector;
399 typedef ScopedVector<StaticSocketDataProvider> AlternateVector;
400 typedef ScopedVector<DeterministicSocketData> AlternateDeterministicVector;
[email protected]3caf5542010-07-16 15:19:47401 HttpRequestInfo request_;
[email protected]262eec82013-03-19 21:01:36402 RequestPriority priority_;
[email protected]b261d0e2010-08-02 19:13:24403 scoped_ptr<SpdySessionDependencies> session_deps_;
[email protected]3caf5542010-07-16 15:19:47404 scoped_refptr<HttpNetworkSession> session_;
405 TransactionHelperResult output_;
406 scoped_ptr<StaticSocketDataProvider> first_transaction_;
407 SSLVector ssl_vector_;
[email protected]514aeaf2014-05-23 10:31:51408 TestCompletionCallback callback_;
[email protected]3caf5542010-07-16 15:19:47409 scoped_ptr<HttpNetworkTransaction> trans_;
410 scoped_ptr<HttpNetworkTransaction> trans_http_;
411 DataVector data_vector_;
[email protected]2d6728692011-03-12 01:39:55412 AlternateVector alternate_vector_;
413 AlternateDeterministicVector alternate_deterministic_vector_;
[email protected]3caf5542010-07-16 15:19:47414 const BoundNetLog& log_;
[email protected]513963e2013-06-15 01:53:04415 SpdyNetworkTransactionTestParams test_params_;
[email protected]9e9e842e2010-07-23 23:09:15416 int port_;
[email protected]3b7828432010-08-18 18:33:27417 bool deterministic_;
[email protected]1f418ee2010-10-16 19:46:56418 bool spdy_enabled_;
[email protected]3caf5542010-07-16 15:19:47419 };
[email protected]aea80602009-09-18 00:55:08420
421 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
422 int expected_status);
423
424 void ConnectStatusHelper(const MockRead& status);
[email protected]d3cee19d2010-06-22 18:42:18425
[email protected]e3ebba0f2010-08-05 17:59:58426 const HttpRequestInfo& CreateGetPushRequest() {
427 google_get_push_request_.method = "GET";
428 google_get_push_request_.url = GURL("http://www.google.com/foo.dat");
429 google_get_push_request_.load_flags = 0;
430 return google_get_push_request_;
431 }
432
[email protected]d3cee19d2010-06-22 18:42:18433 const HttpRequestInfo& CreateGetRequest() {
434 if (!google_get_request_initialized_) {
435 google_get_request_.method = "GET";
[email protected]310240592010-08-05 21:04:19436 google_get_request_.url = GURL(kDefaultURL);
[email protected]d3cee19d2010-06-22 18:42:18437 google_get_request_.load_flags = 0;
438 google_get_request_initialized_ = true;
439 }
440 return google_get_request_;
441 }
442
[email protected]3deb9a52010-11-11 00:24:40443 const HttpRequestInfo& CreateGetRequestWithUserAgent() {
444 if (!google_get_request_initialized_) {
445 google_get_request_.method = "GET";
446 google_get_request_.url = GURL(kDefaultURL);
447 google_get_request_.load_flags = 0;
448 google_get_request_.extra_headers.SetHeader("User-Agent", "Chrome");
449 google_get_request_initialized_ = true;
450 }
451 return google_get_request_;
452 }
453
[email protected]310240592010-08-05 21:04:19454 const HttpRequestInfo& CreatePostRequest() {
455 if (!google_post_request_initialized_) {
[email protected]b2d26cfd2012-12-11 10:36:06456 ScopedVector<UploadElementReader> element_readers;
457 element_readers.push_back(
458 new UploadBytesElementReader(kUploadData, kUploadDataSize));
[email protected]96c77a72013-09-24 09:49:20459 upload_data_stream_.reset(
mmenkecbc2b712014-10-09 20:29:07460 new ElementsUploadDataStream(element_readers.Pass(), 0));
[email protected]329b68b2012-11-14 17:54:27461
[email protected]310240592010-08-05 21:04:19462 google_post_request_.method = "POST";
463 google_post_request_.url = GURL(kDefaultURL);
[email protected]329b68b2012-11-14 17:54:27464 google_post_request_.upload_data_stream = upload_data_stream_.get();
[email protected]310240592010-08-05 21:04:19465 google_post_request_initialized_ = true;
466 }
467 return google_post_request_;
468 }
469
[email protected]69e6b4a2012-10-18 08:03:01470 const HttpRequestInfo& CreateFilePostRequest() {
471 if (!google_post_request_initialized_) {
[email protected]6cdfd7f2013-02-08 20:40:15472 base::FilePath file_path;
[email protected]03d9afc02013-12-03 17:55:52473 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
[email protected]69e6b4a2012-10-18 08:03:01474 CHECK_EQ(static_cast<int>(kUploadDataSize),
[email protected]e5c2a22e2014-03-06 20:42:30475 base::WriteFile(file_path, kUploadData, kUploadDataSize));
[email protected]69e6b4a2012-10-18 08:03:01476
[email protected]b2d26cfd2012-12-11 10:36:06477 ScopedVector<UploadElementReader> element_readers;
[email protected]cadac622013-06-11 16:46:36478 element_readers.push_back(
479 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
480 file_path,
481 0,
482 kUploadDataSize,
483 base::Time()));
[email protected]96c77a72013-09-24 09:49:20484 upload_data_stream_.reset(
mmenkecbc2b712014-10-09 20:29:07485 new ElementsUploadDataStream(element_readers.Pass(), 0));
[email protected]329b68b2012-11-14 17:54:27486
[email protected]69e6b4a2012-10-18 08:03:01487 google_post_request_.method = "POST";
488 google_post_request_.url = GURL(kDefaultURL);
[email protected]329b68b2012-11-14 17:54:27489 google_post_request_.upload_data_stream = upload_data_stream_.get();
[email protected]69e6b4a2012-10-18 08:03:01490 google_post_request_initialized_ = true;
491 }
492 return google_post_request_;
493 }
494
[email protected]999dd8c2013-11-12 06:45:54495 const HttpRequestInfo& CreateUnreadableFilePostRequest() {
496 if (google_post_request_initialized_)
497 return google_post_request_;
498
499 base::FilePath file_path;
[email protected]03d9afc02013-12-03 17:55:52500 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
[email protected]999dd8c2013-11-12 06:45:54501 CHECK_EQ(static_cast<int>(kUploadDataSize),
[email protected]e5c2a22e2014-03-06 20:42:30502 base::WriteFile(file_path, kUploadData, kUploadDataSize));
[email protected]92be8eb2014-08-07 22:57:11503 CHECK(base::MakeFileUnreadable(file_path));
[email protected]999dd8c2013-11-12 06:45:54504
505 ScopedVector<UploadElementReader> element_readers;
506 element_readers.push_back(
507 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
508 file_path,
509 0,
510 kUploadDataSize,
511 base::Time()));
512 upload_data_stream_.reset(
mmenkecbc2b712014-10-09 20:29:07513 new ElementsUploadDataStream(element_readers.Pass(), 0));
[email protected]999dd8c2013-11-12 06:45:54514
515 google_post_request_.method = "POST";
516 google_post_request_.url = GURL(kDefaultURL);
517 google_post_request_.upload_data_stream = upload_data_stream_.get();
518 google_post_request_initialized_ = true;
519 return google_post_request_;
520 }
521
[email protected]69e6b4a2012-10-18 08:03:01522 const HttpRequestInfo& CreateComplexPostRequest() {
523 if (!google_post_request_initialized_) {
524 const int kFileRangeOffset = 1;
525 const int kFileRangeLength = 3;
526 CHECK_LT(kFileRangeOffset + kFileRangeLength, kUploadDataSize);
527
[email protected]6cdfd7f2013-02-08 20:40:15528 base::FilePath file_path;
[email protected]03d9afc02013-12-03 17:55:52529 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
[email protected]69e6b4a2012-10-18 08:03:01530 CHECK_EQ(static_cast<int>(kUploadDataSize),
[email protected]e5c2a22e2014-03-06 20:42:30531 base::WriteFile(file_path, kUploadData, kUploadDataSize));
[email protected]69e6b4a2012-10-18 08:03:01532
[email protected]b2d26cfd2012-12-11 10:36:06533 ScopedVector<UploadElementReader> element_readers;
534 element_readers.push_back(
535 new UploadBytesElementReader(kUploadData, kFileRangeOffset));
[email protected]cadac622013-06-11 16:46:36536 element_readers.push_back(
537 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
538 file_path,
539 kFileRangeOffset,
540 kFileRangeLength,
541 base::Time()));
[email protected]b2d26cfd2012-12-11 10:36:06542 element_readers.push_back(new UploadBytesElementReader(
[email protected]69e6b4a2012-10-18 08:03:01543 kUploadData + kFileRangeOffset + kFileRangeLength,
[email protected]b2d26cfd2012-12-11 10:36:06544 kUploadDataSize - (kFileRangeOffset + kFileRangeLength)));
[email protected]96c77a72013-09-24 09:49:20545 upload_data_stream_.reset(
mmenkecbc2b712014-10-09 20:29:07546 new ElementsUploadDataStream(element_readers.Pass(), 0));
[email protected]329b68b2012-11-14 17:54:27547
548 google_post_request_.method = "POST";
549 google_post_request_.url = GURL(kDefaultURL);
550 google_post_request_.upload_data_stream = upload_data_stream_.get();
[email protected]69e6b4a2012-10-18 08:03:01551 google_post_request_initialized_ = true;
552 }
553 return google_post_request_;
554 }
555
[email protected]0c9bf872011-03-04 17:53:22556 const HttpRequestInfo& CreateChunkedPostRequest() {
557 if (!google_chunked_post_request_initialized_) {
mmenkecbc2b712014-10-09 20:29:07558 upload_chunked_data_stream_.reset(new ChunkedUploadDataStream(0));
[email protected]0c9bf872011-03-04 17:53:22559 google_chunked_post_request_.method = "POST";
560 google_chunked_post_request_.url = GURL(kDefaultURL);
[email protected]329b68b2012-11-14 17:54:27561 google_chunked_post_request_.upload_data_stream =
mmenkecbc2b712014-10-09 20:29:07562 upload_chunked_data_stream_.get();
[email protected]0c9bf872011-03-04 17:53:22563 google_chunked_post_request_initialized_ = true;
564 }
565 return google_chunked_post_request_;
566 }
567
[email protected]19ec8a72010-08-23 03:38:23568 // Read the result of a particular transaction, knowing that we've got
569 // multiple transactions in the read pipeline; so as we read, we may have
570 // to skip over data destined for other transactions while we consume
571 // the data for |trans|.
572 int ReadResult(HttpNetworkTransaction* trans,
[email protected]d08358502010-12-03 22:04:03573 StaticSocketDataProvider* data,
[email protected]19ec8a72010-08-23 03:38:23574 std::string* result) {
575 const int kSize = 3000;
[email protected]e3ebba0f2010-08-05 17:59:58576
[email protected]19ec8a72010-08-23 03:38:23577 int bytes_read = 0;
[email protected]ad8e04a2010-11-01 04:16:27578 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(kSize));
[email protected]49639fa2011-12-20 23:22:41579 TestCompletionCallback callback;
[email protected]19ec8a72010-08-23 03:38:23580 while (true) {
[email protected]90499482013-06-01 00:39:50581 int rv = trans->Read(buf.get(), kSize, callback.callback());
[email protected]19ec8a72010-08-23 03:38:23582 if (rv == ERR_IO_PENDING) {
583 // Multiple transactions may be in the data set. Keep pulling off
584 // reads until we complete our callback.
585 while (!callback.have_result()) {
586 data->CompleteRead();
[email protected]fc9d88472013-08-14 02:31:17587 base::RunLoop().RunUntilIdle();
[email protected]19ec8a72010-08-23 03:38:23588 }
589 rv = callback.WaitForResult();
590 } else if (rv <= 0) {
591 break;
592 }
593 result->append(buf->data(), rv);
594 bytes_read += rv;
[email protected]e3ebba0f2010-08-05 17:59:58595 }
[email protected]19ec8a72010-08-23 03:38:23596 return bytes_read;
597 }
[email protected]e3ebba0f2010-08-05 17:59:58598
[email protected]19ec8a72010-08-23 03:38:23599 void VerifyStreamsClosed(const NormalSpdyTransactionHelper& helper) {
600 // This lengthy block is reaching into the pool to dig out the active
601 // session. Once we have the session, we verify that the streams are
602 // all closed and not leaked at this point.
603 const GURL& url = helper.request().url;
[email protected]513963e2013-06-15 01:53:04604 int port = helper.test_params().ssl_type == SPDYNPN ? 443 : 80;
[email protected]19ec8a72010-08-23 03:38:23605 HostPortPair host_port_pair(url.host(), port);
[email protected]e6d017652013-05-17 18:01:40606 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
[email protected]314b03992014-04-01 01:28:53607 PRIVACY_MODE_DISABLED);
[email protected]19ec8a72010-08-23 03:38:23608 BoundNetLog log;
609 const scoped_refptr<HttpNetworkSession>& session = helper.session();
[email protected]795cbf82013-07-22 09:37:27610 base::WeakPtr<SpdySession> spdy_session =
[email protected]04644d42013-07-08 04:29:59611 session->spdy_session_pool()->FindAvailableSession(key, log);
[email protected]41d64e82013-07-03 22:44:26612 ASSERT_TRUE(spdy_session != NULL);
[email protected]19ec8a72010-08-23 03:38:23613 EXPECT_EQ(0u, spdy_session->num_active_streams());
614 EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams());
615 }
[email protected]e3ebba0f2010-08-05 17:59:58616
[email protected]d08358502010-12-03 22:04:03617 void RunServerPushTest(OrderedSocketData* data,
[email protected]e3ebba0f2010-08-05 17:59:58618 HttpResponseInfo* response,
[email protected]a7a265ef2010-12-08 18:05:57619 HttpResponseInfo* push_response,
[email protected]8a0fc822013-06-27 20:52:43620 const std::string& expected) {
[email protected]262eec82013-03-19 21:01:36621 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:50622 BoundNetLog(), GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:58623 helper.RunPreTestSetup();
[email protected]d08358502010-12-03 22:04:03624 helper.AddData(data);
[email protected]e3ebba0f2010-08-05 17:59:58625
626 HttpNetworkTransaction* trans = helper.trans();
627
628 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:41629 TestCompletionCallback callback;
630 int rv = trans->Start(
631 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]e3ebba0f2010-08-05 17:59:58632 EXPECT_EQ(ERR_IO_PENDING, rv);
633 rv = callback.WaitForResult();
634
635 // Request the pushed path.
[email protected]e3ebba0f2010-08-05 17:59:58636 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:50637 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]49639fa2011-12-20 23:22:41638 rv = trans2->Start(
639 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
[email protected]e3ebba0f2010-08-05 17:59:58640 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]fc9d88472013-08-14 02:31:17641 base::RunLoop().RunUntilIdle();
[email protected]e3ebba0f2010-08-05 17:59:58642
[email protected]513963e2013-06-15 01:53:04643 // The data for the pushed path may be coming in more than 1 frame. Compile
[email protected]e3ebba0f2010-08-05 17:59:58644 // the results into a single string.
[email protected]19ec8a72010-08-23 03:38:23645
646 // Read the server push body.
647 std::string result2;
648 ReadResult(trans2.get(), data, &result2);
649 // Read the response body.
[email protected]e3ebba0f2010-08-05 17:59:58650 std::string result;
[email protected]19ec8a72010-08-23 03:38:23651 ReadResult(trans, data, &result);
[email protected]e3ebba0f2010-08-05 17:59:58652
653 // Verify that we consumed all test data.
654 EXPECT_TRUE(data->at_read_eof());
655 EXPECT_TRUE(data->at_write_eof());
656
657 // Verify that the received push data is same as the expected push data.
[email protected]19ec8a72010-08-23 03:38:23658 EXPECT_EQ(result2.compare(expected), 0) << "Received data: "
659 << result2
660 << "||||| Expected data: "
661 << expected;
[email protected]e3ebba0f2010-08-05 17:59:58662
663 // Verify the SYN_REPLY.
664 // Copy the response info, because trans goes away.
665 *response = *trans->GetResponseInfo();
[email protected]a7a265ef2010-12-08 18:05:57666 *push_response = *trans2->GetResponseInfo();
[email protected]19ec8a72010-08-23 03:38:23667
668 VerifyStreamsClosed(helper);
[email protected]e3ebba0f2010-08-05 17:59:58669 }
670
[email protected]49639fa2011-12-20 23:22:41671 static void DeleteSessionCallback(NormalSpdyTransactionHelper* helper,
672 int result) {
673 helper->ResetTrans();
674 }
675
676 static void StartTransactionCallback(
677 const scoped_refptr<HttpNetworkSession>& session,
678 int result) {
679 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]90499482013-06-01 00:39:50680 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]49639fa2011-12-20 23:22:41681 TestCompletionCallback callback;
682 HttpRequestInfo request;
683 request.method = "GET";
684 request.url = GURL("http://www.google.com/");
685 request.load_flags = 0;
686 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
687 EXPECT_EQ(ERR_IO_PENDING, rv);
688 callback.WaitForResult();
689 }
690
mmenkecbc2b712014-10-09 20:29:07691 ChunkedUploadDataStream* upload_chunked_data_stream() const {
692 return upload_chunked_data_stream_.get();
693 }
694
[email protected]9ec54f82013-05-10 02:53:05695 SpdyTestUtil spdy_util_;
696
[email protected]d3cee19d2010-06-22 18:42:18697 private:
mmenkecbc2b712014-10-09 20:29:07698 scoped_ptr<ChunkedUploadDataStream> upload_chunked_data_stream_;
[email protected]329b68b2012-11-14 17:54:27699 scoped_ptr<UploadDataStream> upload_data_stream_;
[email protected]d3cee19d2010-06-22 18:42:18700 bool google_get_request_initialized_;
[email protected]310240592010-08-05 21:04:19701 bool google_post_request_initialized_;
[email protected]0c9bf872011-03-04 17:53:22702 bool google_chunked_post_request_initialized_;
[email protected]d3cee19d2010-06-22 18:42:18703 HttpRequestInfo google_get_request_;
[email protected]310240592010-08-05 21:04:19704 HttpRequestInfo google_post_request_;
[email protected]0c9bf872011-03-04 17:53:22705 HttpRequestInfo google_chunked_post_request_;
[email protected]e3ebba0f2010-08-05 17:59:58706 HttpRequestInfo google_get_push_request_;
[email protected]ea1a3f62012-11-16 20:34:23707 base::ScopedTempDir temp_dir_;
[email protected]aea80602009-09-18 00:55:08708};
709
710//-----------------------------------------------------------------------------
[email protected]9e9e842e2010-07-23 23:09:15711// All tests are run with three different connection types: SPDY after NPN
712// negotiation, SPDY without SSL, and SPDY with SSL.
[email protected]513963e2013-06-15 01:53:04713//
714// TODO(akalin): Use ::testing::Combine() when we are able to use
715// <tr1/tuple>.
716INSTANTIATE_TEST_CASE_P(
717 Spdy,
718 SpdyNetworkTransactionTest,
719 ::testing::Values(
[email protected]b05bcaa32013-10-06 05:26:02720 SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2, SPDYNOSSL),
721 SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2, SPDYSSL),
722 SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2, SPDYNPN),
[email protected]513963e2013-06-15 01:53:04723 SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYNOSSL),
724 SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYSSL),
725 SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYNPN),
726 SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNOSSL),
727 SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYSSL),
728 SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNPN),
[email protected]d10833bc2014-04-14 17:50:46729 SpdyNetworkTransactionTestParams(kProtoSPDY4, SPDYNOSSL),
730 SpdyNetworkTransactionTestParams(kProtoSPDY4, SPDYSSL),
731 SpdyNetworkTransactionTestParams(kProtoSPDY4, SPDYNPN)));
[email protected]aea80602009-09-18 00:55:08732
[email protected]3caf5542010-07-16 15:19:47733// Verify HttpNetworkTransaction constructor.
[email protected]513963e2013-06-15 01:53:04734TEST_P(SpdyNetworkTransactionTest, Constructor) {
[email protected]bb88e1d32013-05-03 23:11:07735 scoped_ptr<SpdySessionDependencies> session_deps(
[email protected]513963e2013-06-15 01:53:04736 CreateSpdySessionDependencies(GetParam()));
[email protected]ad8e04a2010-11-01 04:16:27737 scoped_refptr<HttpNetworkSession> session(
[email protected]bb88e1d32013-05-03 23:11:07738 SpdySessionDependencies::SpdyCreateSession(session_deps.get()));
[email protected]262eec82013-03-19 21:01:36739 scoped_ptr<HttpTransaction> trans(
[email protected]90499482013-06-01 00:39:50740 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
[email protected]aea80602009-09-18 00:55:08741}
742
[email protected]513963e2013-06-15 01:53:04743TEST_P(SpdyNetworkTransactionTest, Get) {
[email protected]75f30cc22010-06-28 21:41:38744 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:46745 scoped_ptr<SpdyFrame> req(
746 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]e7f75092010-07-01 22:39:13747 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]72552f02009-10-28 15:25:01748
[email protected]513963e2013-06-15 01:53:04749 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
750 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]72552f02009-10-28 15:25:01751 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:13752 CreateMockRead(*resp),
753 CreateMockRead(*body),
[email protected]8ddf8322012-02-23 18:08:06754 MockRead(ASYNC, 0, 0) // EOF
[email protected]72552f02009-10-28 15:25:01755 };
756
[email protected]dd54bd82012-07-19 23:44:57757 DelayedSocketData data(1, reads, arraysize(reads),
758 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:36759 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:50760 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:57761 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:47762 TransactionHelperResult out = helper.output();
[email protected]72552f02009-10-28 15:25:01763 EXPECT_EQ(OK, out.rv);
764 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
765 EXPECT_EQ("hello!", out.response_data);
766}
767
[email protected]513963e2013-06-15 01:53:04768TEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) {
[email protected]3d08dd382013-10-19 00:13:11769 for (RequestPriority p = MINIMUM_PRIORITY; p <= MAXIMUM_PRIORITY;
[email protected]31ae7ab2012-04-24 21:09:05770 p = RequestPriority(p + 1)) {
[email protected]c9c6f5c2010-07-31 01:30:03771 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:46772 scoped_ptr<SpdyFrame> req(
773 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, p, true));
[email protected]c9c6f5c2010-07-31 01:30:03774 MockWrite writes[] = { CreateMockWrite(*req) };
775
[email protected]86aa87b2013-02-15 01:10:03776 SpdyPriority spdy_prio = 0;
[email protected]513963e2013-06-15 01:53:04777 EXPECT_TRUE(GetSpdyPriority(spdy_util_.spdy_version(), *req, &spdy_prio));
[email protected]c9c6f5c2010-07-31 01:30:03778 // this repeats the RequestPriority-->SpdyPriority mapping from
779 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
780 // sure it's being done right.
[email protected]513963e2013-06-15 01:53:04781 if (spdy_util_.spdy_version() < SPDY3) {
mmenkecbc2b712014-10-09 20:29:07782 switch (p) {
[email protected]513963e2013-06-15 01:53:04783 case HIGHEST:
784 EXPECT_EQ(0, spdy_prio);
785 break;
786 case MEDIUM:
787 EXPECT_EQ(1, spdy_prio);
788 break;
789 case LOW:
790 case LOWEST:
791 EXPECT_EQ(2, spdy_prio);
792 break;
793 case IDLE:
794 EXPECT_EQ(3, spdy_prio);
795 break;
796 default:
797 FAIL();
798 }
799 } else {
800 switch(p) {
801 case HIGHEST:
802 EXPECT_EQ(0, spdy_prio);
803 break;
804 case MEDIUM:
805 EXPECT_EQ(1, spdy_prio);
806 break;
807 case LOW:
808 EXPECT_EQ(2, spdy_prio);
809 break;
810 case LOWEST:
811 EXPECT_EQ(3, spdy_prio);
812 break;
813 case IDLE:
814 EXPECT_EQ(4, spdy_prio);
815 break;
816 default:
817 FAIL();
818 }
[email protected]c9c6f5c2010-07-31 01:30:03819 }
820
[email protected]513963e2013-06-15 01:53:04821 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
822 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c9c6f5c2010-07-31 01:30:03823 MockRead reads[] = {
824 CreateMockRead(*resp),
825 CreateMockRead(*body),
[email protected]8ddf8322012-02-23 18:08:06826 MockRead(ASYNC, 0, 0) // EOF
[email protected]c9c6f5c2010-07-31 01:30:03827 };
828
[email protected]dd54bd82012-07-19 23:44:57829 DelayedSocketData data(1, reads, arraysize(reads),
830 writes, arraysize(writes));
[email protected]c9c6f5c2010-07-31 01:30:03831 HttpRequestInfo http_req = CreateGetRequest();
[email protected]c9c6f5c2010-07-31 01:30:03832
[email protected]262eec82013-03-19 21:01:36833 NormalSpdyTransactionHelper helper(http_req, p, BoundNetLog(),
[email protected]61b4efc2012-04-27 18:12:50834 GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:57835 helper.RunToCompletion(&data);
[email protected]c9c6f5c2010-07-31 01:30:03836 TransactionHelperResult out = helper.output();
837 EXPECT_EQ(OK, out.rv);
838 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
839 EXPECT_EQ("hello!", out.response_data);
840 }
841}
842
[email protected]2bd93022010-07-17 00:58:44843// Start three gets simultaniously; making sure that multiplexed
844// streams work properly.
845
846// This can't use the TransactionHelper method, since it only
847// handles a single transaction, and finishes them as soon
848// as it launches them.
849
850// TODO(gavinp): create a working generalized TransactionHelper that
851// can allow multiple streams in flight.
852
[email protected]513963e2013-06-15 01:53:04853TEST_P(SpdyNetworkTransactionTest, ThreeGets) {
[email protected]cdf8f7e72013-05-23 10:56:46854 scoped_ptr<SpdyFrame> req(
855 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:04856 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
857 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
858 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2bd93022010-07-17 00:58:44859
[email protected]cdf8f7e72013-05-23 10:56:46860 scoped_ptr<SpdyFrame> req2(
861 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:04862 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
863 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
864 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]2bd93022010-07-17 00:58:44865
[email protected]cdf8f7e72013-05-23 10:56:46866 scoped_ptr<SpdyFrame> req3(
867 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
[email protected]513963e2013-06-15 01:53:04868 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
869 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
870 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
[email protected]2bd93022010-07-17 00:58:44871
[email protected]1b323172011-03-01 17:50:17872 MockWrite writes[] = {
873 CreateMockWrite(*req),
874 CreateMockWrite(*req2),
875 CreateMockWrite(*req3),
[email protected]2bd93022010-07-17 00:58:44876 };
877 MockRead reads[] = {
878 CreateMockRead(*resp, 1),
879 CreateMockRead(*body),
880 CreateMockRead(*resp2, 4),
881 CreateMockRead(*body2),
882 CreateMockRead(*resp3, 7),
883 CreateMockRead(*body3),
884
885 CreateMockRead(*fbody),
886 CreateMockRead(*fbody2),
887 CreateMockRead(*fbody3),
888
[email protected]8ddf8322012-02-23 18:08:06889 MockRead(ASYNC, 0, 0), // EOF
[email protected]2bd93022010-07-17 00:58:44890 };
[email protected]dd54bd82012-07-19 23:44:57891 OrderedSocketData data(reads, arraysize(reads),
892 writes, arraysize(writes));
893 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
[email protected]2bd93022010-07-17 00:58:44894
895 BoundNetLog log;
896 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:36897 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:50898 BoundNetLog(), GetParam(), NULL);
[email protected]bdebd1b2010-08-09 20:18:08899 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:57900 helper.AddData(&data);
[email protected]bdebd1b2010-08-09 20:18:08901 // We require placeholder data because three get requests are sent out, so
902 // there needs to be three sets of SSL connection data.
[email protected]dd54bd82012-07-19 23:44:57903 helper.AddData(&data_placeholder);
904 helper.AddData(&data_placeholder);
[email protected]bdebd1b2010-08-09 20:18:08905 scoped_ptr<HttpNetworkTransaction> trans1(
[email protected]90499482013-06-01 00:39:50906 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:08907 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:50908 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:08909 scoped_ptr<HttpNetworkTransaction> trans3(
[email protected]90499482013-06-01 00:39:50910 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]2bd93022010-07-17 00:58:44911
[email protected]49639fa2011-12-20 23:22:41912 TestCompletionCallback callback1;
913 TestCompletionCallback callback2;
914 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:44915
[email protected]bdebd1b2010-08-09 20:18:08916 HttpRequestInfo httpreq1 = CreateGetRequest();
917 HttpRequestInfo httpreq2 = CreateGetRequest();
918 HttpRequestInfo httpreq3 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:44919
[email protected]49639fa2011-12-20 23:22:41920 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:08921 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:41922 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:08923 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:41924 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:08925 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]2bd93022010-07-17 00:58:44926
[email protected]bdebd1b2010-08-09 20:18:08927 out.rv = callback1.WaitForResult();
928 ASSERT_EQ(OK, out.rv);
929 out.rv = callback3.WaitForResult();
930 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:44931
[email protected]bdebd1b2010-08-09 20:18:08932 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]90499482013-06-01 00:39:50933 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]bdebd1b2010-08-09 20:18:08934 EXPECT_TRUE(response1->was_fetched_via_spdy);
935 out.status_line = response1->headers->GetStatusLine();
936 out.response_info = *response1;
[email protected]2bd93022010-07-17 00:58:44937
[email protected]bdebd1b2010-08-09 20:18:08938 trans2->GetResponseInfo();
[email protected]2bd93022010-07-17 00:58:44939
[email protected]bdebd1b2010-08-09 20:18:08940 out.rv = ReadTransaction(trans1.get(), &out.response_data);
941 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:44942 EXPECT_EQ(OK, out.rv);
943
[email protected]2bd93022010-07-17 00:58:44944 EXPECT_EQ(OK, out.rv);
945 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
946 EXPECT_EQ("hello!hello!", out.response_data);
947}
948
[email protected]513963e2013-06-15 01:53:04949TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
[email protected]cdf8f7e72013-05-23 10:56:46950 scoped_ptr<SpdyFrame> req(
951 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:04952 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
953 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
954 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]1b323172011-03-01 17:50:17955
[email protected]cdf8f7e72013-05-23 10:56:46956 scoped_ptr<SpdyFrame> req2(
957 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:04958 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
959 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
960 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]1b323172011-03-01 17:50:17961
962 MockWrite writes[] = {
963 CreateMockWrite(*req),
964 CreateMockWrite(*req2),
965 };
966 MockRead reads[] = {
967 CreateMockRead(*resp, 1),
968 CreateMockRead(*body),
969 CreateMockRead(*resp2, 4),
970 CreateMockRead(*body2),
971 CreateMockRead(*fbody),
972 CreateMockRead(*fbody2),
[email protected]8ddf8322012-02-23 18:08:06973 MockRead(ASYNC, 0, 0), // EOF
[email protected]1b323172011-03-01 17:50:17974 };
[email protected]dd54bd82012-07-19 23:44:57975 OrderedSocketData data(reads, arraysize(reads),
976 writes, arraysize(writes));
[email protected]1b323172011-03-01 17:50:17977
[email protected]d973e99a2012-02-17 21:02:36978 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]1b323172011-03-01 17:50:17979
[email protected]dd54bd82012-07-19 23:44:57980 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
981 data_placeholder.set_connect_data(never_finishing_connect);
[email protected]1b323172011-03-01 17:50:17982
983 BoundNetLog log;
984 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:36985 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:50986 BoundNetLog(), GetParam(), NULL);
[email protected]1b323172011-03-01 17:50:17987 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:57988 helper.AddData(&data);
[email protected]1b323172011-03-01 17:50:17989 // We require placeholder data because two get requests are sent out, so
990 // there needs to be two sets of SSL connection data.
[email protected]dd54bd82012-07-19 23:44:57991 helper.AddData(&data_placeholder);
[email protected]1b323172011-03-01 17:50:17992 scoped_ptr<HttpNetworkTransaction> trans1(
[email protected]90499482013-06-01 00:39:50993 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]1b323172011-03-01 17:50:17994 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:50995 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]1b323172011-03-01 17:50:17996
[email protected]49639fa2011-12-20 23:22:41997 TestCompletionCallback callback1;
998 TestCompletionCallback callback2;
[email protected]1b323172011-03-01 17:50:17999
1000 HttpRequestInfo httpreq1 = CreateGetRequest();
1001 HttpRequestInfo httpreq2 = CreateGetRequest();
1002
[email protected]49639fa2011-12-20 23:22:411003 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]1b323172011-03-01 17:50:171004 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:411005 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]1b323172011-03-01 17:50:171006 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1007
1008 out.rv = callback1.WaitForResult();
1009 ASSERT_EQ(OK, out.rv);
1010 out.rv = callback2.WaitForResult();
1011 ASSERT_EQ(OK, out.rv);
1012
1013 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]90499482013-06-01 00:39:501014 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]1b323172011-03-01 17:50:171015 EXPECT_TRUE(response1->was_fetched_via_spdy);
1016 out.status_line = response1->headers->GetStatusLine();
1017 out.response_info = *response1;
1018 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1019 EXPECT_EQ(OK, out.rv);
1020 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1021 EXPECT_EQ("hello!hello!", out.response_data);
1022
1023 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
[email protected]90499482013-06-01 00:39:501024 EXPECT_TRUE(response2->headers.get() != NULL);
[email protected]1b323172011-03-01 17:50:171025 EXPECT_TRUE(response2->was_fetched_via_spdy);
1026 out.status_line = response2->headers->GetStatusLine();
1027 out.response_info = *response2;
1028 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1029 EXPECT_EQ(OK, out.rv);
1030 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1031 EXPECT_EQ("hello!hello!", out.response_data);
1032
1033 helper.VerifyDataConsumed();
1034}
1035
[email protected]513963e2013-06-15 01:53:041036TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
[email protected]cdf8f7e72013-05-23 10:56:461037 scoped_ptr<SpdyFrame> req(
1038 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041039 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1040 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1041 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]1b323172011-03-01 17:50:171042
[email protected]cdf8f7e72013-05-23 10:56:461043 scoped_ptr<SpdyFrame> req2(
1044 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041045 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1046 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1047 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]1b323172011-03-01 17:50:171048
1049 MockWrite writes[] = {
1050 CreateMockWrite(*req),
1051 CreateMockWrite(*req2),
1052 };
1053 MockRead reads[] = {
1054 CreateMockRead(*resp, 1),
1055 CreateMockRead(*body),
1056 CreateMockRead(*resp2, 4),
1057 CreateMockRead(*body2),
1058 CreateMockRead(*fbody),
1059 CreateMockRead(*fbody2),
[email protected]8ddf8322012-02-23 18:08:061060 MockRead(ASYNC, 0, 0), // EOF
[email protected]1b323172011-03-01 17:50:171061 };
[email protected]dd54bd82012-07-19 23:44:571062 OrderedSocketData preconnect_data(reads, arraysize(reads),
1063 writes, arraysize(writes));
[email protected]1b323172011-03-01 17:50:171064
[email protected]d973e99a2012-02-17 21:02:361065 MockConnect never_finishing_connect(ASYNC, ERR_IO_PENDING);
[email protected]1b323172011-03-01 17:50:171066
[email protected]dd54bd82012-07-19 23:44:571067 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1068 data_placeholder.set_connect_data(never_finishing_connect);
[email protected]1b323172011-03-01 17:50:171069
1070 BoundNetLog log;
1071 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361072 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501073 BoundNetLog(), GetParam(), NULL);
[email protected]1b323172011-03-01 17:50:171074 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571075 helper.AddData(&preconnect_data);
[email protected]1b323172011-03-01 17:50:171076 // We require placeholder data because 3 connections are attempted (first is
1077 // the preconnect, 2nd and 3rd are the never finished connections.
[email protected]dd54bd82012-07-19 23:44:571078 helper.AddData(&data_placeholder);
1079 helper.AddData(&data_placeholder);
[email protected]1b323172011-03-01 17:50:171080
1081 scoped_ptr<HttpNetworkTransaction> trans1(
[email protected]90499482013-06-01 00:39:501082 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]1b323172011-03-01 17:50:171083 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:501084 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]1b323172011-03-01 17:50:171085
[email protected]49639fa2011-12-20 23:22:411086 TestCompletionCallback callback1;
1087 TestCompletionCallback callback2;
[email protected]1b323172011-03-01 17:50:171088
1089 HttpRequestInfo httpreq = CreateGetRequest();
1090
1091 // Preconnect the first.
1092 SSLConfig preconnect_ssl_config;
1093 helper.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config);
1094 HttpStreamFactory* http_stream_factory =
1095 helper.session()->http_stream_factory();
[email protected]d7599122014-05-24 03:37:231096 helper.session()->GetNextProtos(&preconnect_ssl_config.next_protos);
[email protected]1b323172011-03-01 17:50:171097
1098 http_stream_factory->PreconnectStreams(
[email protected]262eec82013-03-19 21:01:361099 1, httpreq, DEFAULT_PRIORITY,
1100 preconnect_ssl_config, preconnect_ssl_config);
[email protected]1b323172011-03-01 17:50:171101
[email protected]49639fa2011-12-20 23:22:411102 out.rv = trans1->Start(&httpreq, callback1.callback(), log);
[email protected]1b323172011-03-01 17:50:171103 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:411104 out.rv = trans2->Start(&httpreq, callback2.callback(), log);
[email protected]1b323172011-03-01 17:50:171105 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1106
1107 out.rv = callback1.WaitForResult();
1108 ASSERT_EQ(OK, out.rv);
1109 out.rv = callback2.WaitForResult();
1110 ASSERT_EQ(OK, out.rv);
1111
1112 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]90499482013-06-01 00:39:501113 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]1b323172011-03-01 17:50:171114 EXPECT_TRUE(response1->was_fetched_via_spdy);
1115 out.status_line = response1->headers->GetStatusLine();
1116 out.response_info = *response1;
1117 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1118 EXPECT_EQ(OK, out.rv);
1119 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1120 EXPECT_EQ("hello!hello!", out.response_data);
1121
1122 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
[email protected]90499482013-06-01 00:39:501123 EXPECT_TRUE(response2->headers.get() != NULL);
[email protected]1b323172011-03-01 17:50:171124 EXPECT_TRUE(response2->was_fetched_via_spdy);
1125 out.status_line = response2->headers->GetStatusLine();
1126 out.response_info = *response2;
1127 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1128 EXPECT_EQ(OK, out.rv);
1129 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1130 EXPECT_EQ("hello!hello!", out.response_data);
1131
1132 helper.VerifyDataConsumed();
1133}
1134
[email protected]2bd93022010-07-17 00:58:441135// Similar to ThreeGets above, however this test adds a SETTINGS
1136// frame. The SETTINGS frame is read during the IO loop waiting on
1137// the first transaction completion, and sets a maximum concurrent
1138// stream limit of 1. This means that our IO loop exists after the
1139// second transaction completes, so we can assert on read_index().
[email protected]513963e2013-06-15 01:53:041140TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
[email protected]2bd93022010-07-17 00:58:441141 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:461142 scoped_ptr<SpdyFrame> req(
1143 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041144 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1145 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1146 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2bd93022010-07-17 00:58:441147
[email protected]cdf8f7e72013-05-23 10:56:461148 scoped_ptr<SpdyFrame> req2(
1149 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041150 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1151 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1152 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]2bd93022010-07-17 00:58:441153
[email protected]cdf8f7e72013-05-23 10:56:461154 scoped_ptr<SpdyFrame> req3(
1155 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041156 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
1157 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
1158 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
[email protected]2bd93022010-07-17 00:58:441159
[email protected]18b28ab2012-04-18 02:14:421160 SettingsMap settings;
[email protected]9dcec242013-01-10 23:24:281161 const uint32 max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:421162 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1163 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
[email protected]c10b20852013-05-15 21:29:201164 scoped_ptr<SpdyFrame> settings_frame(
1165 spdy_util_.ConstructSpdySettings(settings));
[email protected]d4a77c12014-05-15 20:45:211166 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]2bd93022010-07-17 00:58:441167
[email protected]2d6728692011-03-12 01:39:551168 MockWrite writes[] = {
1169 CreateMockWrite(*req),
[email protected]d4a77c12014-05-15 20:45:211170 CreateMockWrite(*settings_ack, 2),
[email protected]2d6728692011-03-12 01:39:551171 CreateMockWrite(*req2),
1172 CreateMockWrite(*req3),
[email protected]2bd93022010-07-17 00:58:441173 };
[email protected]2d6728692011-03-12 01:39:551174
[email protected]2bd93022010-07-17 00:58:441175 MockRead reads[] = {
[email protected]bdebd1b2010-08-09 20:18:081176 CreateMockRead(*settings_frame, 1),
[email protected]2bd93022010-07-17 00:58:441177 CreateMockRead(*resp),
1178 CreateMockRead(*body),
1179 CreateMockRead(*fbody),
[email protected]d4a77c12014-05-15 20:45:211180 CreateMockRead(*resp2, 8),
[email protected]2bd93022010-07-17 00:58:441181 CreateMockRead(*body2),
1182 CreateMockRead(*fbody2),
[email protected]d4a77c12014-05-15 20:45:211183 CreateMockRead(*resp3, 13),
[email protected]2bd93022010-07-17 00:58:441184 CreateMockRead(*body3),
1185 CreateMockRead(*fbody3),
1186
[email protected]8ddf8322012-02-23 18:08:061187 MockRead(ASYNC, 0, 0), // EOF
[email protected]2bd93022010-07-17 00:58:441188 };
1189
[email protected]dd54bd82012-07-19 23:44:571190 OrderedSocketData data(reads, arraysize(reads),
1191 writes, arraysize(writes));
1192 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
[email protected]2bd93022010-07-17 00:58:441193
1194 BoundNetLog log;
1195 TransactionHelperResult out;
1196 {
[email protected]262eec82013-03-19 21:01:361197 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501198 BoundNetLog(), GetParam(), NULL);
[email protected]2d6728692011-03-12 01:39:551199 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571200 helper.AddData(&data);
[email protected]2d6728692011-03-12 01:39:551201 // We require placeholder data because three get requests are sent out, so
1202 // there needs to be three sets of SSL connection data.
[email protected]dd54bd82012-07-19 23:44:571203 helper.AddData(&data_placeholder);
1204 helper.AddData(&data_placeholder);
[email protected]bdebd1b2010-08-09 20:18:081205 scoped_ptr<HttpNetworkTransaction> trans1(
[email protected]90499482013-06-01 00:39:501206 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:081207 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:501208 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:081209 scoped_ptr<HttpNetworkTransaction> trans3(
[email protected]90499482013-06-01 00:39:501210 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]2bd93022010-07-17 00:58:441211
[email protected]49639fa2011-12-20 23:22:411212 TestCompletionCallback callback1;
1213 TestCompletionCallback callback2;
1214 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:441215
1216 HttpRequestInfo httpreq1 = CreateGetRequest();
1217 HttpRequestInfo httpreq2 = CreateGetRequest();
1218 HttpRequestInfo httpreq3 = CreateGetRequest();
1219
[email protected]49639fa2011-12-20 23:22:411220 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]2bd93022010-07-17 00:58:441221 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]513963e2013-06-15 01:53:041222 // Run transaction 1 through quickly to force a read of our SETTINGS
1223 // frame.
[email protected]2bd93022010-07-17 00:58:441224 out.rv = callback1.WaitForResult();
[email protected]bdebd1b2010-08-09 20:18:081225 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441226
[email protected]49639fa2011-12-20 23:22:411227 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]2bd93022010-07-17 00:58:441228 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]49639fa2011-12-20 23:22:411229 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]2bd93022010-07-17 00:58:441230 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1231 out.rv = callback2.WaitForResult();
1232 ASSERT_EQ(OK, out.rv);
[email protected]dd54bd82012-07-19 23:44:571233 EXPECT_EQ(7U, data.read_index()); // i.e. the third trans was queued
[email protected]2bd93022010-07-17 00:58:441234
1235 out.rv = callback3.WaitForResult();
1236 ASSERT_EQ(OK, out.rv);
1237
1238 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]bdebd1b2010-08-09 20:18:081239 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:501240 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]2bd93022010-07-17 00:58:441241 EXPECT_TRUE(response1->was_fetched_via_spdy);
1242 out.status_line = response1->headers->GetStatusLine();
1243 out.response_info = *response1;
1244 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1245 EXPECT_EQ(OK, out.rv);
1246 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1247 EXPECT_EQ("hello!hello!", out.response_data);
1248
1249 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1250 out.status_line = response2->headers->GetStatusLine();
1251 out.response_info = *response2;
1252 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1253 EXPECT_EQ(OK, out.rv);
1254 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1255 EXPECT_EQ("hello!hello!", out.response_data);
1256
1257 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1258 out.status_line = response3->headers->GetStatusLine();
1259 out.response_info = *response3;
1260 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1261 EXPECT_EQ(OK, out.rv);
1262 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1263 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]044dcc52010-09-17 15:44:261264
1265 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441266 }
1267 EXPECT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441268}
1269
1270// Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1271// a fourth transaction. The third and fourth transactions have
1272// different data ("hello!" vs "hello!hello!") and because of the
1273// user specified priority, we expect to see them inverted in
1274// the response from the server.
[email protected]513963e2013-06-15 01:53:041275TEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
[email protected]2bd93022010-07-17 00:58:441276 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:461277 scoped_ptr<SpdyFrame> req(
1278 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041279 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1280 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1281 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2bd93022010-07-17 00:58:441282
[email protected]cdf8f7e72013-05-23 10:56:461283 scoped_ptr<SpdyFrame> req2(
1284 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041285 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1286 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1287 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]2bd93022010-07-17 00:58:441288
[email protected]ff98d7f02012-03-22 21:44:191289 scoped_ptr<SpdyFrame> req4(
[email protected]cdf8f7e72013-05-23 10:56:461290 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, HIGHEST, true));
[email protected]513963e2013-06-15 01:53:041291 scoped_ptr<SpdyFrame> resp4(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
1292 scoped_ptr<SpdyFrame> fbody4(spdy_util_.ConstructSpdyBodyFrame(5, true));
[email protected]2bd93022010-07-17 00:58:441293
[email protected]cdf8f7e72013-05-23 10:56:461294 scoped_ptr<SpdyFrame> req3(
1295 spdy_util_.ConstructSpdyGet(NULL, 0, false, 7, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041296 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 7));
1297 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(7, false));
1298 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(7, true));
[email protected]2bd93022010-07-17 00:58:441299
[email protected]18b28ab2012-04-18 02:14:421300 SettingsMap settings;
[email protected]9dcec242013-01-10 23:24:281301 const uint32 max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:421302 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1303 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
[email protected]c10b20852013-05-15 21:29:201304 scoped_ptr<SpdyFrame> settings_frame(
1305 spdy_util_.ConstructSpdySettings(settings));
[email protected]d4a77c12014-05-15 20:45:211306 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]2bd93022010-07-17 00:58:441307
1308 MockWrite writes[] = { CreateMockWrite(*req),
[email protected]d4a77c12014-05-15 20:45:211309 CreateMockWrite(*settings_ack, 2),
[email protected]bdebd1b2010-08-09 20:18:081310 CreateMockWrite(*req2),
1311 CreateMockWrite(*req4),
1312 CreateMockWrite(*req3),
[email protected]2bd93022010-07-17 00:58:441313 };
1314 MockRead reads[] = {
[email protected]bdebd1b2010-08-09 20:18:081315 CreateMockRead(*settings_frame, 1),
[email protected]2bd93022010-07-17 00:58:441316 CreateMockRead(*resp),
1317 CreateMockRead(*body),
1318 CreateMockRead(*fbody),
[email protected]d4a77c12014-05-15 20:45:211319 CreateMockRead(*resp2, 8),
[email protected]2bd93022010-07-17 00:58:441320 CreateMockRead(*body2),
1321 CreateMockRead(*fbody2),
[email protected]d4a77c12014-05-15 20:45:211322 CreateMockRead(*resp4, 14),
[email protected]2bd93022010-07-17 00:58:441323 CreateMockRead(*fbody4),
[email protected]d4a77c12014-05-15 20:45:211324 CreateMockRead(*resp3, 17),
[email protected]2bd93022010-07-17 00:58:441325 CreateMockRead(*body3),
1326 CreateMockRead(*fbody3),
1327
[email protected]8ddf8322012-02-23 18:08:061328 MockRead(ASYNC, 0, 0), // EOF
[email protected]2bd93022010-07-17 00:58:441329 };
1330
[email protected]dd54bd82012-07-19 23:44:571331 OrderedSocketData data(reads, arraysize(reads),
1332 writes, arraysize(writes));
1333 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
[email protected]2bd93022010-07-17 00:58:441334
1335 BoundNetLog log;
1336 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361337 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1338 BoundNetLog(), GetParam(), NULL);
[email protected]bdebd1b2010-08-09 20:18:081339 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571340 helper.AddData(&data);
[email protected]bdebd1b2010-08-09 20:18:081341 // We require placeholder data because four get requests are sent out, so
1342 // there needs to be four sets of SSL connection data.
[email protected]dd54bd82012-07-19 23:44:571343 helper.AddData(&data_placeholder);
1344 helper.AddData(&data_placeholder);
1345 helper.AddData(&data_placeholder);
[email protected]bdebd1b2010-08-09 20:18:081346 scoped_ptr<HttpNetworkTransaction> trans1(
[email protected]90499482013-06-01 00:39:501347 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:081348 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:501349 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:081350 scoped_ptr<HttpNetworkTransaction> trans3(
[email protected]90499482013-06-01 00:39:501351 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:081352 scoped_ptr<HttpNetworkTransaction> trans4(
[email protected]90499482013-06-01 00:39:501353 new HttpNetworkTransaction(HIGHEST, helper.session().get()));
[email protected]2bd93022010-07-17 00:58:441354
[email protected]49639fa2011-12-20 23:22:411355 TestCompletionCallback callback1;
1356 TestCompletionCallback callback2;
1357 TestCompletionCallback callback3;
1358 TestCompletionCallback callback4;
[email protected]2bd93022010-07-17 00:58:441359
[email protected]bdebd1b2010-08-09 20:18:081360 HttpRequestInfo httpreq1 = CreateGetRequest();
1361 HttpRequestInfo httpreq2 = CreateGetRequest();
1362 HttpRequestInfo httpreq3 = CreateGetRequest();
1363 HttpRequestInfo httpreq4 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:441364
[email protected]49639fa2011-12-20 23:22:411365 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081366 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]e0935cc2012-03-24 14:12:481367 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]bdebd1b2010-08-09 20:18:081368 out.rv = callback1.WaitForResult();
1369 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441370
[email protected]49639fa2011-12-20 23:22:411371 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081372 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:411373 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081374 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]49639fa2011-12-20 23:22:411375 out.rv = trans4->Start(&httpreq4, callback4.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081376 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]2bd93022010-07-17 00:58:441377
[email protected]bdebd1b2010-08-09 20:18:081378 out.rv = callback2.WaitForResult();
1379 ASSERT_EQ(OK, out.rv);
[email protected]dd54bd82012-07-19 23:44:571380 EXPECT_EQ(data.read_index(), 7U); // i.e. the third & fourth trans queued
[email protected]2bd93022010-07-17 00:58:441381
[email protected]bdebd1b2010-08-09 20:18:081382 out.rv = callback3.WaitForResult();
1383 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441384
[email protected]bdebd1b2010-08-09 20:18:081385 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]90499482013-06-01 00:39:501386 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]bdebd1b2010-08-09 20:18:081387 EXPECT_TRUE(response1->was_fetched_via_spdy);
1388 out.status_line = response1->headers->GetStatusLine();
1389 out.response_info = *response1;
1390 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1391 EXPECT_EQ(OK, out.rv);
1392 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1393 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441394
[email protected]bdebd1b2010-08-09 20:18:081395 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1396 out.status_line = response2->headers->GetStatusLine();
1397 out.response_info = *response2;
1398 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1399 EXPECT_EQ(OK, out.rv);
1400 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1401 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441402
[email protected]bdebd1b2010-08-09 20:18:081403 // notice: response3 gets two hellos, response4 gets one
1404 // hello, so we know dequeuing priority was respected.
1405 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1406 out.status_line = response3->headers->GetStatusLine();
1407 out.response_info = *response3;
1408 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1409 EXPECT_EQ(OK, out.rv);
1410 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1411 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441412
[email protected]bdebd1b2010-08-09 20:18:081413 out.rv = callback4.WaitForResult();
1414 EXPECT_EQ(OK, out.rv);
1415 const HttpResponseInfo* response4 = trans4->GetResponseInfo();
1416 out.status_line = response4->headers->GetStatusLine();
1417 out.response_info = *response4;
1418 out.rv = ReadTransaction(trans4.get(), &out.response_data);
1419 EXPECT_EQ(OK, out.rv);
1420 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1421 EXPECT_EQ("hello!", out.response_data);
1422 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441423 EXPECT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441424}
1425
1426// Similar to ThreeGetsMaxConcurrrent above, however, this test
1427// deletes a session in the middle of the transaction to insure
1428// that we properly remove pendingcreatestream objects from
1429// the spdy_session
[email protected]513963e2013-06-15 01:53:041430TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
[email protected]2bd93022010-07-17 00:58:441431 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:461432 scoped_ptr<SpdyFrame> req(
1433 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041434 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1435 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1436 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]2bd93022010-07-17 00:58:441437
[email protected]cdf8f7e72013-05-23 10:56:461438 scoped_ptr<SpdyFrame> req2(
1439 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041440 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1441 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1442 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]2bd93022010-07-17 00:58:441443
[email protected]18b28ab2012-04-18 02:14:421444 SettingsMap settings;
[email protected]9dcec242013-01-10 23:24:281445 const uint32 max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:421446 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1447 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
[email protected]c10b20852013-05-15 21:29:201448 scoped_ptr<SpdyFrame> settings_frame(
1449 spdy_util_.ConstructSpdySettings(settings));
[email protected]d4a77c12014-05-15 20:45:211450 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]2bd93022010-07-17 00:58:441451
[email protected]d4a77c12014-05-15 20:45:211452 MockWrite writes[] = {
1453 CreateMockWrite(*req),
1454 CreateMockWrite(*settings_ack, 2),
[email protected]bdebd1b2010-08-09 20:18:081455 CreateMockWrite(*req2),
[email protected]2bd93022010-07-17 00:58:441456 };
1457 MockRead reads[] = {
[email protected]bdebd1b2010-08-09 20:18:081458 CreateMockRead(*settings_frame, 1),
[email protected]2bd93022010-07-17 00:58:441459 CreateMockRead(*resp),
1460 CreateMockRead(*body),
1461 CreateMockRead(*fbody),
[email protected]d4a77c12014-05-15 20:45:211462 CreateMockRead(*resp2, 8),
[email protected]2bd93022010-07-17 00:58:441463 CreateMockRead(*body2),
1464 CreateMockRead(*fbody2),
[email protected]8ddf8322012-02-23 18:08:061465 MockRead(ASYNC, 0, 0), // EOF
[email protected]2bd93022010-07-17 00:58:441466 };
1467
[email protected]dd54bd82012-07-19 23:44:571468 OrderedSocketData data(reads, arraysize(reads),
1469 writes, arraysize(writes));
1470 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
[email protected]2bd93022010-07-17 00:58:441471
1472 BoundNetLog log;
1473 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361474 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1475 BoundNetLog(), GetParam(), NULL);
[email protected]bdebd1b2010-08-09 20:18:081476 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571477 helper.AddData(&data);
[email protected]bdebd1b2010-08-09 20:18:081478 // We require placeholder data because three get requests are sent out, so
1479 // there needs to be three sets of SSL connection data.
[email protected]dd54bd82012-07-19 23:44:571480 helper.AddData(&data_placeholder);
1481 helper.AddData(&data_placeholder);
[email protected]bdebd1b2010-08-09 20:18:081482 scoped_ptr<HttpNetworkTransaction> trans1(
[email protected]90499482013-06-01 00:39:501483 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:081484 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:501485 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]bdebd1b2010-08-09 20:18:081486 scoped_ptr<HttpNetworkTransaction> trans3(
[email protected]90499482013-06-01 00:39:501487 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]2bd93022010-07-17 00:58:441488
[email protected]49639fa2011-12-20 23:22:411489 TestCompletionCallback callback1;
1490 TestCompletionCallback callback2;
1491 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:441492
[email protected]bdebd1b2010-08-09 20:18:081493 HttpRequestInfo httpreq1 = CreateGetRequest();
1494 HttpRequestInfo httpreq2 = CreateGetRequest();
1495 HttpRequestInfo httpreq3 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:441496
[email protected]49639fa2011-12-20 23:22:411497 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081498 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]e0935cc2012-03-24 14:12:481499 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]bdebd1b2010-08-09 20:18:081500 out.rv = callback1.WaitForResult();
1501 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441502
[email protected]49639fa2011-12-20 23:22:411503 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081504 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]49639fa2011-12-20 23:22:411505 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]bdebd1b2010-08-09 20:18:081506 delete trans3.release();
1507 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1508 out.rv = callback2.WaitForResult();
1509 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441510
[email protected]dd54bd82012-07-19 23:44:571511 EXPECT_EQ(8U, data.read_index());
[email protected]2bd93022010-07-17 00:58:441512
[email protected]bdebd1b2010-08-09 20:18:081513 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1514 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:501515 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]bdebd1b2010-08-09 20:18:081516 EXPECT_TRUE(response1->was_fetched_via_spdy);
1517 out.status_line = response1->headers->GetStatusLine();
1518 out.response_info = *response1;
1519 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1520 EXPECT_EQ(OK, out.rv);
1521 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1522 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441523
[email protected]bdebd1b2010-08-09 20:18:081524 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1525 ASSERT_TRUE(response2 != NULL);
1526 out.status_line = response2->headers->GetStatusLine();
1527 out.response_info = *response2;
1528 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1529 EXPECT_EQ(OK, out.rv);
1530 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1531 EXPECT_EQ("hello!hello!", out.response_data);
1532 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441533 EXPECT_EQ(OK, out.rv);
[email protected]044dcc52010-09-17 15:44:261534}
[email protected]2bd93022010-07-17 00:58:441535
[email protected]448d4ca52012-03-04 04:12:231536namespace {
1537
[email protected]044dcc52010-09-17 15:44:261538// The KillerCallback will delete the transaction on error as part of the
1539// callback.
[email protected]49639fa2011-12-20 23:22:411540class KillerCallback : public TestCompletionCallbackBase {
[email protected]044dcc52010-09-17 15:44:261541 public:
1542 explicit KillerCallback(HttpNetworkTransaction* transaction)
[email protected]49639fa2011-12-20 23:22:411543 : transaction_(transaction),
[email protected]aa249b52013-04-30 01:04:321544 callback_(base::Bind(&KillerCallback::OnComplete,
1545 base::Unretained(this))) {
[email protected]044dcc52010-09-17 15:44:261546 }
1547
dchengb03027d2014-10-21 12:00:201548 ~KillerCallback() override {}
[email protected]49639fa2011-12-20 23:22:411549
1550 const CompletionCallback& callback() const { return callback_; }
1551
[email protected]044dcc52010-09-17 15:44:261552 private:
[email protected]49639fa2011-12-20 23:22:411553 void OnComplete(int result) {
1554 if (result < 0)
1555 delete transaction_;
1556
1557 SetResult(result);
1558 }
1559
[email protected]044dcc52010-09-17 15:44:261560 HttpNetworkTransaction* transaction_;
[email protected]49639fa2011-12-20 23:22:411561 CompletionCallback callback_;
[email protected]044dcc52010-09-17 15:44:261562};
1563
[email protected]448d4ca52012-03-04 04:12:231564} // namespace
1565
[email protected]044dcc52010-09-17 15:44:261566// Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1567// closes the socket while we have a pending transaction waiting for
1568// a pending stream creation. http://crbug.com/52901
[email protected]513963e2013-06-15 01:53:041569TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
[email protected]044dcc52010-09-17 15:44:261570 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:461571 scoped_ptr<SpdyFrame> req(
1572 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041573 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1574 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1575 scoped_ptr<SpdyFrame> fin_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]044dcc52010-09-17 15:44:261576
[email protected]cdf8f7e72013-05-23 10:56:461577 scoped_ptr<SpdyFrame> req2(
1578 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]513963e2013-06-15 01:53:041579 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
[email protected]044dcc52010-09-17 15:44:261580
[email protected]18b28ab2012-04-18 02:14:421581 SettingsMap settings;
[email protected]9dcec242013-01-10 23:24:281582 const uint32 max_concurrent_streams = 1;
[email protected]18b28ab2012-04-18 02:14:421583 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1584 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
[email protected]c10b20852013-05-15 21:29:201585 scoped_ptr<SpdyFrame> settings_frame(
1586 spdy_util_.ConstructSpdySettings(settings));
[email protected]d4a77c12014-05-15 20:45:211587 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
[email protected]044dcc52010-09-17 15:44:261588
[email protected]d4a77c12014-05-15 20:45:211589 MockWrite writes[] = {
1590 CreateMockWrite(*req),
1591 CreateMockWrite(*settings_ack, 2),
[email protected]044dcc52010-09-17 15:44:261592 CreateMockWrite(*req2),
1593 };
1594 MockRead reads[] = {
1595 CreateMockRead(*settings_frame, 1),
1596 CreateMockRead(*resp),
1597 CreateMockRead(*body),
1598 CreateMockRead(*fin_body),
[email protected]d4a77c12014-05-15 20:45:211599 CreateMockRead(*resp2, 8),
[email protected]8ddf8322012-02-23 18:08:061600 MockRead(ASYNC, ERR_CONNECTION_RESET, 0), // Abort!
[email protected]044dcc52010-09-17 15:44:261601 };
1602
[email protected]dd54bd82012-07-19 23:44:571603 OrderedSocketData data(reads, arraysize(reads),
1604 writes, arraysize(writes));
1605 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
[email protected]044dcc52010-09-17 15:44:261606
1607 BoundNetLog log;
1608 TransactionHelperResult out;
[email protected]262eec82013-03-19 21:01:361609 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1610 BoundNetLog(), GetParam(), NULL);
[email protected]044dcc52010-09-17 15:44:261611 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:571612 helper.AddData(&data);
[email protected]044dcc52010-09-17 15:44:261613 // We require placeholder data because three get requests are sent out, so
1614 // there needs to be three sets of SSL connection data.
[email protected]dd54bd82012-07-19 23:44:571615 helper.AddData(&data_placeholder);
1616 helper.AddData(&data_placeholder);
[email protected]90499482013-06-01 00:39:501617 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session().get());
1618 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session().get());
[email protected]262eec82013-03-19 21:01:361619 HttpNetworkTransaction* trans3(
[email protected]90499482013-06-01 00:39:501620 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]044dcc52010-09-17 15:44:261621
[email protected]49639fa2011-12-20 23:22:411622 TestCompletionCallback callback1;
1623 TestCompletionCallback callback2;
[email protected]044dcc52010-09-17 15:44:261624 KillerCallback callback3(trans3);
1625
1626 HttpRequestInfo httpreq1 = CreateGetRequest();
1627 HttpRequestInfo httpreq2 = CreateGetRequest();
1628 HttpRequestInfo httpreq3 = CreateGetRequest();
1629
[email protected]49639fa2011-12-20 23:22:411630 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
[email protected]044dcc52010-09-17 15:44:261631 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]e0935cc2012-03-24 14:12:481632 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
[email protected]044dcc52010-09-17 15:44:261633 out.rv = callback1.WaitForResult();
1634 ASSERT_EQ(OK, out.rv);
1635
[email protected]49639fa2011-12-20 23:22:411636 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
[email protected]044dcc52010-09-17 15:44:261637 ASSERT_EQ(out.rv, ERR_IO_PENDING);
[email protected]49639fa2011-12-20 23:22:411638 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
[email protected]044dcc52010-09-17 15:44:261639 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1640 out.rv = callback3.WaitForResult();
1641 ASSERT_EQ(ERR_ABORTED, out.rv);
1642
[email protected]dd54bd82012-07-19 23:44:571643 EXPECT_EQ(6U, data.read_index());
[email protected]044dcc52010-09-17 15:44:261644
1645 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
1646 ASSERT_TRUE(response1 != NULL);
[email protected]90499482013-06-01 00:39:501647 EXPECT_TRUE(response1->headers.get() != NULL);
[email protected]044dcc52010-09-17 15:44:261648 EXPECT_TRUE(response1->was_fetched_via_spdy);
1649 out.status_line = response1->headers->GetStatusLine();
1650 out.response_info = *response1;
1651 out.rv = ReadTransaction(&trans1, &out.response_data);
1652 EXPECT_EQ(OK, out.rv);
1653
1654 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
1655 ASSERT_TRUE(response2 != NULL);
1656 out.status_line = response2->headers->GetStatusLine();
1657 out.response_info = *response2;
1658 out.rv = ReadTransaction(&trans2, &out.response_data);
1659 EXPECT_EQ(ERR_CONNECTION_RESET, out.rv);
1660
1661 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441662}
1663
[email protected]d8ef27b2010-08-06 17:34:391664// Test that a simple PUT request works.
[email protected]513963e2013-06-15 01:53:041665TEST_P(SpdyNetworkTransactionTest, Put) {
[email protected]d8ef27b2010-08-06 17:34:391666 // Setup the request
1667 HttpRequestInfo request;
1668 request.method = "PUT";
1669 request.url = GURL("http://www.google.com/");
1670
[email protected]513963e2013-06-15 01:53:041671 scoped_ptr<SpdyHeaderBlock> put_headers(
1672 spdy_util_.ConstructPutHeaderBlock("http://www.google.com", 0));
[email protected]745aa9c2014-06-27 02:21:291673 scoped_ptr<SpdyFrame> req(
1674 spdy_util_.ConstructSpdySyn(1, *put_headers, LOWEST, false, true));
[email protected]d8ef27b2010-08-06 17:34:391675 MockWrite writes[] = {
[email protected]cdf8f7e72013-05-23 10:56:461676 CreateMockWrite(*req),
[email protected]d8ef27b2010-08-06 17:34:391677 };
1678
[email protected]745aa9c2014-06-27 02:21:291679 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:041680 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d8ef27b2010-08-06 17:34:391681 MockRead reads[] = {
1682 CreateMockRead(*resp),
1683 CreateMockRead(*body),
[email protected]8ddf8322012-02-23 18:08:061684 MockRead(ASYNC, 0, 0) // EOF
[email protected]d8ef27b2010-08-06 17:34:391685 };
1686
[email protected]dd54bd82012-07-19 23:44:571687 DelayedSocketData data(1, reads, arraysize(reads),
1688 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361689 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501690 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:571691 helper.RunToCompletion(&data);
[email protected]d8ef27b2010-08-06 17:34:391692 TransactionHelperResult out = helper.output();
1693
1694 EXPECT_EQ(OK, out.rv);
1695 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1696}
1697
1698// Test that a simple HEAD request works.
[email protected]513963e2013-06-15 01:53:041699TEST_P(SpdyNetworkTransactionTest, Head) {
[email protected]d8ef27b2010-08-06 17:34:391700 // Setup the request
1701 HttpRequestInfo request;
1702 request.method = "HEAD";
1703 request.url = GURL("http://www.google.com/");
1704
[email protected]513963e2013-06-15 01:53:041705 scoped_ptr<SpdyHeaderBlock> head_headers(
1706 spdy_util_.ConstructHeadHeaderBlock("http://www.google.com", 0));
[email protected]745aa9c2014-06-27 02:21:291707 scoped_ptr<SpdyFrame> req(
1708 spdy_util_.ConstructSpdySyn(1, *head_headers, LOWEST, false, true));
[email protected]d8ef27b2010-08-06 17:34:391709 MockWrite writes[] = {
[email protected]cdf8f7e72013-05-23 10:56:461710 CreateMockWrite(*req),
[email protected]d8ef27b2010-08-06 17:34:391711 };
1712
[email protected]745aa9c2014-06-27 02:21:291713 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:041714 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d8ef27b2010-08-06 17:34:391715 MockRead reads[] = {
1716 CreateMockRead(*resp),
1717 CreateMockRead(*body),
[email protected]8ddf8322012-02-23 18:08:061718 MockRead(ASYNC, 0, 0) // EOF
[email protected]d8ef27b2010-08-06 17:34:391719 };
1720
[email protected]dd54bd82012-07-19 23:44:571721 DelayedSocketData data(1, reads, arraysize(reads),
1722 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361723 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501724 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:571725 helper.RunToCompletion(&data);
[email protected]d8ef27b2010-08-06 17:34:391726 TransactionHelperResult out = helper.output();
1727
1728 EXPECT_EQ(OK, out.rv);
1729 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1730}
1731
[email protected]72552f02009-10-28 15:25:011732// Test that a simple POST works.
[email protected]513963e2013-06-15 01:53:041733TEST_P(SpdyNetworkTransactionTest, Post) {
[email protected]cbdd73162013-03-18 23:27:331734 scoped_ptr<SpdyFrame> req(
[email protected]513963e2013-06-15 01:53:041735 spdy_util_.ConstructSpdyPost(
1736 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
1737 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]ff57bb82009-11-12 06:52:141738 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:131739 CreateMockWrite(*req),
1740 CreateMockWrite(*body), // POST upload frame
[email protected]ff57bb82009-11-12 06:52:141741 };
[email protected]72552f02009-10-28 15:25:011742
[email protected]513963e2013-06-15 01:53:041743 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]ff57bb82009-11-12 06:52:141744 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:131745 CreateMockRead(*resp),
1746 CreateMockRead(*body),
[email protected]8ddf8322012-02-23 18:08:061747 MockRead(ASYNC, 0, 0) // EOF
[email protected]aea80602009-09-18 00:55:081748 };
1749
[email protected]dd54bd82012-07-19 23:44:571750 DelayedSocketData data(2, reads, arraysize(reads),
1751 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361752 NormalSpdyTransactionHelper helper(CreatePostRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501753 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:571754 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:471755 TransactionHelperResult out = helper.output();
[email protected]aea80602009-09-18 00:55:081756 EXPECT_EQ(OK, out.rv);
1757 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1758 EXPECT_EQ("hello!", out.response_data);
1759}
1760
[email protected]69e6b4a2012-10-18 08:03:011761// Test that a POST with a file works.
[email protected]513963e2013-06-15 01:53:041762TEST_P(SpdyNetworkTransactionTest, FilePost) {
[email protected]cbdd73162013-03-18 23:27:331763 scoped_ptr<SpdyFrame> req(
[email protected]513963e2013-06-15 01:53:041764 spdy_util_.ConstructSpdyPost(
1765 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
1766 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]69e6b4a2012-10-18 08:03:011767 MockWrite writes[] = {
1768 CreateMockWrite(*req),
1769 CreateMockWrite(*body), // POST upload frame
1770 };
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[] = {
1774 CreateMockRead(*resp),
1775 CreateMockRead(*body),
1776 MockRead(ASYNC, 0, 0) // EOF
1777 };
1778
1779 DelayedSocketData data(2, reads, arraysize(reads),
1780 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:361781 NormalSpdyTransactionHelper helper(CreateFilePostRequest(), 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]999dd8c2013-11-12 06:45:541790// Test that a POST with a unreadable file fails.
1791TEST_P(SpdyNetworkTransactionTest, UnreadableFilePost) {
1792 MockWrite writes[] = {
1793 MockWrite(ASYNC, 0, 0) // EOF
1794 };
1795 MockRead reads[] = {
1796 MockRead(ASYNC, 0, 0) // EOF
1797 };
1798
1799 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
1800 NormalSpdyTransactionHelper helper(CreateUnreadableFilePostRequest(),
1801 DEFAULT_PRIORITY,
1802 BoundNetLog(), GetParam(), NULL);
1803 helper.RunPreTestSetup();
1804 helper.AddData(&data);
1805 helper.RunDefaultTest();
1806
1807 base::RunLoop().RunUntilIdle();
1808 helper.VerifyDataNotConsumed();
1809 EXPECT_EQ(ERR_ACCESS_DENIED, helper.output().rv);
1810}
1811
[email protected]69e6b4a2012-10-18 08:03:011812// Test that a complex POST works.
[email protected]513963e2013-06-15 01:53:041813TEST_P(SpdyNetworkTransactionTest, ComplexPost) {
[email protected]cbdd73162013-03-18 23:27:331814 scoped_ptr<SpdyFrame> req(
[email protected]513963e2013-06-15 01:53:041815 spdy_util_.ConstructSpdyPost(
1816 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
1817 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]69e6b4a2012-10-18 08:03:011818 MockWrite writes[] = {
1819 CreateMockWrite(*req),
1820 CreateMockWrite(*body), // POST upload frame
1821 };
1822
[email protected]513963e2013-06-15 01:53:041823 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]69e6b4a2012-10-18 08:03:011824 MockRead reads[] = {
1825 CreateMockRead(*resp),
1826 CreateMockRead(*body),
1827 MockRead(ASYNC, 0, 0) // EOF
1828 };
1829
1830 DelayedSocketData data(2, reads, arraysize(reads),
1831 writes, arraysize(writes));
[email protected]69e6b4a2012-10-18 08:03:011832 NormalSpdyTransactionHelper helper(CreateComplexPostRequest(),
[email protected]262eec82013-03-19 21:01:361833 DEFAULT_PRIORITY,
[email protected]69e6b4a2012-10-18 08:03:011834 BoundNetLog(), GetParam(), NULL);
1835 helper.RunToCompletion(&data);
1836 TransactionHelperResult out = helper.output();
1837 EXPECT_EQ(OK, out.rv);
1838 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1839 EXPECT_EQ("hello!", out.response_data);
1840}
1841
[email protected]0c9bf872011-03-04 17:53:221842// Test that a chunked POST works.
[email protected]513963e2013-06-15 01:53:041843TEST_P(SpdyNetworkTransactionTest, ChunkedPost) {
[email protected]513963e2013-06-15 01:53:041844 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1845 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]0c9bf872011-03-04 17:53:221846 MockWrite writes[] = {
1847 CreateMockWrite(*req),
[email protected]34b345f92013-02-22 03:27:261848 CreateMockWrite(*body),
[email protected]0c9bf872011-03-04 17:53:221849 };
1850
[email protected]513963e2013-06-15 01:53:041851 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]0c9bf872011-03-04 17:53:221852 MockRead reads[] = {
1853 CreateMockRead(*resp),
[email protected]34b345f92013-02-22 03:27:261854 CreateMockRead(*body),
[email protected]8ddf8322012-02-23 18:08:061855 MockRead(ASYNC, 0, 0) // EOF
[email protected]0c9bf872011-03-04 17:53:221856 };
1857
[email protected]dd54bd82012-07-19 23:44:571858 DelayedSocketData data(2, reads, arraysize(reads),
1859 writes, arraysize(writes));
[email protected]0c9bf872011-03-04 17:53:221860 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
[email protected]262eec82013-03-19 21:01:361861 DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501862 BoundNetLog(), GetParam(), NULL);
[email protected]34b345f92013-02-22 03:27:261863
1864 // These chunks get merged into a single frame when being sent.
1865 const int kFirstChunkSize = kUploadDataSize/2;
mmenkecbc2b712014-10-09 20:29:071866 upload_chunked_data_stream()->AppendData(kUploadData, kFirstChunkSize, false);
1867 upload_chunked_data_stream()->AppendData(
[email protected]34b345f92013-02-22 03:27:261868 kUploadData + kFirstChunkSize, kUploadDataSize - kFirstChunkSize, true);
1869
[email protected]dd54bd82012-07-19 23:44:571870 helper.RunToCompletion(&data);
[email protected]0c9bf872011-03-04 17:53:221871 TransactionHelperResult out = helper.output();
1872 EXPECT_EQ(OK, out.rv);
1873 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
[email protected]34b345f92013-02-22 03:27:261874 EXPECT_EQ(kUploadData, out.response_data);
1875}
1876
1877// Test that a chunked POST works with chunks appended after transaction starts.
[email protected]513963e2013-06-15 01:53:041878TEST_P(SpdyNetworkTransactionTest, DelayedChunkedPost) {
[email protected]513963e2013-06-15 01:53:041879 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1880 scoped_ptr<SpdyFrame> chunk1(spdy_util_.ConstructSpdyBodyFrame(1, false));
1881 scoped_ptr<SpdyFrame> chunk2(spdy_util_.ConstructSpdyBodyFrame(1, false));
1882 scoped_ptr<SpdyFrame> chunk3(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]34b345f92013-02-22 03:27:261883 MockWrite writes[] = {
1884 CreateMockWrite(*req),
1885 CreateMockWrite(*chunk1),
1886 CreateMockWrite(*chunk2),
1887 CreateMockWrite(*chunk3),
1888 };
1889
[email protected]513963e2013-06-15 01:53:041890 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]34b345f92013-02-22 03:27:261891 MockRead reads[] = {
1892 CreateMockRead(*resp),
1893 CreateMockRead(*chunk1),
1894 CreateMockRead(*chunk2),
1895 CreateMockRead(*chunk3),
1896 MockRead(ASYNC, 0, 0) // EOF
1897 };
1898
1899 DelayedSocketData data(4, reads, arraysize(reads),
1900 writes, arraysize(writes));
1901 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
[email protected]262eec82013-03-19 21:01:361902 DEFAULT_PRIORITY,
[email protected]34b345f92013-02-22 03:27:261903 BoundNetLog(), GetParam(), NULL);
1904
mmenkecbc2b712014-10-09 20:29:071905 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
[email protected]34b345f92013-02-22 03:27:261906
1907 helper.RunPreTestSetup();
1908 helper.AddData(&data);
1909 ASSERT_TRUE(helper.StartDefaultTest());
1910
[email protected]fc9d88472013-08-14 02:31:171911 base::RunLoop().RunUntilIdle();
mmenkecbc2b712014-10-09 20:29:071912 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
[email protected]fc9d88472013-08-14 02:31:171913 base::RunLoop().RunUntilIdle();
mmenkecbc2b712014-10-09 20:29:071914 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true);
[email protected]34b345f92013-02-22 03:27:261915
1916 helper.FinishDefaultTest();
1917 helper.VerifyDataConsumed();
1918
1919 std::string expected_response;
1920 expected_response += kUploadData;
1921 expected_response += kUploadData;
1922 expected_response += kUploadData;
1923
1924 TransactionHelperResult out = helper.output();
1925 EXPECT_EQ(OK, out.rv);
1926 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1927 EXPECT_EQ(expected_response, out.response_data);
[email protected]0c9bf872011-03-04 17:53:221928}
1929
[email protected]a33cad2b62010-07-30 22:24:391930// Test that a POST without any post data works.
[email protected]513963e2013-06-15 01:53:041931TEST_P(SpdyNetworkTransactionTest, NullPost) {
[email protected]d2c1a97b2014-03-03 19:25:091932 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]a33cad2b62010-07-30 22:24:391933 // Setup the request
1934 HttpRequestInfo request;
1935 request.method = "POST";
[email protected]cbdd73162013-03-18 23:27:331936 request.url = GURL(kRequestUrl);
[email protected]a33cad2b62010-07-30 22:24:391937 // Create an empty UploadData.
[email protected]329b68b2012-11-14 17:54:271938 request.upload_data_stream = NULL;
[email protected]a33cad2b62010-07-30 22:24:391939
[email protected]329b68b2012-11-14 17:54:271940 // When request.upload_data_stream is NULL for post, content-length is
[email protected]a33cad2b62010-07-30 22:24:391941 // expected to be 0.
[email protected]745aa9c2014-06-27 02:21:291942 scoped_ptr<SpdyHeaderBlock> req_block(
1943 spdy_util_.ConstructPostHeaderBlock(kRequestUrl, 0));
1944 scoped_ptr<SpdyFrame> req(
1945 spdy_util_.ConstructSpdySyn(1, *req_block, LOWEST, false, true));
[email protected]d2c1a97b2014-03-03 19:25:091946
[email protected]a33cad2b62010-07-30 22:24:391947 MockWrite writes[] = {
1948 CreateMockWrite(*req),
1949 };
1950
[email protected]513963e2013-06-15 01:53:041951 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1952 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]a33cad2b62010-07-30 22:24:391953 MockRead reads[] = {
1954 CreateMockRead(*resp),
1955 CreateMockRead(*body),
[email protected]8ddf8322012-02-23 18:08:061956 MockRead(ASYNC, 0, 0) // EOF
[email protected]a33cad2b62010-07-30 22:24:391957 };
1958
[email protected]dd54bd82012-07-19 23:44:571959 DelayedSocketData data(1, reads, arraysize(reads),
1960 writes, arraysize(writes));
[email protected]a33cad2b62010-07-30 22:24:391961
[email protected]262eec82013-03-19 21:01:361962 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:501963 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:571964 helper.RunToCompletion(&data);
[email protected]a33cad2b62010-07-30 22:24:391965 TransactionHelperResult out = helper.output();
1966 EXPECT_EQ(OK, out.rv);
1967 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1968 EXPECT_EQ("hello!", out.response_data);
1969}
1970
[email protected]edd3b0a52009-11-24 18:56:361971// Test that a simple POST works.
[email protected]513963e2013-06-15 01:53:041972TEST_P(SpdyNetworkTransactionTest, EmptyPost) {
[email protected]d2c1a97b2014-03-03 19:25:091973 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]329b68b2012-11-14 17:54:271974 // Create an empty UploadDataStream.
[email protected]b2d26cfd2012-12-11 10:36:061975 ScopedVector<UploadElementReader> element_readers;
mmenkecbc2b712014-10-09 20:29:071976 ElementsUploadDataStream stream(element_readers.Pass(), 0);
[email protected]329b68b2012-11-14 17:54:271977
[email protected]edd3b0a52009-11-24 18:56:361978 // Setup the request
1979 HttpRequestInfo request;
1980 request.method = "POST";
[email protected]513963e2013-06-15 01:53:041981 request.url = GURL(kRequestUrl);
[email protected]329b68b2012-11-14 17:54:271982 request.upload_data_stream = &stream;
[email protected]edd3b0a52009-11-24 18:56:361983
[email protected]ad91dc52012-09-01 03:46:061984 const uint64 kContentLength = 0;
[email protected]d2c1a97b2014-03-03 19:25:091985
[email protected]745aa9c2014-06-27 02:21:291986 scoped_ptr<SpdyHeaderBlock> req_block(
1987 spdy_util_.ConstructPostHeaderBlock(kRequestUrl, kContentLength));
1988 scoped_ptr<SpdyFrame> req(
1989 spdy_util_.ConstructSpdySyn(1, *req_block, LOWEST, false, true));
[email protected]d2c1a97b2014-03-03 19:25:091990
[email protected]edd3b0a52009-11-24 18:56:361991 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:131992 CreateMockWrite(*req),
[email protected]edd3b0a52009-11-24 18:56:361993 };
1994
[email protected]513963e2013-06-15 01:53:041995 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1996 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]edd3b0a52009-11-24 18:56:361997 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:131998 CreateMockRead(*resp),
1999 CreateMockRead(*body),
[email protected]8ddf8322012-02-23 18:08:062000 MockRead(ASYNC, 0, 0) // EOF
[email protected]edd3b0a52009-11-24 18:56:362001 };
2002
[email protected]bf3eb002012-11-15 05:50:112003 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
[email protected]bf2491a92009-11-29 16:39:482004
[email protected]262eec82013-03-19 21:01:362005 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
2006 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:572007 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:472008 TransactionHelperResult out = helper.output();
[email protected]edd3b0a52009-11-24 18:56:362009 EXPECT_EQ(OK, out.rv);
2010 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
2011 EXPECT_EQ("hello!", out.response_data);
2012}
2013
[email protected]35c3fc732014-02-15 00:16:072014// While we're doing a post, the server sends the reply before upload completes.
2015TEST_P(SpdyNetworkTransactionTest, ResponseBeforePostCompletes) {
2016 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
2017 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2018 MockWrite writes[] = {
2019 CreateMockWrite(*req, 0),
2020 CreateMockWrite(*body, 3),
2021 };
2022 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
[email protected]a5566f9702010-05-05 22:25:432023 MockRead reads[] = {
[email protected]35c3fc732014-02-15 00:16:072024 CreateMockRead(*resp, 1),
2025 CreateMockRead(*body, 2),
[email protected]099bc7e2013-07-18 04:19:162026 MockRead(ASYNC, 0, 4) // EOF
[email protected]a5566f9702010-05-05 22:25:432027 };
2028
[email protected]35c3fc732014-02-15 00:16:072029 // Write the request headers, and read the complete response
2030 // while still waiting for chunked request data.
[email protected]c92f4b4542012-07-26 23:53:212031 DeterministicSocketData data(reads, arraysize(reads),
2032 writes, arraysize(writes));
[email protected]35c3fc732014-02-15 00:16:072033 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
2034 DEFAULT_PRIORITY,
[email protected]c92f4b4542012-07-26 23:53:212035 BoundNetLog(), GetParam(), NULL);
2036 helper.SetDeterministic();
2037 helper.RunPreTestSetup();
2038 helper.AddDeterministicData(&data);
[email protected]c92f4b4542012-07-26 23:53:212039
[email protected]35c3fc732014-02-15 00:16:072040 ASSERT_TRUE(helper.StartDefaultTest());
[email protected]c92f4b4542012-07-26 23:53:212041
[email protected]35c3fc732014-02-15 00:16:072042 // Process the request headers, SYN_REPLY, and response body.
2043 // The request body is still in flight.
2044 data.RunFor(3);
2045
2046 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
2047 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2048
2049 // Finish sending the request body.
mmenkecbc2b712014-10-09 20:29:072050 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true);
[email protected]35c3fc732014-02-15 00:16:072051 data.RunFor(2);
2052
2053 std::string response_body;
2054 EXPECT_EQ(OK, ReadTransaction(helper.trans(), &response_body));
2055 EXPECT_EQ(kUploadData, response_body);
2056 helper.VerifyDataConsumed();
[email protected]a5566f9702010-05-05 22:25:432057}
2058
[email protected]f9a26d72010-08-03 18:07:132059// The client upon cancellation tries to send a RST_STREAM frame. The mock
2060// socket causes the TCP write to return zero. This test checks that the client
2061// tries to queue up the RST_STREAM frame again.
[email protected]513963e2013-06-15 01:53:042062TEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
[email protected]cdf8f7e72013-05-23 10:56:462063 scoped_ptr<SpdyFrame> req(
2064 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]ff98d7f02012-03-22 21:44:192065 scoped_ptr<SpdyFrame> rst(
[email protected]c10b20852013-05-15 21:29:202066 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]f9a26d72010-08-03 18:07:132067 MockWrite writes[] = {
[email protected]8ddf8322012-02-23 18:08:062068 CreateMockWrite(*req.get(), 0, SYNCHRONOUS),
2069 MockWrite(SYNCHRONOUS, 0, 0, 2),
2070 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
[email protected]f9a26d72010-08-03 18:07:132071 };
2072
[email protected]513963e2013-06-15 01:53:042073 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]f9a26d72010-08-03 18:07:132074 MockRead reads[] = {
[email protected]8ddf8322012-02-23 18:08:062075 CreateMockRead(*resp.get(), 1, ASYNC),
2076 MockRead(ASYNC, 0, 0, 4) // EOF
[email protected]f9a26d72010-08-03 18:07:132077 };
2078
[email protected]dd54bd82012-07-19 23:44:572079 DeterministicSocketData data(reads, arraysize(reads),
2080 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362081 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502082 BoundNetLog(), GetParam(), NULL);
[email protected]3b7828432010-08-18 18:33:272083 helper.SetDeterministic();
[email protected]f9a26d72010-08-03 18:07:132084 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572085 helper.AddDeterministicData(&data);
[email protected]f9a26d72010-08-03 18:07:132086 HttpNetworkTransaction* trans = helper.trans();
2087
[email protected]49639fa2011-12-20 23:22:412088 TestCompletionCallback callback;
2089 int rv = trans->Start(
2090 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]f9a26d72010-08-03 18:07:132091 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3b7828432010-08-18 18:33:272092
[email protected]dd54bd82012-07-19 23:44:572093 data.SetStop(2);
2094 data.Run();
[email protected]f9a26d72010-08-03 18:07:132095 helper.ResetTrans();
[email protected]dd54bd82012-07-19 23:44:572096 data.SetStop(20);
2097 data.Run();
[email protected]3b7828432010-08-18 18:33:272098
[email protected]f9a26d72010-08-03 18:07:132099 helper.VerifyDataConsumed();
2100}
2101
[email protected]93300672009-10-24 13:22:512102// Test that the transaction doesn't crash when we don't have a reply.
[email protected]513963e2013-06-15 01:53:042103TEST_P(SpdyNetworkTransactionTest, ResponseWithoutSynReply) {
[email protected]513963e2013-06-15 01:53:042104 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]ff57bb82009-11-12 06:52:142105 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:132106 CreateMockRead(*body),
[email protected]8ddf8322012-02-23 18:08:062107 MockRead(ASYNC, 0, 0) // EOF
[email protected]93300672009-10-24 13:22:512108 };
2109
[email protected]dd54bd82012-07-19 23:44:572110 DelayedSocketData data(1, reads, arraysize(reads), NULL, 0);
[email protected]262eec82013-03-19 21:01:362111 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502112 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:572113 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:472114 TransactionHelperResult out = helper.output();
[email protected]2aeef782013-06-21 18:30:562115 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]93300672009-10-24 13:22:512116}
2117
[email protected]d30022352010-06-24 19:17:582118// Test that the transaction doesn't crash when we get two replies on the same
2119// stream ID. See http://crbug.com/45639.
[email protected]513963e2013-06-15 01:53:042120TEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
[email protected]cdf8f7e72013-05-23 10:56:462121 scoped_ptr<SpdyFrame> req(
2122 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]2aeef782013-06-21 18:30:562123 scoped_ptr<SpdyFrame> rst(
[email protected]00b29472014-01-16 18:10:242124 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
[email protected]2aeef782013-06-21 18:30:562125 MockWrite writes[] = {
2126 CreateMockWrite(*req),
2127 CreateMockWrite(*rst),
2128 };
[email protected]d30022352010-06-24 19:17:582129
[email protected]513963e2013-06-15 01:53:042130 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2131 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d30022352010-06-24 19:17:582132 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:132133 CreateMockRead(*resp),
2134 CreateMockRead(*resp),
2135 CreateMockRead(*body),
[email protected]8ddf8322012-02-23 18:08:062136 MockRead(ASYNC, 0, 0) // EOF
[email protected]d30022352010-06-24 19:17:582137 };
2138
[email protected]dd54bd82012-07-19 23:44:572139 DelayedSocketData data(1, reads, arraysize(reads),
2140 writes, arraysize(writes));
[email protected]d30022352010-06-24 19:17:582141
[email protected]262eec82013-03-19 21:01:362142 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502143 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:472144 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572145 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:472146
2147 HttpNetworkTransaction* trans = helper.trans();
[email protected]d30022352010-06-24 19:17:582148
[email protected]49639fa2011-12-20 23:22:412149 TestCompletionCallback callback;
2150 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
[email protected]d30022352010-06-24 19:17:582151 EXPECT_EQ(ERR_IO_PENDING, rv);
2152 rv = callback.WaitForResult();
2153 EXPECT_EQ(OK, rv);
2154
2155 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a5c493b92010-08-06 23:04:292156 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:502157 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]d30022352010-06-24 19:17:582158 EXPECT_TRUE(response->was_fetched_via_spdy);
2159 std::string response_data;
[email protected]3caf5542010-07-16 15:19:472160 rv = ReadTransaction(trans, &response_data);
[email protected]d30022352010-06-24 19:17:582161 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
[email protected]3caf5542010-07-16 15:19:472162
2163 helper.VerifyDataConsumed();
[email protected]d30022352010-06-24 19:17:582164}
2165
[email protected]513963e2013-06-15 01:53:042166TEST_P(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) {
[email protected]b3503002012-03-27 04:57:252167 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:462168 scoped_ptr<SpdyFrame> req(
2169 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]5a7bb252013-02-09 00:21:052170 scoped_ptr<SpdyFrame> rst(
[email protected]c10b20852013-05-15 21:29:202171 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
[email protected]b3503002012-03-27 04:57:252172 MockWrite writes[] = {
2173 CreateMockWrite(*req),
2174 CreateMockWrite(*rst),
2175 };
2176
2177 const char* const headers[] = {
[email protected]513963e2013-06-15 01:53:042178 "transfer-encoding", "chunked"
[email protected]b3503002012-03-27 04:57:252179 };
[email protected]513963e2013-06-15 01:53:042180 scoped_ptr<SpdyFrame> resp(
2181 spdy_util_.ConstructSpdyGetSynReply(headers, 1, 1));
2182 scoped_ptr<SpdyFrame> body(
2183 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]b3503002012-03-27 04:57:252184 MockRead reads[] = {
2185 CreateMockRead(*resp),
2186 CreateMockRead(*body),
2187 MockRead(ASYNC, 0, 0) // EOF
2188 };
2189
[email protected]dd54bd82012-07-19 23:44:572190 DelayedSocketData data(1, reads, arraysize(reads),
2191 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362192 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502193 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:572194 helper.RunToCompletion(&data);
[email protected]b3503002012-03-27 04:57:252195 TransactionHelperResult out = helper.output();
2196 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
2197
2198 helper.session()->spdy_session_pool()->CloseAllSessions();
2199 helper.VerifyDataConsumed();
2200}
2201
[email protected]513963e2013-06-15 01:53:042202TEST_P(SpdyNetworkTransactionTest, ResetPushWithTransferEncoding) {
[email protected]b3503002012-03-27 04:57:252203 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:462204 scoped_ptr<SpdyFrame> req(
2205 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]5a7bb252013-02-09 00:21:052206 scoped_ptr<SpdyFrame> rst(
[email protected]c10b20852013-05-15 21:29:202207 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
[email protected]b3503002012-03-27 04:57:252208 MockWrite writes[] = {
2209 CreateMockWrite(*req),
2210 CreateMockWrite(*rst),
2211 };
2212
[email protected]513963e2013-06-15 01:53:042213 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2214 const char* const headers[] = {
2215 "transfer-encoding", "chunked"
2216 };
2217 scoped_ptr<SpdyFrame> push(
2218 spdy_util_.ConstructSpdyPush(headers, arraysize(headers) / 2,
2219 2, 1, "http://www.google.com/1"));
2220 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]b3503002012-03-27 04:57:252221 MockRead reads[] = {
2222 CreateMockRead(*resp),
2223 CreateMockRead(*push),
2224 CreateMockRead(*body),
2225 MockRead(ASYNC, 0, 0) // EOF
2226 };
2227
[email protected]dd54bd82012-07-19 23:44:572228 DelayedSocketData data(1, reads, arraysize(reads),
2229 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362230 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502231 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:572232 helper.RunToCompletion(&data);
[email protected]b3503002012-03-27 04:57:252233 TransactionHelperResult out = helper.output();
2234 EXPECT_EQ(OK, out.rv);
2235 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
2236 EXPECT_EQ("hello!", out.response_data);
2237
2238 helper.session()->spdy_session_pool()->CloseAllSessions();
2239 helper.VerifyDataConsumed();
2240}
2241
[email protected]513963e2013-06-15 01:53:042242TEST_P(SpdyNetworkTransactionTest, CancelledTransaction) {
[email protected]75f30cc22010-06-28 21:41:382243 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:462244 scoped_ptr<SpdyFrame> req(
2245 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]34437af82009-11-06 02:28:492246 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:132247 CreateMockWrite(*req),
[email protected]34437af82009-11-06 02:28:492248 };
2249
[email protected]513963e2013-06-15 01:53:042250 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]34437af82009-11-06 02:28:492251 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:132252 CreateMockRead(*resp),
[email protected]34437af82009-11-06 02:28:492253 // This following read isn't used by the test, except during the
[email protected]b4c62eb2012-11-14 18:36:512254 // RunUntilIdle() call at the end since the SpdySession survives the
[email protected]3caf5542010-07-16 15:19:472255 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
[email protected]34437af82009-11-06 02:28:492256 // MockRead will do here.
[email protected]8ddf8322012-02-23 18:08:062257 MockRead(ASYNC, 0, 0) // EOF
[email protected]34437af82009-11-06 02:28:492258 };
2259
[email protected]31a2bfe2010-02-09 08:03:392260 StaticSocketDataProvider data(reads, arraysize(reads),
2261 writes, arraysize(writes));
[email protected]3caf5542010-07-16 15:19:472262
[email protected]262eec82013-03-19 21:01:362263 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502264 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:472265 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:582266 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:472267 HttpNetworkTransaction* trans = helper.trans();
[email protected]34437af82009-11-06 02:28:492268
[email protected]49639fa2011-12-20 23:22:412269 TestCompletionCallback callback;
2270 int rv = trans->Start(
2271 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]34437af82009-11-06 02:28:492272 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3caf5542010-07-16 15:19:472273 helper.ResetTrans(); // Cancel the transaction.
[email protected]34437af82009-11-06 02:28:492274
[email protected]30c942b2010-07-21 16:59:592275 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]34437af82009-11-06 02:28:492276 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:172277 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:472278 helper.VerifyDataNotConsumed();
[email protected]34437af82009-11-06 02:28:492279}
[email protected]72552f02009-10-28 15:25:012280
[email protected]6c6ea172010-07-27 20:04:032281// Verify that the client sends a Rst Frame upon cancelling the stream.
[email protected]513963e2013-06-15 01:53:042282TEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
[email protected]cdf8f7e72013-05-23 10:56:462283 scoped_ptr<SpdyFrame> req(
2284 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]ff98d7f02012-03-22 21:44:192285 scoped_ptr<SpdyFrame> rst(
[email protected]c10b20852013-05-15 21:29:202286 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
[email protected]6c6ea172010-07-27 20:04:032287 MockWrite writes[] = {
[email protected]8ddf8322012-02-23 18:08:062288 CreateMockWrite(*req, 0, SYNCHRONOUS),
2289 CreateMockWrite(*rst, 2, SYNCHRONOUS),
[email protected]6c6ea172010-07-27 20:04:032290 };
2291
[email protected]513963e2013-06-15 01:53:042292 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]6c6ea172010-07-27 20:04:032293 MockRead reads[] = {
[email protected]8ddf8322012-02-23 18:08:062294 CreateMockRead(*resp, 1, ASYNC),
2295 MockRead(ASYNC, 0, 0, 3) // EOF
[email protected]6c6ea172010-07-27 20:04:032296 };
2297
[email protected]dd54bd82012-07-19 23:44:572298 DeterministicSocketData data(reads, arraysize(reads),
[email protected]513963e2013-06-15 01:53:042299 writes, arraysize(writes));
[email protected]6c6ea172010-07-27 20:04:032300
[email protected]262eec82013-03-19 21:01:362301 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]6c6ea172010-07-27 20:04:032302 BoundNetLog(),
[email protected]61b4efc2012-04-27 18:12:502303 GetParam(), NULL);
[email protected]3b7828432010-08-18 18:33:272304 helper.SetDeterministic();
[email protected]6c6ea172010-07-27 20:04:032305 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572306 helper.AddDeterministicData(&data);
[email protected]6c6ea172010-07-27 20:04:032307 HttpNetworkTransaction* trans = helper.trans();
2308
[email protected]49639fa2011-12-20 23:22:412309 TestCompletionCallback callback;
[email protected]6c6ea172010-07-27 20:04:032310
[email protected]49639fa2011-12-20 23:22:412311 int rv = trans->Start(
2312 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]6c6ea172010-07-27 20:04:032313 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]6c6ea172010-07-27 20:04:032314
[email protected]dd54bd82012-07-19 23:44:572315 data.SetStop(2);
2316 data.Run();
[email protected]3b7828432010-08-18 18:33:272317 helper.ResetTrans();
[email protected]dd54bd82012-07-19 23:44:572318 data.SetStop(20);
2319 data.Run();
[email protected]3b7828432010-08-18 18:33:272320
[email protected]6c6ea172010-07-27 20:04:032321 helper.VerifyDataConsumed();
2322}
2323
[email protected]b278eb72010-07-09 20:17:002324// Verify that the client can correctly deal with the user callback attempting
2325// to start another transaction on a session that is closing down. See
2326// http://crbug.com/47455
[email protected]513963e2013-06-15 01:53:042327TEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
[email protected]cdf8f7e72013-05-23 10:56:462328 scoped_ptr<SpdyFrame> req(
2329 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]b278eb72010-07-09 20:17:002330 MockWrite writes[] = { CreateMockWrite(*req) };
2331 MockWrite writes2[] = { CreateMockWrite(*req) };
2332
[email protected]cbdd73162013-03-18 23:27:332333 // The indicated length of this frame is longer than its actual length. When
2334 // the session receives an empty frame after this one, it shuts down the
[email protected]b278eb72010-07-09 20:17:002335 // session, and calls the read callback with the incomplete data.
2336 const uint8 kGetBodyFrame2[] = {
2337 0x00, 0x00, 0x00, 0x01,
2338 0x01, 0x00, 0x00, 0x07,
2339 'h', 'e', 'l', 'l', 'o', '!',
2340 };
2341
[email protected]513963e2013-06-15 01:53:042342 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]b278eb72010-07-09 20:17:002343 MockRead reads[] = {
2344 CreateMockRead(*resp, 2),
[email protected]8ddf8322012-02-23 18:08:062345 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause
2346 MockRead(ASYNC, reinterpret_cast<const char*>(kGetBodyFrame2),
[email protected]b278eb72010-07-09 20:17:002347 arraysize(kGetBodyFrame2), 4),
[email protected]8ddf8322012-02-23 18:08:062348 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
2349 MockRead(ASYNC, 0, 0, 6), // EOF
[email protected]b278eb72010-07-09 20:17:002350 };
2351 MockRead reads2[] = {
2352 CreateMockRead(*resp, 2),
[email protected]8ddf8322012-02-23 18:08:062353 MockRead(ASYNC, 0, 0, 3), // EOF
[email protected]b278eb72010-07-09 20:17:002354 };
2355
[email protected]dd54bd82012-07-19 23:44:572356 OrderedSocketData data(reads, arraysize(reads),
2357 writes, arraysize(writes));
2358 DelayedSocketData data2(1, reads2, arraysize(reads2),
2359 writes2, arraysize(writes2));
[email protected]3caf5542010-07-16 15:19:472360
[email protected]262eec82013-03-19 21:01:362361 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502362 BoundNetLog(), GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:582363 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572364 helper.AddData(&data);
2365 helper.AddData(&data2);
[email protected]3caf5542010-07-16 15:19:472366 HttpNetworkTransaction* trans = helper.trans();
[email protected]b278eb72010-07-09 20:17:002367
2368 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412369 TestCompletionCallback callback;
2370 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
[email protected]b278eb72010-07-09 20:17:002371 EXPECT_EQ(ERR_IO_PENDING, rv);
2372 rv = callback.WaitForResult();
2373
[email protected]b278eb72010-07-09 20:17:002374 const int kSize = 3000;
[email protected]ad8e04a2010-11-01 04:16:272375 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
[email protected]49639fa2011-12-20 23:22:412376 rv = trans->Read(
[email protected]90499482013-06-01 00:39:502377 buf.get(),
2378 kSize,
[email protected]513963e2013-06-15 01:53:042379 base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback,
[email protected]49639fa2011-12-20 23:22:412380 helper.session()));
[email protected]3caf5542010-07-16 15:19:472381 // This forces an err_IO_pending, which sets the callback.
[email protected]dd54bd82012-07-19 23:44:572382 data.CompleteRead();
[email protected]3caf5542010-07-16 15:19:472383 // This finishes the read.
[email protected]dd54bd82012-07-19 23:44:572384 data.CompleteRead();
[email protected]3caf5542010-07-16 15:19:472385 helper.VerifyDataConsumed();
[email protected]b278eb72010-07-09 20:17:002386}
2387
[email protected]9be804c82010-06-24 17:59:462388// Verify that the client can correctly deal with the user callback deleting the
2389// transaction. Failures will usually be valgrind errors. See
2390// http://crbug.com/46925
[email protected]513963e2013-06-15 01:53:042391TEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
[email protected]cdf8f7e72013-05-23 10:56:462392 scoped_ptr<SpdyFrame> req(
2393 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]e7f75092010-07-01 22:39:132394 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]9be804c82010-06-24 17:59:462395
[email protected]513963e2013-06-15 01:53:042396 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2397 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]9be804c82010-06-24 17:59:462398 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:132399 CreateMockRead(*resp.get(), 2),
[email protected]8ddf8322012-02-23 18:08:062400 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause
[email protected]e7f75092010-07-01 22:39:132401 CreateMockRead(*body.get(), 4),
[email protected]8ddf8322012-02-23 18:08:062402 MockRead(ASYNC, 0, 0, 5), // EOF
[email protected]9be804c82010-06-24 17:59:462403 };
2404
[email protected]dd54bd82012-07-19 23:44:572405 OrderedSocketData data(reads, arraysize(reads),
2406 writes, arraysize(writes));
[email protected]3caf5542010-07-16 15:19:472407
[email protected]262eec82013-03-19 21:01:362408 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502409 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:472410 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572411 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:472412 HttpNetworkTransaction* trans = helper.trans();
[email protected]9be804c82010-06-24 17:59:462413
2414 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412415 TestCompletionCallback callback;
2416 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
[email protected]9be804c82010-06-24 17:59:462417 EXPECT_EQ(ERR_IO_PENDING, rv);
2418 rv = callback.WaitForResult();
2419
2420 // Setup a user callback which will delete the session, and clear out the
2421 // memory holding the stream object. Note that the callback deletes trans.
[email protected]9be804c82010-06-24 17:59:462422 const int kSize = 3000;
[email protected]ad8e04a2010-11-01 04:16:272423 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
[email protected]49639fa2011-12-20 23:22:412424 rv = trans->Read(
[email protected]90499482013-06-01 00:39:502425 buf.get(),
2426 kSize,
[email protected]513963e2013-06-15 01:53:042427 base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback,
[email protected]49639fa2011-12-20 23:22:412428 base::Unretained(&helper)));
[email protected]9be804c82010-06-24 17:59:462429 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]dd54bd82012-07-19 23:44:572430 data.CompleteRead();
[email protected]9be804c82010-06-24 17:59:462431
2432 // Finish running rest of tasks.
[email protected]fc9d88472013-08-14 02:31:172433 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:472434 helper.VerifyDataConsumed();
[email protected]9be804c82010-06-24 17:59:462435}
2436
[email protected]e3ebba0f2010-08-05 17:59:582437// Send a spdy request to www.google.com that gets redirected to www.foo.com.
[email protected]513963e2013-06-15 01:53:042438TEST_P(SpdyNetworkTransactionTest, RedirectGetRequest) {
[email protected]513963e2013-06-15 01:53:042439 scoped_ptr<SpdyHeaderBlock> headers(
2440 spdy_util_.ConstructGetHeaderBlock("http://www.google.com/"));
2441 (*headers)["user-agent"] = "";
jgraettinger8f00db8b2014-09-24 23:00:062442 (*headers)["accept-encoding"] = "gzip, deflate";
[email protected]513963e2013-06-15 01:53:042443 scoped_ptr<SpdyHeaderBlock> headers2(
2444 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2445 (*headers2)["user-agent"] = "";
jgraettinger8f00db8b2014-09-24 23:00:062446 (*headers2)["accept-encoding"] = "gzip, deflate";
[email protected]e3ebba0f2010-08-05 17:59:582447
2448 // Setup writes/reads to www.google.com
[email protected]745aa9c2014-06-27 02:21:292449 scoped_ptr<SpdyFrame> req(
2450 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
2451 scoped_ptr<SpdyFrame> req2(
2452 spdy_util_.ConstructSpdySyn(1, *headers2, LOWEST, false, true));
[email protected]513963e2013-06-15 01:53:042453 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReplyRedirect(1));
[email protected]e3ebba0f2010-08-05 17:59:582454 MockWrite writes[] = {
2455 CreateMockWrite(*req, 1),
2456 };
2457 MockRead reads[] = {
2458 CreateMockRead(*resp, 2),
[email protected]8ddf8322012-02-23 18:08:062459 MockRead(ASYNC, 0, 0, 3) // EOF
[email protected]e3ebba0f2010-08-05 17:59:582460 };
2461
2462 // Setup writes/reads to www.foo.com
[email protected]513963e2013-06-15 01:53:042463 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2464 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582465 MockWrite writes2[] = {
2466 CreateMockWrite(*req2, 1),
2467 };
2468 MockRead reads2[] = {
2469 CreateMockRead(*resp2, 2),
2470 CreateMockRead(*body2, 3),
[email protected]8ddf8322012-02-23 18:08:062471 MockRead(ASYNC, 0, 0, 4) // EOF
[email protected]e3ebba0f2010-08-05 17:59:582472 };
[email protected]dd54bd82012-07-19 23:44:572473 OrderedSocketData data(reads, arraysize(reads),
2474 writes, arraysize(writes));
2475 OrderedSocketData data2(reads2, arraysize(reads2),
2476 writes2, arraysize(writes2));
[email protected]e3ebba0f2010-08-05 17:59:582477
2478 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
[email protected]e3ebba0f2010-08-05 17:59:582479 TestDelegate d;
2480 {
[email protected]d7599122014-05-24 03:37:232481 SpdyURLRequestContext spdy_url_request_context(
2482 GetParam().protocol,
2483 false /* force_spdy_over_ssl*/,
2484 true /* force_spdy_always */);
[email protected]f7022f32014-08-21 16:32:192485 scoped_ptr<URLRequest> r(
2486 spdy_url_request_context.CreateRequest(GURL("http://www.google.com/"),
2487 DEFAULT_PRIORITY,
2488 &d,
2489 NULL));
[email protected]ef2bf422012-05-11 03:27:092490 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572491 AddSocketDataProvider(&data);
[email protected]ef2bf422012-05-11 03:27:092492 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572493 AddSocketDataProvider(&data2);
[email protected]e3ebba0f2010-08-05 17:59:582494
2495 d.set_quit_on_redirect(true);
[email protected]f7022f32014-08-21 16:32:192496 r->Start();
[email protected]fc9d88472013-08-14 02:31:172497 base::RunLoop().Run();
[email protected]513963e2013-06-15 01:53:042498
[email protected]e3ebba0f2010-08-05 17:59:582499 EXPECT_EQ(1, d.received_redirect_count());
2500
[email protected]f7022f32014-08-21 16:32:192501 r->FollowDeferredRedirect();
[email protected]fc9d88472013-08-14 02:31:172502 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582503 EXPECT_EQ(1, d.response_started_count());
2504 EXPECT_FALSE(d.received_data_before_response());
[email protected]f7022f32014-08-21 16:32:192505 EXPECT_EQ(net::URLRequestStatus::SUCCESS, r->status().status());
[email protected]e3ebba0f2010-08-05 17:59:582506 std::string contents("hello!");
2507 EXPECT_EQ(contents, d.data_received());
2508 }
[email protected]dd54bd82012-07-19 23:44:572509 EXPECT_TRUE(data.at_read_eof());
2510 EXPECT_TRUE(data.at_write_eof());
2511 EXPECT_TRUE(data2.at_read_eof());
2512 EXPECT_TRUE(data2.at_write_eof());
[email protected]e3ebba0f2010-08-05 17:59:582513}
2514
2515// Send a spdy request to www.google.com. Get a pushed stream that redirects to
2516// www.foo.com.
[email protected]513963e2013-06-15 01:53:042517TEST_P(SpdyNetworkTransactionTest, RedirectServerPush) {
[email protected]513963e2013-06-15 01:53:042518 scoped_ptr<SpdyHeaderBlock> headers(
2519 spdy_util_.ConstructGetHeaderBlock("http://www.google.com/"));
2520 (*headers)["user-agent"] = "";
jgraettinger8f00db8b2014-09-24 23:00:062521 (*headers)["accept-encoding"] = "gzip, deflate";
[email protected]3a8d6852011-03-11 23:43:442522
2523 // Setup writes/reads to www.google.com
[email protected]ff98d7f02012-03-22 21:44:192524 scoped_ptr<SpdyFrame> req(
[email protected]745aa9c2014-06-27 02:21:292525 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
[email protected]513963e2013-06-15 01:53:042526 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]ff98d7f02012-03-22 21:44:192527 scoped_ptr<SpdyFrame> rep(
[email protected]513963e2013-06-15 01:53:042528 spdy_util_.ConstructSpdyPush(NULL,
[email protected]3a8d6852011-03-11 23:43:442529 0,
2530 2,
2531 1,
2532 "http://www.google.com/foo.dat",
2533 "301 Moved Permanently",
2534 "http://www.foo.com/index.php"));
[email protected]513963e2013-06-15 01:53:042535 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c10b20852013-05-15 21:29:202536 scoped_ptr<SpdyFrame> rst(
2537 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
[email protected]3a8d6852011-03-11 23:43:442538 MockWrite writes[] = {
2539 CreateMockWrite(*req, 1),
2540 CreateMockWrite(*rst, 6),
2541 };
2542 MockRead reads[] = {
2543 CreateMockRead(*resp, 2),
2544 CreateMockRead(*rep, 3),
2545 CreateMockRead(*body, 4),
[email protected]8ddf8322012-02-23 18:08:062546 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
2547 MockRead(ASYNC, 0, 0, 7) // EOF
[email protected]3a8d6852011-03-11 23:43:442548 };
2549
2550 // Setup writes/reads to www.foo.com
[email protected]513963e2013-06-15 01:53:042551 scoped_ptr<SpdyHeaderBlock> headers2(
2552 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2553 (*headers2)["user-agent"] = "";
jgraettinger8f00db8b2014-09-24 23:00:062554 (*headers2)["accept-encoding"] = "gzip, deflate";
[email protected]ff98d7f02012-03-22 21:44:192555 scoped_ptr<SpdyFrame> req2(
[email protected]745aa9c2014-06-27 02:21:292556 spdy_util_.ConstructSpdySyn(1, *headers2, LOWEST, false, true));
[email protected]513963e2013-06-15 01:53:042557 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2558 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582559 MockWrite writes2[] = {
2560 CreateMockWrite(*req2, 1),
2561 };
2562 MockRead reads2[] = {
2563 CreateMockRead(*resp2, 2),
2564 CreateMockRead(*body2, 3),
[email protected]8ddf8322012-02-23 18:08:062565 MockRead(ASYNC, 0, 0, 5) // EOF
[email protected]e3ebba0f2010-08-05 17:59:582566 };
[email protected]dd54bd82012-07-19 23:44:572567 OrderedSocketData data(reads, arraysize(reads),
2568 writes, arraysize(writes));
2569 OrderedSocketData data2(reads2, arraysize(reads2),
2570 writes2, arraysize(writes2));
[email protected]e3ebba0f2010-08-05 17:59:582571
2572 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
[email protected]e3ebba0f2010-08-05 17:59:582573 TestDelegate d;
2574 TestDelegate d2;
[email protected]d7599122014-05-24 03:37:232575 SpdyURLRequestContext spdy_url_request_context(
2576 GetParam().protocol,
2577 false /* force_spdy_over_ssl*/,
2578 true /* force_spdy_always */);
[email protected]e3ebba0f2010-08-05 17:59:582579 {
[email protected]f7022f32014-08-21 16:32:192580 scoped_ptr<URLRequest> r(
2581 spdy_url_request_context.CreateRequest(GURL("http://www.google.com/"),
2582 DEFAULT_PRIORITY,
2583 &d,
2584 NULL));
[email protected]ef2bf422012-05-11 03:27:092585 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572586 AddSocketDataProvider(&data);
[email protected]e3ebba0f2010-08-05 17:59:582587
[email protected]f7022f32014-08-21 16:32:192588 r->Start();
[email protected]fc9d88472013-08-14 02:31:172589 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582590
2591 EXPECT_EQ(0, d.received_redirect_count());
2592 std::string contents("hello!");
2593 EXPECT_EQ(contents, d.data_received());
2594
[email protected]f7022f32014-08-21 16:32:192595 scoped_ptr<URLRequest> r2(
2596 spdy_url_request_context.CreateRequest(
2597 GURL("http://www.google.com/foo.dat"),
2598 DEFAULT_PRIORITY,
2599 &d2,
2600 NULL));
[email protected]ef2bf422012-05-11 03:27:092601 spdy_url_request_context.socket_factory().
[email protected]dd54bd82012-07-19 23:44:572602 AddSocketDataProvider(&data2);
[email protected]e3ebba0f2010-08-05 17:59:582603
2604 d2.set_quit_on_redirect(true);
[email protected]f7022f32014-08-21 16:32:192605 r2->Start();
[email protected]fc9d88472013-08-14 02:31:172606 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582607 EXPECT_EQ(1, d2.received_redirect_count());
2608
[email protected]f7022f32014-08-21 16:32:192609 r2->FollowDeferredRedirect();
[email protected]fc9d88472013-08-14 02:31:172610 base::RunLoop().Run();
[email protected]e3ebba0f2010-08-05 17:59:582611 EXPECT_EQ(1, d2.response_started_count());
2612 EXPECT_FALSE(d2.received_data_before_response());
[email protected]f7022f32014-08-21 16:32:192613 EXPECT_EQ(net::URLRequestStatus::SUCCESS, r2->status().status());
[email protected]e3ebba0f2010-08-05 17:59:582614 std::string contents2("hello!");
2615 EXPECT_EQ(contents2, d2.data_received());
2616 }
[email protected]dd54bd82012-07-19 23:44:572617 data.CompleteRead();
2618 data2.CompleteRead();
2619 EXPECT_TRUE(data.at_read_eof());
2620 EXPECT_TRUE(data.at_write_eof());
2621 EXPECT_TRUE(data2.at_read_eof());
2622 EXPECT_TRUE(data2.at_write_eof());
[email protected]e3ebba0f2010-08-05 17:59:582623}
2624
[email protected]513963e2013-06-15 01:53:042625TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
[email protected]cdf8f7e72013-05-23 10:56:462626 scoped_ptr<SpdyFrame> stream1_syn(
2627 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042628 scoped_ptr<SpdyFrame> stream1_body(
2629 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582630 MockWrite writes[] = {
[email protected]19ec8a72010-08-23 03:38:232631 CreateMockWrite(*stream1_syn, 1),
[email protected]e3ebba0f2010-08-05 17:59:582632 };
2633
[email protected]ff98d7f02012-03-22 21:44:192634 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042635 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]ff98d7f02012-03-22 21:44:192636 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042637 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
[email protected]d08358502010-12-03 22:04:032638 0,
2639 2,
2640 1,
2641 "http://www.google.com/foo.dat"));
[email protected]8a0fc822013-06-27 20:52:432642 const char kPushedData[] = "pushed";
2643 scoped_ptr<SpdyFrame> stream2_body(
2644 spdy_util_.ConstructSpdyBodyFrame(
2645 2, kPushedData, strlen(kPushedData), true));
[email protected]e3ebba0f2010-08-05 17:59:582646 MockRead reads[] = {
[email protected]19ec8a72010-08-23 03:38:232647 CreateMockRead(*stream1_reply, 2),
2648 CreateMockRead(*stream2_syn, 3),
[email protected]8ddf8322012-02-23 18:08:062649 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
[email protected]8a0fc822013-06-27 20:52:432650 CreateMockRead(*stream2_body, 5),
[email protected]8ddf8322012-02-23 18:08:062651 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582652 };
2653
2654 HttpResponseInfo response;
2655 HttpResponseInfo response2;
[email protected]19ec8a72010-08-23 03:38:232656 std::string expected_push_result("pushed");
[email protected]dd54bd82012-07-19 23:44:572657 OrderedSocketData data(reads, arraysize(reads),
2658 writes, arraysize(writes));
2659 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:032660 &response,
2661 &response2,
2662 expected_push_result);
[email protected]e3ebba0f2010-08-05 17:59:582663
2664 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502665 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]e3ebba0f2010-08-05 17:59:582666 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2667
2668 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502669 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]e3ebba0f2010-08-05 17:59:582670 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2671}
2672
[email protected]513963e2013-06-15 01:53:042673TEST_P(SpdyNetworkTransactionTest, ServerPushBeforeSynReply) {
[email protected]cdf8f7e72013-05-23 10:56:462674 scoped_ptr<SpdyFrame> stream1_syn(
2675 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042676 scoped_ptr<SpdyFrame> stream1_body(
2677 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]a5b8eb29d2012-03-06 06:19:462678 MockWrite writes[] = {
2679 CreateMockWrite(*stream1_syn, 1),
2680 };
2681
[email protected]ff98d7f02012-03-22 21:44:192682 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042683 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]ff98d7f02012-03-22 21:44:192684 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042685 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
[email protected]a5b8eb29d2012-03-06 06:19:462686 0,
2687 2,
2688 1,
2689 "http://www.google.com/foo.dat"));
[email protected]8a0fc822013-06-27 20:52:432690 const char kPushedData[] = "pushed";
2691 scoped_ptr<SpdyFrame> stream2_body(
2692 spdy_util_.ConstructSpdyBodyFrame(
2693 2, kPushedData, strlen(kPushedData), true));
[email protected]a5b8eb29d2012-03-06 06:19:462694 MockRead reads[] = {
2695 CreateMockRead(*stream2_syn, 2),
2696 CreateMockRead(*stream1_reply, 3),
2697 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
[email protected]8a0fc822013-06-27 20:52:432698 CreateMockRead(*stream2_body, 5),
[email protected]a5b8eb29d2012-03-06 06:19:462699 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2700 };
2701
2702 HttpResponseInfo response;
2703 HttpResponseInfo response2;
2704 std::string expected_push_result("pushed");
[email protected]dd54bd82012-07-19 23:44:572705 OrderedSocketData data(reads, arraysize(reads),
2706 writes, arraysize(writes));
2707 RunServerPushTest(&data,
[email protected]a5b8eb29d2012-03-06 06:19:462708 &response,
2709 &response2,
2710 expected_push_result);
2711
2712 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502713 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]a5b8eb29d2012-03-06 06:19:462714 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2715
2716 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502717 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]a5b8eb29d2012-03-06 06:19:462718 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2719}
2720
[email protected]513963e2013-06-15 01:53:042721TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
[email protected]cdf8f7e72013-05-23 10:56:462722 scoped_ptr<SpdyFrame> stream1_syn(
2723 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2724 MockWrite writes[] = { CreateMockWrite(*stream1_syn, 1), };
[email protected]82918cc2010-08-25 17:24:502725
[email protected]ff98d7f02012-03-22 21:44:192726 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042727 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]ff98d7f02012-03-22 21:44:192728 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042729 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
[email protected]d08358502010-12-03 22:04:032730 0,
2731 2,
2732 1,
2733 "http://www.google.com/foo.dat"));
[email protected]8a0fc822013-06-27 20:52:432734 const char kPushedData[] = "pushed";
2735 scoped_ptr<SpdyFrame> stream2_body(
2736 spdy_util_.ConstructSpdyBodyFrame(
2737 2, kPushedData, strlen(kPushedData), true));
[email protected]ff98d7f02012-03-22 21:44:192738 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042739 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]82918cc2010-08-25 17:24:502740 MockRead reads[] = {
2741 CreateMockRead(*stream1_reply, 2),
2742 CreateMockRead(*stream2_syn, 3),
[email protected]8a0fc822013-06-27 20:52:432743 CreateMockRead(*stream2_body, 4),
2744 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
[email protected]8ddf8322012-02-23 18:08:062745 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
[email protected]82918cc2010-08-25 17:24:502746 };
2747
2748 HttpResponseInfo response;
2749 HttpResponseInfo response2;
2750 std::string expected_push_result("pushed");
[email protected]dd54bd82012-07-19 23:44:572751 OrderedSocketData data(reads, arraysize(reads),
2752 writes, arraysize(writes));
2753 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:032754 &response,
2755 &response2,
2756 expected_push_result);
[email protected]82918cc2010-08-25 17:24:502757
2758 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502759 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]82918cc2010-08-25 17:24:502760 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2761
2762 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502763 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]82918cc2010-08-25 17:24:502764 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2765}
2766
[email protected]513963e2013-06-15 01:53:042767TEST_P(SpdyNetworkTransactionTest, ServerPushServerAborted) {
[email protected]cdf8f7e72013-05-23 10:56:462768 scoped_ptr<SpdyFrame> stream1_syn(
2769 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042770 scoped_ptr<SpdyFrame> stream1_body(
2771 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582772 MockWrite writes[] = {
[email protected]19ec8a72010-08-23 03:38:232773 CreateMockWrite(*stream1_syn, 1),
[email protected]e3ebba0f2010-08-05 17:59:582774 };
2775
[email protected]ff98d7f02012-03-22 21:44:192776 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042777 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]ff98d7f02012-03-22 21:44:192778 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042779 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
[email protected]d08358502010-12-03 22:04:032780 0,
2781 2,
2782 1,
2783 "http://www.google.com/foo.dat"));
[email protected]c10b20852013-05-15 21:29:202784 scoped_ptr<SpdyFrame> stream2_rst(
2785 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
[email protected]e3ebba0f2010-08-05 17:59:582786 MockRead reads[] = {
[email protected]19ec8a72010-08-23 03:38:232787 CreateMockRead(*stream1_reply, 2),
2788 CreateMockRead(*stream2_syn, 3),
2789 CreateMockRead(*stream2_rst, 4),
[email protected]8ddf8322012-02-23 18:08:062790 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
2791 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582792 };
2793
[email protected]dd54bd82012-07-19 23:44:572794 OrderedSocketData data(reads, arraysize(reads),
2795 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:362796 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:502797 BoundNetLog(), GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:582798
2799 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:572800 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:582801
2802 HttpNetworkTransaction* trans = helper.trans();
2803
2804 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:412805 TestCompletionCallback callback;
2806 int rv = trans->Start(
2807 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]e3ebba0f2010-08-05 17:59:582808 EXPECT_EQ(ERR_IO_PENDING, rv);
2809 rv = callback.WaitForResult();
[email protected]19ec8a72010-08-23 03:38:232810 EXPECT_EQ(OK, rv);
2811
2812 // Verify that we consumed all test data.
[email protected]dd54bd82012-07-19 23:44:572813 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
2814 << data.read_count()
[email protected]19ec8a72010-08-23 03:38:232815 << " Read index: "
[email protected]dd54bd82012-07-19 23:44:572816 << data.read_index();
2817 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
2818 << data.write_count()
[email protected]19ec8a72010-08-23 03:38:232819 << " Write index: "
[email protected]dd54bd82012-07-19 23:44:572820 << data.write_index();
[email protected]19ec8a72010-08-23 03:38:232821
2822 // Verify the SYN_REPLY.
2823 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:502824 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]19ec8a72010-08-23 03:38:232825 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2826}
2827
[email protected]8a0fc822013-06-27 20:52:432828// Verify that we don't leak streams and that we properly send a reset
2829// if the server pushes the same stream twice.
[email protected]513963e2013-06-15 01:53:042830TEST_P(SpdyNetworkTransactionTest, ServerPushDuplicate) {
[email protected]cdf8f7e72013-05-23 10:56:462831 scoped_ptr<SpdyFrame> stream1_syn(
2832 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042833 scoped_ptr<SpdyFrame> stream1_body(
2834 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c10b20852013-05-15 21:29:202835 scoped_ptr<SpdyFrame> stream3_rst(
2836 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR));
[email protected]fdc165a2010-09-03 03:51:292837 MockWrite writes[] = {
2838 CreateMockWrite(*stream1_syn, 1),
2839 CreateMockWrite(*stream3_rst, 5),
2840 };
2841
[email protected]ff98d7f02012-03-22 21:44:192842 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042843 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]ff98d7f02012-03-22 21:44:192844 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042845 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
[email protected]d08358502010-12-03 22:04:032846 0,
2847 2,
2848 1,
2849 "http://www.google.com/foo.dat"));
[email protected]8a0fc822013-06-27 20:52:432850 const char kPushedData[] = "pushed";
2851 scoped_ptr<SpdyFrame> stream2_body(
2852 spdy_util_.ConstructSpdyBodyFrame(
2853 2, kPushedData, strlen(kPushedData), true));
[email protected]ff98d7f02012-03-22 21:44:192854 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042855 stream3_syn(spdy_util_.ConstructSpdyPush(NULL,
[email protected]d08358502010-12-03 22:04:032856 0,
2857 4,
2858 1,
2859 "http://www.google.com/foo.dat"));
[email protected]fdc165a2010-09-03 03:51:292860 MockRead reads[] = {
2861 CreateMockRead(*stream1_reply, 2),
2862 CreateMockRead(*stream2_syn, 3),
2863 CreateMockRead(*stream3_syn, 4),
[email protected]8ddf8322012-02-23 18:08:062864 CreateMockRead(*stream1_body, 6, SYNCHRONOUS),
[email protected]8a0fc822013-06-27 20:52:432865 CreateMockRead(*stream2_body, 7),
[email protected]8ddf8322012-02-23 18:08:062866 MockRead(ASYNC, ERR_IO_PENDING, 8), // Force a pause
[email protected]fdc165a2010-09-03 03:51:292867 };
2868
2869 HttpResponseInfo response;
2870 HttpResponseInfo response2;
2871 std::string expected_push_result("pushed");
[email protected]dd54bd82012-07-19 23:44:572872 OrderedSocketData data(reads, arraysize(reads),
2873 writes, arraysize(writes));
2874 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:032875 &response,
2876 &response2,
2877 expected_push_result);
[email protected]fdc165a2010-09-03 03:51:292878
2879 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502880 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]fdc165a2010-09-03 03:51:292881 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2882
2883 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502884 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]fdc165a2010-09-03 03:51:292885 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2886}
2887
[email protected]513963e2013-06-15 01:53:042888TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
[email protected]cdf8f7e72013-05-23 10:56:462889 scoped_ptr<SpdyFrame> stream1_syn(
2890 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042891 scoped_ptr<SpdyFrame> stream1_body(
2892 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]19ec8a72010-08-23 03:38:232893 MockWrite writes[] = {
2894 CreateMockWrite(*stream1_syn, 1),
2895 };
2896
[email protected]ff98d7f02012-03-22 21:44:192897 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042898 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]ff98d7f02012-03-22 21:44:192899 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042900 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
[email protected]d08358502010-12-03 22:04:032901 0,
2902 2,
2903 1,
2904 "http://www.google.com/foo.dat"));
[email protected]8a0fc822013-06-27 20:52:432905 static const char kPushedData[] = "pushed my darling hello my baby";
2906 scoped_ptr<SpdyFrame> stream2_body_base(
2907 spdy_util_.ConstructSpdyBodyFrame(
2908 2, kPushedData, strlen(kPushedData), true));
2909 const size_t kChunkSize = strlen(kPushedData) / 4;
2910 scoped_ptr<SpdyFrame> stream2_body1(
2911 new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
2912 scoped_ptr<SpdyFrame> stream2_body2(
2913 new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
2914 scoped_ptr<SpdyFrame> stream2_body3(
2915 new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
2916 kChunkSize, false));
2917 scoped_ptr<SpdyFrame> stream2_body4(
2918 new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
2919 stream2_body_base->size() - 3 * kChunkSize, false));
[email protected]19ec8a72010-08-23 03:38:232920 MockRead reads[] = {
2921 CreateMockRead(*stream1_reply, 2),
2922 CreateMockRead(*stream2_syn, 3),
[email protected]8a0fc822013-06-27 20:52:432923 CreateMockRead(*stream2_body1, 4),
2924 CreateMockRead(*stream2_body2, 5),
2925 CreateMockRead(*stream2_body3, 6),
2926 CreateMockRead(*stream2_body4, 7),
[email protected]8ddf8322012-02-23 18:08:062927 CreateMockRead(*stream1_body, 8, SYNCHRONOUS),
2928 MockRead(ASYNC, ERR_IO_PENDING, 9), // Force a pause
[email protected]19ec8a72010-08-23 03:38:232929 };
2930
2931 HttpResponseInfo response;
2932 HttpResponseInfo response2;
2933 std::string expected_push_result("pushed my darling hello my baby");
[email protected]dd54bd82012-07-19 23:44:572934 OrderedSocketData data(reads, arraysize(reads),
2935 writes, arraysize(writes));
[email protected]8a0fc822013-06-27 20:52:432936 RunServerPushTest(&data, &response, &response2, kPushedData);
[email protected]19ec8a72010-08-23 03:38:232937
2938 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502939 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]19ec8a72010-08-23 03:38:232940 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2941
2942 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:502943 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]19ec8a72010-08-23 03:38:232944 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2945}
2946
[email protected]513963e2013-06-15 01:53:042947TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
[email protected]cdf8f7e72013-05-23 10:56:462948 scoped_ptr<SpdyFrame> stream1_syn(
2949 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:042950 scoped_ptr<SpdyFrame> stream1_body(
2951 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]19ec8a72010-08-23 03:38:232952 MockWrite writes[] = {
2953 CreateMockWrite(*stream1_syn, 1),
2954 };
2955
[email protected]ff98d7f02012-03-22 21:44:192956 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042957 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]ff98d7f02012-03-22 21:44:192958 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:042959 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
[email protected]d08358502010-12-03 22:04:032960 0,
2961 2,
2962 1,
2963 "http://www.google.com/foo.dat"));
[email protected]8a0fc822013-06-27 20:52:432964 static const char kPushedData[] = "pushed my darling hello my baby";
2965 scoped_ptr<SpdyFrame> stream2_body_base(
2966 spdy_util_.ConstructSpdyBodyFrame(
2967 2, kPushedData, strlen(kPushedData), true));
2968 const size_t kChunkSize = strlen(kPushedData) / 4;
2969 scoped_ptr<SpdyFrame> stream2_body1(
2970 new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
2971 scoped_ptr<SpdyFrame> stream2_body2(
2972 new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
2973 scoped_ptr<SpdyFrame> stream2_body3(
2974 new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
2975 kChunkSize, false));
2976 scoped_ptr<SpdyFrame> stream2_body4(
2977 new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
2978 stream2_body_base->size() - 3 * kChunkSize, false));
[email protected]19ec8a72010-08-23 03:38:232979 MockRead reads[] = {
2980 CreateMockRead(*stream1_reply, 2),
2981 CreateMockRead(*stream2_syn, 3),
[email protected]8a0fc822013-06-27 20:52:432982 CreateMockRead(*stream2_body1, 4),
2983 CreateMockRead(*stream2_body2, 5),
[email protected]8ddf8322012-02-23 18:08:062984 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
[email protected]8a0fc822013-06-27 20:52:432985 CreateMockRead(*stream2_body3, 7),
2986 CreateMockRead(*stream2_body4, 8),
[email protected]8ddf8322012-02-23 18:08:062987 CreateMockRead(*stream1_body.get(), 9, SYNCHRONOUS),
2988 MockRead(ASYNC, ERR_IO_PENDING, 10) // Force a pause.
[email protected]19ec8a72010-08-23 03:38:232989 };
2990
2991 HttpResponseInfo response;
2992 HttpResponseInfo response2;
[email protected]dd54bd82012-07-19 23:44:572993 OrderedSocketData data(reads, arraysize(reads),
2994 writes, arraysize(writes));
[email protected]8a0fc822013-06-27 20:52:432995 RunServerPushTest(&data, &response, &response2, kPushedData);
[email protected]19ec8a72010-08-23 03:38:232996
2997 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:502998 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]19ec8a72010-08-23 03:38:232999 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3000
3001 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:503002 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]19ec8a72010-08-23 03:38:233003 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
3004}
3005
[email protected]513963e2013-06-15 01:53:043006TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
[email protected]00b29472014-01-16 18:10:243007 if (spdy_util_.spdy_version() == SPDY4) {
[email protected]0338bc62014-06-20 17:09:563008 // PUSH_PROMISE with stream id 0 is connection-level error.
3009 // TODO(baranovich): Test session going away.
[email protected]00b29472014-01-16 18:10:243010 return;
3011 }
[email protected]0338bc62014-06-20 17:09:563012
[email protected]cdf8f7e72013-05-23 10:56:463013 scoped_ptr<SpdyFrame> stream1_syn(
3014 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:043015 scoped_ptr<SpdyFrame> stream1_body(
3016 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c10b20852013-05-15 21:29:203017 scoped_ptr<SpdyFrame> stream2_rst(
3018 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
[email protected]19ec8a72010-08-23 03:38:233019 MockWrite writes[] = {
3020 CreateMockWrite(*stream1_syn, 1),
3021 CreateMockWrite(*stream2_rst, 4),
3022 };
3023
[email protected]ff98d7f02012-03-22 21:44:193024 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:043025 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]ff98d7f02012-03-22 21:44:193026 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:043027 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
[email protected]d08358502010-12-03 22:04:033028 0,
3029 2,
3030 0,
3031 "http://www.google.com/foo.dat"));
[email protected]19ec8a72010-08-23 03:38:233032 MockRead reads[] = {
3033 CreateMockRead(*stream1_reply, 2),
3034 CreateMockRead(*stream2_syn, 3),
3035 CreateMockRead(*stream1_body, 4),
[email protected]8ddf8322012-02-23 18:08:063036 MockRead(ASYNC, ERR_IO_PENDING, 5) // Force a pause
[email protected]19ec8a72010-08-23 03:38:233037 };
3038
[email protected]dd54bd82012-07-19 23:44:573039 OrderedSocketData data(reads, arraysize(reads),
3040 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:363041 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503042 BoundNetLog(), GetParam(), NULL);
[email protected]19ec8a72010-08-23 03:38:233043
3044 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573045 helper.AddData(&data);
[email protected]19ec8a72010-08-23 03:38:233046
3047 HttpNetworkTransaction* trans = helper.trans();
3048
3049 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:413050 TestCompletionCallback callback;
3051 int rv = trans->Start(
3052 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]19ec8a72010-08-23 03:38:233053 EXPECT_EQ(ERR_IO_PENDING, rv);
3054 rv = callback.WaitForResult();
[email protected]e3ebba0f2010-08-05 17:59:583055 EXPECT_EQ(OK, rv);
3056
3057 // Verify that we consumed all test data.
[email protected]dd54bd82012-07-19 23:44:573058 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3059 << data.read_count()
[email protected]e3ebba0f2010-08-05 17:59:583060 << " Read index: "
[email protected]dd54bd82012-07-19 23:44:573061 << data.read_index();
3062 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3063 << data.write_count()
[email protected]e3ebba0f2010-08-05 17:59:583064 << " Write index: "
[email protected]dd54bd82012-07-19 23:44:573065 << data.write_index();
[email protected]e3ebba0f2010-08-05 17:59:583066
3067 // Verify the SYN_REPLY.
3068 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503069 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]e3ebba0f2010-08-05 17:59:583070 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3071}
3072
[email protected]513963e2013-06-15 01:53:043073TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
[email protected]cdf8f7e72013-05-23 10:56:463074 scoped_ptr<SpdyFrame> stream1_syn(
3075 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:043076 scoped_ptr<SpdyFrame> stream1_body(
3077 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c10b20852013-05-15 21:29:203078 scoped_ptr<SpdyFrame> stream2_rst(
3079 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM));
[email protected]e3ebba0f2010-08-05 17:59:583080 MockWrite writes[] = {
[email protected]19ec8a72010-08-23 03:38:233081 CreateMockWrite(*stream1_syn, 1),
3082 CreateMockWrite(*stream2_rst, 4),
[email protected]e3ebba0f2010-08-05 17:59:583083 };
3084
[email protected]ff98d7f02012-03-22 21:44:193085 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:043086 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]ff98d7f02012-03-22 21:44:193087 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:043088 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
[email protected]d08358502010-12-03 22:04:033089 0,
3090 2,
3091 9,
3092 "http://www.google.com/foo.dat"));
[email protected]e3ebba0f2010-08-05 17:59:583093 MockRead reads[] = {
[email protected]19ec8a72010-08-23 03:38:233094 CreateMockRead(*stream1_reply, 2),
3095 CreateMockRead(*stream2_syn, 3),
3096 CreateMockRead(*stream1_body, 4),
[email protected]8ddf8322012-02-23 18:08:063097 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:583098 };
3099
[email protected]dd54bd82012-07-19 23:44:573100 OrderedSocketData data(reads, arraysize(reads),
3101 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:363102 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503103 BoundNetLog(), GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:583104
3105 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573106 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:583107
3108 HttpNetworkTransaction* trans = helper.trans();
3109
3110 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:413111 TestCompletionCallback callback;
3112 int rv = trans->Start(
3113 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]e3ebba0f2010-08-05 17:59:583114 EXPECT_EQ(ERR_IO_PENDING, rv);
3115 rv = callback.WaitForResult();
[email protected]e3ebba0f2010-08-05 17:59:583116 EXPECT_EQ(OK, rv);
3117
3118 // Verify that we consumed all test data.
[email protected]dd54bd82012-07-19 23:44:573119 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3120 << data.read_count()
[email protected]e3ebba0f2010-08-05 17:59:583121 << " Read index: "
[email protected]dd54bd82012-07-19 23:44:573122 << data.read_index();
3123 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3124 << data.write_count()
[email protected]e3ebba0f2010-08-05 17:59:583125 << " Write index: "
[email protected]dd54bd82012-07-19 23:44:573126 << data.write_index();
[email protected]e3ebba0f2010-08-05 17:59:583127
3128 // Verify the SYN_REPLY.
3129 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503130 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]e3ebba0f2010-08-05 17:59:583131 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3132}
3133
[email protected]513963e2013-06-15 01:53:043134TEST_P(SpdyNetworkTransactionTest, ServerPushNoURL) {
[email protected]cdf8f7e72013-05-23 10:56:463135 scoped_ptr<SpdyFrame> stream1_syn(
3136 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:043137 scoped_ptr<SpdyFrame> stream1_body(
3138 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]c10b20852013-05-15 21:29:203139 scoped_ptr<SpdyFrame> stream2_rst(
3140 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
[email protected]e3ebba0f2010-08-05 17:59:583141 MockWrite writes[] = {
[email protected]19ec8a72010-08-23 03:38:233142 CreateMockWrite(*stream1_syn, 1),
3143 CreateMockWrite(*stream2_rst, 4),
[email protected]e3ebba0f2010-08-05 17:59:583144 };
3145
[email protected]ff98d7f02012-03-22 21:44:193146 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:043147 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8b9211d2013-06-24 05:54:453148 scoped_ptr<SpdyHeaderBlock> incomplete_headers(new SpdyHeaderBlock());
3149 (*incomplete_headers)["hello"] = "bye";
3150 (*incomplete_headers)[spdy_util_.GetStatusKey()] = "200 OK";
3151 (*incomplete_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
[email protected]0338bc62014-06-20 17:09:563152 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
3153 incomplete_headers.Pass(), 2, 1));
[email protected]e3ebba0f2010-08-05 17:59:583154 MockRead reads[] = {
[email protected]19ec8a72010-08-23 03:38:233155 CreateMockRead(*stream1_reply, 2),
3156 CreateMockRead(*stream2_syn, 3),
3157 CreateMockRead(*stream1_body, 4),
[email protected]8ddf8322012-02-23 18:08:063158 MockRead(ASYNC, ERR_IO_PENDING, 5) // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:583159 };
3160
[email protected]dd54bd82012-07-19 23:44:573161 OrderedSocketData data(reads, arraysize(reads),
3162 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:363163 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503164 BoundNetLog(), GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:583165
3166 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573167 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:583168
3169 HttpNetworkTransaction* trans = helper.trans();
3170
3171 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:413172 TestCompletionCallback callback;
3173 int rv = trans->Start(
3174 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]e3ebba0f2010-08-05 17:59:583175 EXPECT_EQ(ERR_IO_PENDING, rv);
3176 rv = callback.WaitForResult();
[email protected]e3ebba0f2010-08-05 17:59:583177 EXPECT_EQ(OK, rv);
3178 // Verify that we consumed all test data.
[email protected]dd54bd82012-07-19 23:44:573179 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3180 << data.read_count()
[email protected]e3ebba0f2010-08-05 17:59:583181 << " Read index: "
[email protected]dd54bd82012-07-19 23:44:573182 << data.read_index();
3183 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3184 << data.write_count()
[email protected]e3ebba0f2010-08-05 17:59:583185 << " Write index: "
[email protected]dd54bd82012-07-19 23:44:573186 << data.write_index();
[email protected]e3ebba0f2010-08-05 17:59:583187
3188 // Verify the SYN_REPLY.
3189 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503190 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]e3ebba0f2010-08-05 17:59:583191 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3192}
3193
[email protected]8b070372009-11-16 22:01:253194// Verify that various SynReply headers parse correctly through the
3195// HTTP layer.
[email protected]513963e2013-06-15 01:53:043196TEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) {
[email protected]e7f75092010-07-01 22:39:133197 struct SynReplyHeadersTests {
3198 int num_headers;
3199 const char* extra_headers[5];
[email protected]513963e2013-06-15 01:53:043200 SpdyHeaderBlock expected_headers;
[email protected]8b070372009-11-16 22:01:253201 } test_cases[] = {
[email protected]e7f75092010-07-01 22:39:133202 // This uses a multi-valued cookie header.
3203 { 2,
3204 { "cookie", "val1",
3205 "cookie", "val2", // will get appended separated by NULL
3206 NULL
3207 },
[email protected]8b070372009-11-16 22:01:253208 },
[email protected]e7f75092010-07-01 22:39:133209 // This is the minimalist set of headers.
3210 { 0,
3211 { NULL },
[email protected]8b070372009-11-16 22:01:253212 },
[email protected]e7f75092010-07-01 22:39:133213 // Headers with a comma separated list.
3214 { 1,
3215 { "cookie", "val1,val2",
3216 NULL
3217 },
[email protected]8b070372009-11-16 22:01:253218 }
3219 };
3220
[email protected]513963e2013-06-15 01:53:043221 test_cases[0].expected_headers["cookie"] = "val1";
3222 test_cases[0].expected_headers["cookie"] += '\0';
3223 test_cases[0].expected_headers["cookie"] += "val2";
3224 test_cases[0].expected_headers["hello"] = "bye";
3225 test_cases[0].expected_headers["status"] = "200";
[email protected]513963e2013-06-15 01:53:043226
3227 test_cases[1].expected_headers["hello"] = "bye";
3228 test_cases[1].expected_headers["status"] = "200";
[email protected]513963e2013-06-15 01:53:043229
3230 test_cases[2].expected_headers["cookie"] = "val1,val2";
3231 test_cases[2].expected_headers["hello"] = "bye";
3232 test_cases[2].expected_headers["status"] = "200";
[email protected]601e03f12014-04-06 16:26:393233
3234 if (spdy_util_.spdy_version() < SPDY4) {
3235 // SPDY4/HTTP2 eliminates use of the :version header.
3236 test_cases[0].expected_headers["version"] = "HTTP/1.1";
3237 test_cases[1].expected_headers["version"] = "HTTP/1.1";
3238 test_cases[2].expected_headers["version"] = "HTTP/1.1";
3239 }
[email protected]513963e2013-06-15 01:53:043240
viettrungluue4a8b882014-10-16 06:17:383241 for (size_t i = 0; i < arraysize(test_cases); ++i) {
[email protected]ff98d7f02012-03-22 21:44:193242 scoped_ptr<SpdyFrame> req(
[email protected]cdf8f7e72013-05-23 10:56:463243 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]e7f75092010-07-01 22:39:133244 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]8b070372009-11-16 22:01:253245
[email protected]ff98d7f02012-03-22 21:44:193246 scoped_ptr<SpdyFrame> resp(
[email protected]513963e2013-06-15 01:53:043247 spdy_util_.ConstructSpdyGetSynReply(test_cases[i].extra_headers,
[email protected]2bd93022010-07-17 00:58:443248 test_cases[i].num_headers,
3249 1));
[email protected]513963e2013-06-15 01:53:043250 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]8b070372009-11-16 22:01:253251 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133252 CreateMockRead(*resp),
3253 CreateMockRead(*body),
[email protected]8ddf8322012-02-23 18:08:063254 MockRead(ASYNC, 0, 0) // EOF
[email protected]8b070372009-11-16 22:01:253255 };
3256
[email protected]dd54bd82012-07-19 23:44:573257 DelayedSocketData data(1, reads, arraysize(reads),
3258 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:363259 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503260 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573261 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473262 TransactionHelperResult out = helper.output();
3263
[email protected]8b070372009-11-16 22:01:253264 EXPECT_EQ(OK, out.rv);
3265 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3266 EXPECT_EQ("hello!", out.response_data);
3267
3268 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3269 EXPECT_TRUE(headers.get() != NULL);
3270 void* iter = NULL;
[email protected]513963e2013-06-15 01:53:043271 std::string name, value;
3272 SpdyHeaderBlock header_block;
[email protected]8b070372009-11-16 22:01:253273 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
[email protected]513963e2013-06-15 01:53:043274 if (header_block[name].empty()) {
3275 header_block[name] = value;
3276 } else {
3277 header_block[name] += '\0';
3278 header_block[name] += value;
3279 }
[email protected]8b070372009-11-16 22:01:253280 }
[email protected]513963e2013-06-15 01:53:043281 EXPECT_EQ(test_cases[i].expected_headers, header_block);
[email protected]8b070372009-11-16 22:01:253282 }
3283}
3284
[email protected]3f662f12010-03-25 19:56:123285// Verify that various SynReply headers parse vary fields correctly
3286// through the HTTP layer, and the response matches the request.
[email protected]513963e2013-06-15 01:53:043287TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) {
[email protected]3f662f12010-03-25 19:56:123288 // Modify the following data to change/add test cases:
3289 struct SynReplyTests {
[email protected]3f662f12010-03-25 19:56:123290 bool vary_matches;
3291 int num_headers[2];
3292 const char* extra_headers[2][16];
3293 } test_cases[] = {
3294 // Test the case of a multi-valued cookie. When the value is delimited
3295 // with NUL characters, it needs to be unfolded into multiple headers.
3296 {
[email protected]3f662f12010-03-25 19:56:123297 true,
[email protected]8c76ae22010-04-20 22:15:433298 { 1, 4 },
3299 { { "cookie", "val1,val2",
[email protected]3f662f12010-03-25 19:56:123300 NULL
3301 },
[email protected]513963e2013-06-15 01:53:043302 { "vary", "cookie",
3303 spdy_util_.GetStatusKey(), "200",
3304 spdy_util_.GetPathKey(), "/index.php",
3305 spdy_util_.GetVersionKey(), "HTTP/1.1",
[email protected]3f662f12010-03-25 19:56:123306 NULL
3307 }
3308 }
3309 }, { // Multiple vary fields.
[email protected]3f662f12010-03-25 19:56:123310 true,
3311 { 2, 5 },
3312 { { "friend", "barney",
3313 "enemy", "snaggletooth",
3314 NULL
3315 },
[email protected]513963e2013-06-15 01:53:043316 { "vary", "friend",
[email protected]3f662f12010-03-25 19:56:123317 "vary", "enemy",
[email protected]513963e2013-06-15 01:53:043318 spdy_util_.GetStatusKey(), "200",
3319 spdy_util_.GetPathKey(), "/index.php",
3320 spdy_util_.GetVersionKey(), "HTTP/1.1",
[email protected]3f662f12010-03-25 19:56:123321 NULL
3322 }
3323 }
3324 }, { // Test a '*' vary field.
[email protected]3f662f12010-03-25 19:56:123325 false,
3326 { 1, 4 },
3327 { { "cookie", "val1,val2",
3328 NULL
3329 },
[email protected]513963e2013-06-15 01:53:043330 { "vary", "*",
3331 spdy_util_.GetStatusKey(), "200",
3332 spdy_util_.GetPathKey(), "/index.php",
3333 spdy_util_.GetVersionKey(), "HTTP/1.1",
[email protected]3f662f12010-03-25 19:56:123334 NULL
3335 }
3336 }
3337 }, { // Multiple comma-separated vary fields.
[email protected]3f662f12010-03-25 19:56:123338 true,
3339 { 2, 4 },
3340 { { "friend", "barney",
3341 "enemy", "snaggletooth",
3342 NULL
3343 },
[email protected]513963e2013-06-15 01:53:043344 { "vary", "friend,enemy",
3345 spdy_util_.GetStatusKey(), "200",
3346 spdy_util_.GetPathKey(), "/index.php",
3347 spdy_util_.GetVersionKey(), "HTTP/1.1",
[email protected]3f662f12010-03-25 19:56:123348 NULL
3349 }
3350 }
3351 }
3352 };
3353
viettrungluue4a8b882014-10-16 06:17:383354 for (size_t i = 0; i < arraysize(test_cases); ++i) {
[email protected]3f662f12010-03-25 19:56:123355 // Construct the request.
[email protected]ff98d7f02012-03-22 21:44:193356 scoped_ptr<SpdyFrame> frame_req(
[email protected]cdf8f7e72013-05-23 10:56:463357 spdy_util_.ConstructSpdyGet(test_cases[i].extra_headers[0],
3358 test_cases[i].num_headers[0],
3359 false, 1, LOWEST, true));
[email protected]3f662f12010-03-25 19:56:123360
3361 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:133362 CreateMockWrite(*frame_req),
[email protected]3f662f12010-03-25 19:56:123363 };
3364
3365 // Construct the reply.
[email protected]745aa9c2014-06-27 02:21:293366 SpdyHeaderBlock reply_headers;
3367 AppendToHeaderBlock(test_cases[i].extra_headers[1],
3368 test_cases[i].num_headers[1],
3369 &reply_headers);
[email protected]ff98d7f02012-03-22 21:44:193370 scoped_ptr<SpdyFrame> frame_reply(
[email protected]745aa9c2014-06-27 02:21:293371 spdy_util_.ConstructSpdyReply(1, reply_headers));
[email protected]3f662f12010-03-25 19:56:123372
[email protected]513963e2013-06-15 01:53:043373 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]3f662f12010-03-25 19:56:123374 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133375 CreateMockRead(*frame_reply),
3376 CreateMockRead(*body),
[email protected]8ddf8322012-02-23 18:08:063377 MockRead(ASYNC, 0, 0) // EOF
[email protected]3f662f12010-03-25 19:56:123378 };
3379
[email protected]3f662f12010-03-25 19:56:123380 // Attach the headers to the request.
[email protected]8c76ae22010-04-20 22:15:433381 int header_count = test_cases[i].num_headers[0];
[email protected]3f662f12010-03-25 19:56:123382
[email protected]d3cee19d2010-06-22 18:42:183383 HttpRequestInfo request = CreateGetRequest();
[email protected]8c76ae22010-04-20 22:15:433384 for (int ct = 0; ct < header_count; ct++) {
3385 const char* header_key = test_cases[i].extra_headers[0][ct * 2];
3386 const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1];
3387 request.extra_headers.SetHeader(header_key, header_value);
[email protected]3f662f12010-03-25 19:56:123388 }
3389
[email protected]dd54bd82012-07-19 23:44:573390 DelayedSocketData data(1, reads, arraysize(reads),
3391 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:363392 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503393 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573394 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473395 TransactionHelperResult out = helper.output();
3396
[email protected]3f662f12010-03-25 19:56:123397 EXPECT_EQ(OK, out.rv) << i;
3398 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line) << i;
3399 EXPECT_EQ("hello!", out.response_data) << i;
3400
3401 // Test the response information.
3402 EXPECT_TRUE(out.response_info.response_time >
3403 out.response_info.request_time) << i;
3404 base::TimeDelta test_delay = out.response_info.response_time -
3405 out.response_info.request_time;
3406 base::TimeDelta min_expected_delay;
3407 min_expected_delay.FromMilliseconds(10);
3408 EXPECT_GT(test_delay.InMillisecondsF(),
3409 min_expected_delay.InMillisecondsF()) << i;
3410 EXPECT_EQ(out.response_info.vary_data.is_valid(),
3411 test_cases[i].vary_matches) << i;
3412
3413 // Check the headers.
3414 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3415 ASSERT_TRUE(headers.get() != NULL) << i;
3416 void* iter = NULL;
3417 std::string name, value, lines;
3418 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3419 lines.append(name);
3420 lines.append(": ");
3421 lines.append(value);
3422 lines.append("\n");
3423 }
3424
3425 // Construct the expected header reply string.
[email protected]9aa323192013-05-31 21:38:403426 std::string expected_reply =
3427 spdy_util_.ConstructSpdyReplyString(reply_headers);
3428 EXPECT_EQ(expected_reply, lines) << i;
[email protected]3f662f12010-03-25 19:56:123429 }
3430}
3431
[email protected]dd11b932009-11-30 19:39:483432// Verify that we don't crash on invalid SynReply responses.
[email protected]513963e2013-06-15 01:53:043433TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) {
[email protected]e7f75092010-07-01 22:39:133434 struct InvalidSynReplyTests {
3435 int num_headers;
3436 const char* headers[10];
[email protected]dd11b932009-11-30 19:39:483437 } test_cases[] = {
[email protected]e7f75092010-07-01 22:39:133438 // SYN_REPLY missing status header
3439 { 4,
3440 { "cookie", "val1",
3441 "cookie", "val2",
[email protected]513963e2013-06-15 01:53:043442 spdy_util_.GetPathKey(), "/index.php",
3443 spdy_util_.GetVersionKey(), "HTTP/1.1",
[email protected]e7f75092010-07-01 22:39:133444 NULL
3445 },
3446 },
3447 // SYN_REPLY missing version header
3448 { 2,
[email protected]513963e2013-06-15 01:53:043449 { "status", "200",
3450 spdy_util_.GetPathKey(), "/index.php",
[email protected]e7f75092010-07-01 22:39:133451 NULL
3452 },
3453 },
[email protected]0d384bb2010-07-14 01:51:123454 // SYN_REPLY with no headers
3455 { 0, { NULL }, },
[email protected]dd11b932009-11-30 19:39:483456 };
3457
viettrungluue4a8b882014-10-16 06:17:383458 for (size_t i = 0; i < arraysize(test_cases); ++i) {
[email protected]ff98d7f02012-03-22 21:44:193459 scoped_ptr<SpdyFrame> req(
[email protected]cdf8f7e72013-05-23 10:56:463460 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]b771bb72013-06-24 09:55:413461 scoped_ptr<SpdyFrame> rst(
3462 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
[email protected]dd11b932009-11-30 19:39:483463 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:133464 CreateMockWrite(*req),
[email protected]b771bb72013-06-24 09:55:413465 CreateMockWrite(*rst),
[email protected]dd11b932009-11-30 19:39:483466 };
3467
[email protected]745aa9c2014-06-27 02:21:293468 // Construct the reply.
3469 SpdyHeaderBlock reply_headers;
3470 AppendToHeaderBlock(
3471 test_cases[i].headers, test_cases[i].num_headers, &reply_headers);
3472 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyReply(1, reply_headers));
[email protected]dd11b932009-11-30 19:39:483473 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133474 CreateMockRead(*resp),
[email protected]8ddf8322012-02-23 18:08:063475 MockRead(ASYNC, 0, 0) // EOF
[email protected]dd11b932009-11-30 19:39:483476 };
3477
[email protected]dd54bd82012-07-19 23:44:573478 DelayedSocketData data(1, reads, arraysize(reads),
3479 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:363480 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503481 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573482 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473483 TransactionHelperResult out = helper.output();
[email protected]b771bb72013-06-24 09:55:413484 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]dd11b932009-11-30 19:39:483485 }
3486}
3487
[email protected]94d78132010-01-22 00:53:003488// Verify that we don't crash on some corrupt frames.
[email protected]e3352df2014-03-19 05:55:423489// TODO(jgraettinger): SPDY4 and up treats a header decompression failure as a
3490// connection error. I'd like to backport this behavior to SPDY3 as well.
[email protected]513963e2013-06-15 01:53:043491TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
[email protected]e3352df2014-03-19 05:55:423492 if (spdy_util_.spdy_version() >= SPDY4) {
3493 return;
3494 }
[email protected]61c83f782011-01-27 21:00:243495 // This is the length field that's too short.
[email protected]ff98d7f02012-03-22 21:44:193496 scoped_ptr<SpdyFrame> syn_reply_wrong_length(
[email protected]513963e2013-06-15 01:53:043497 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:043498 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]8a0fc822013-06-27 20:52:433499 size_t right_size =
3500 (spdy_util_.spdy_version() < SPDY4) ?
3501 syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize() :
3502 syn_reply_wrong_length->size();
3503 size_t wrong_size = right_size - 4;
[email protected]a4bfdf72013-02-22 04:06:163504 test::SetFrameLength(syn_reply_wrong_length.get(),
[email protected]8a0fc822013-06-27 20:52:433505 wrong_size,
[email protected]513963e2013-06-15 01:53:043506 spdy_util_.spdy_version());
[email protected]94d78132010-01-22 00:53:003507
3508 struct SynReplyTests {
[email protected]ff98d7f02012-03-22 21:44:193509 const SpdyFrame* syn_reply;
[email protected]94d78132010-01-22 00:53:003510 } test_cases[] = {
[email protected]61c83f782011-01-27 21:00:243511 { syn_reply_wrong_length.get(), },
[email protected]94d78132010-01-22 00:53:003512 };
3513
viettrungluue4a8b882014-10-16 06:17:383514 for (size_t i = 0; i < arraysize(test_cases); ++i) {
[email protected]ff98d7f02012-03-22 21:44:193515 scoped_ptr<SpdyFrame> req(
[email protected]cdf8f7e72013-05-23 10:56:463516 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]099bc7e2013-07-18 04:19:163517 scoped_ptr<SpdyFrame> rst(
3518 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
3519 MockWrite writes[] = {
3520 CreateMockWrite(*req),
3521 CreateMockWrite(*rst),
[email protected]94d78132010-01-22 00:53:003522 };
3523
[email protected]513963e2013-06-15 01:53:043524 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]94d78132010-01-22 00:53:003525 MockRead reads[] = {
[email protected]d1918d62013-02-26 10:18:013526 MockRead(ASYNC, test_cases[i].syn_reply->data(), wrong_size),
[email protected]e7f75092010-07-01 22:39:133527 CreateMockRead(*body),
[email protected]8ddf8322012-02-23 18:08:063528 MockRead(ASYNC, 0, 0) // EOF
[email protected]94d78132010-01-22 00:53:003529 };
3530
[email protected]dd54bd82012-07-19 23:44:573531 DelayedSocketData data(1, reads, arraysize(reads),
3532 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:363533 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503534 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573535 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473536 TransactionHelperResult out = helper.output();
[email protected]955fc2e72010-02-08 20:37:303537 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]94d78132010-01-22 00:53:003538 }
3539}
3540
[email protected]e3352df2014-03-19 05:55:423541// SPDY4 treats a header decompression failure as a connection-level error.
3542TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionErrorSpdy4) {
3543 if (spdy_util_.spdy_version() < SPDY4) {
3544 return;
3545 }
3546 // This is the length field that's too short.
3547 scoped_ptr<SpdyFrame> syn_reply_wrong_length(
3548 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3549 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3550 size_t right_size =
[email protected]c143f2742014-03-31 00:48:543551 syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize();
[email protected]e3352df2014-03-19 05:55:423552 size_t wrong_size = right_size - 4;
3553 test::SetFrameLength(syn_reply_wrong_length.get(),
3554 wrong_size,
3555 spdy_util_.spdy_version());
3556
[email protected]e3352df2014-03-19 05:55:423557 scoped_ptr<SpdyFrame> req(
3558 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]bdd1b222014-06-10 11:08:393559 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3560 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3561 MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*goaway)};
[email protected]e3352df2014-03-19 05:55:423562
3563 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3564 MockRead reads[] = {
[email protected]c143f2742014-03-31 00:48:543565 MockRead(ASYNC, syn_reply_wrong_length->data(),
3566 syn_reply_wrong_length->size() - 4),
[email protected]e3352df2014-03-19 05:55:423567 };
3568
3569 DelayedSocketData data(1, reads, arraysize(reads),
3570 writes, arraysize(writes));
3571 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3572 BoundNetLog(), GetParam(), NULL);
3573 helper.RunToCompletion(&data);
3574 TransactionHelperResult out = helper.output();
[email protected]bdd1b222014-06-10 11:08:393575 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
3576}
3577
3578TEST_P(SpdyNetworkTransactionTest, GoAwayOnDecompressionFailure) {
3579 if (GetParam().protocol < kProtoSPDY4) {
3580 // Decompression failures are a stream error in SPDY3 and above.
3581 return;
3582 }
3583 scoped_ptr<SpdyFrame> req(
3584 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3585 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3586 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3587 MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*goaway)};
3588
3589 // Read HEADERS with corrupted payload.
3590 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3591 memset(resp->data() + 12, 0xff, resp->size() - 12);
3592 MockRead reads[] = {CreateMockRead(*resp)};
3593
3594 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
3595 NormalSpdyTransactionHelper helper(
3596 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
3597 helper.RunToCompletion(&data);
3598 TransactionHelperResult out = helper.output();
3599 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
3600}
3601
3602TEST_P(SpdyNetworkTransactionTest, GoAwayOnFrameSizeError) {
3603 scoped_ptr<SpdyFrame> req(
3604 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3605 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3606 0, GOAWAY_PROTOCOL_ERROR, "Framer error: 1 (INVALID_CONTROL_FRAME)."));
3607 MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*goaway)};
3608
3609 // Read WINDOW_UPDATE with incorrectly-sized payload.
3610 // TODO(jgraettinger): SpdyFramer signals this as an INVALID_CONTROL_FRAME,
3611 // which is mapped to a protocol error, and not a frame size error.
3612 scoped_ptr<SpdyFrame> bad_window_update(
3613 spdy_util_.ConstructSpdyWindowUpdate(1, 1));
3614 test::SetFrameLength(bad_window_update.get(),
3615 bad_window_update->size() - 1,
3616 spdy_util_.spdy_version());
3617 MockRead reads[] = {CreateMockRead(*bad_window_update)};
3618
3619 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
3620 NormalSpdyTransactionHelper helper(
3621 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
3622 helper.RunToCompletion(&data);
3623 TransactionHelperResult out = helper.output();
[email protected]e3352df2014-03-19 05:55:423624 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3625}
3626
[email protected]bf2491a92009-11-29 16:39:483627// Test that we shutdown correctly on write errors.
[email protected]513963e2013-06-15 01:53:043628TEST_P(SpdyNetworkTransactionTest, WriteError) {
[email protected]cdf8f7e72013-05-23 10:56:463629 scoped_ptr<SpdyFrame> req(
3630 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]bf2491a92009-11-29 16:39:483631 MockWrite writes[] = {
[email protected]bdd1b222014-06-10 11:08:393632 // We'll write 10 bytes successfully
3633 MockWrite(ASYNC, req->data(), 10, 0),
3634 // Followed by ERROR!
3635 MockWrite(ASYNC, ERR_FAILED, 1),
3636 // Session drains and attempts to write a GOAWAY: Another ERROR!
3637 MockWrite(ASYNC, ERR_FAILED, 2),
[email protected]bf2491a92009-11-29 16:39:483638 };
3639
[email protected]238002d2013-10-17 02:01:403640 MockRead reads[] = {
[email protected]bdd1b222014-06-10 11:08:393641 MockRead(ASYNC, 0, 3) // EOF
[email protected]238002d2013-10-17 02:01:403642 };
3643
3644 DeterministicSocketData data(reads, arraysize(reads),
3645 writes, arraysize(writes));
3646
[email protected]262eec82013-03-19 21:01:363647 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503648 BoundNetLog(), GetParam(), NULL);
[email protected]238002d2013-10-17 02:01:403649 helper.SetDeterministic();
3650 helper.RunPreTestSetup();
3651 helper.AddDeterministicData(&data);
3652 EXPECT_TRUE(helper.StartDefaultTest());
3653 data.RunFor(2);
3654 helper.FinishDefaultTest();
3655 EXPECT_TRUE(data.at_write_eof());
3656 EXPECT_TRUE(!data.at_read_eof());
[email protected]3caf5542010-07-16 15:19:473657 TransactionHelperResult out = helper.output();
[email protected]bf2491a92009-11-29 16:39:483658 EXPECT_EQ(ERR_FAILED, out.rv);
3659}
3660
3661// Test that partial writes work.
[email protected]513963e2013-06-15 01:53:043662TEST_P(SpdyNetworkTransactionTest, PartialWrite) {
[email protected]bf2491a92009-11-29 16:39:483663 // Chop the SYN_STREAM frame into 5 chunks.
[email protected]cdf8f7e72013-05-23 10:56:463664 scoped_ptr<SpdyFrame> req(
3665 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]bf2491a92009-11-29 16:39:483666 const int kChunks = 5;
[email protected]4356f0f2013-04-07 00:58:173667 scoped_ptr<MockWrite[]> writes(ChopWriteFrame(*req.get(), kChunks));
[email protected]bf2491a92009-11-29 16:39:483668
[email protected]513963e2013-06-15 01:53:043669 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3670 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]bf2491a92009-11-29 16:39:483671 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133672 CreateMockRead(*resp),
3673 CreateMockRead(*body),
[email protected]8ddf8322012-02-23 18:08:063674 MockRead(ASYNC, 0, 0) // EOF
[email protected]bf2491a92009-11-29 16:39:483675 };
3676
[email protected]dd54bd82012-07-19 23:44:573677 DelayedSocketData data(kChunks, reads, arraysize(reads),
3678 writes.get(), kChunks);
[email protected]262eec82013-03-19 21:01:363679 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503680 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573681 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473682 TransactionHelperResult out = helper.output();
[email protected]bf2491a92009-11-29 16:39:483683 EXPECT_EQ(OK, out.rv);
3684 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3685 EXPECT_EQ("hello!", out.response_data);
3686}
3687
[email protected]94d78132010-01-22 00:53:003688// In this test, we enable compression, but get a uncompressed SynReply from
3689// the server. Verify that teardown is all clean.
[email protected]513963e2013-06-15 01:53:043690TEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) {
[email protected]e3352df2014-03-19 05:55:423691 if (spdy_util_.spdy_version() >= SPDY4) {
3692 // HPACK doesn't use deflate compression.
3693 return;
3694 }
[email protected]ff98d7f02012-03-22 21:44:193695 scoped_ptr<SpdyFrame> compressed(
[email protected]cdf8f7e72013-05-23 10:56:463696 spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, LOWEST, true));
[email protected]bdd1b222014-06-10 11:08:393697 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3698 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3699 MockWrite writes[] = {CreateMockWrite(*compressed), CreateMockWrite(*goaway)};
[email protected]94d78132010-01-22 00:53:003700
[email protected]513963e2013-06-15 01:53:043701 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3702 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]94d78132010-01-22 00:53:003703 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133704 CreateMockRead(*resp),
[email protected]94d78132010-01-22 00:53:003705 };
3706
[email protected]dd54bd82012-07-19 23:44:573707 DelayedSocketData data(1, reads, arraysize(reads),
3708 writes, arraysize(writes));
[email protected]513963e2013-06-15 01:53:043709 SpdySessionDependencies* session_deps =
3710 CreateSpdySessionDependencies(GetParam());
[email protected]f9cf5572012-12-04 15:52:093711 session_deps->enable_compression = true;
[email protected]262eec82013-03-19 21:01:363712 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]f9cf5572012-12-04 15:52:093713 BoundNetLog(), GetParam(), session_deps);
[email protected]dd54bd82012-07-19 23:44:573714 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473715 TransactionHelperResult out = helper.output();
[email protected]bdd1b222014-06-10 11:08:393716 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
[email protected]dd54bd82012-07-19 23:44:573717 data.Reset();
[email protected]94d78132010-01-22 00:53:003718}
3719
[email protected]9e743cd2010-03-16 07:03:533720// Test that the NetLog contains good data for a simple GET request.
[email protected]513963e2013-06-15 01:53:043721TEST_P(SpdyNetworkTransactionTest, NetLog) {
[email protected]3deb9a52010-11-11 00:24:403722 static const char* const kExtraHeaders[] = {
3723 "user-agent", "Chrome",
3724 };
[email protected]cdf8f7e72013-05-23 10:56:463725 scoped_ptr<SpdyFrame> req(
3726 spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, false, 1, LOWEST, true));
[email protected]e7f75092010-07-01 22:39:133727 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]dac358042009-12-18 02:07:483728
[email protected]513963e2013-06-15 01:53:043729 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3730 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]dac358042009-12-18 02:07:483731 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133732 CreateMockRead(*resp),
3733 CreateMockRead(*body),
[email protected]8ddf8322012-02-23 18:08:063734 MockRead(ASYNC, 0, 0) // EOF
[email protected]dac358042009-12-18 02:07:483735 };
3736
[email protected]333bdf62012-06-08 22:57:293737 CapturingBoundNetLog log;
[email protected]dac358042009-12-18 02:07:483738
[email protected]dd54bd82012-07-19 23:44:573739 DelayedSocketData data(1, reads, arraysize(reads),
3740 writes, arraysize(writes));
[email protected]3deb9a52010-11-11 00:24:403741 NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(),
[email protected]262eec82013-03-19 21:01:363742 DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503743 log.bound(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:573744 helper.RunToCompletion(&data);
[email protected]3caf5542010-07-16 15:19:473745 TransactionHelperResult out = helper.output();
[email protected]dac358042009-12-18 02:07:483746 EXPECT_EQ(OK, out.rv);
3747 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3748 EXPECT_EQ("hello!", out.response_data);
3749
[email protected]9e743cd2010-03-16 07:03:533750 // Check that the NetLog was filled reasonably.
[email protected]3caf5542010-07-16 15:19:473751 // This test is intentionally non-specific about the exact ordering of the
3752 // log; instead we just check to make sure that certain events exist, and that
3753 // they are in the right order.
[email protected]f3da152d2012-06-02 01:00:573754 net::CapturingNetLog::CapturedEntryList entries;
[email protected]b2fcd0e2010-12-01 15:19:403755 log.GetEntries(&entries);
3756
3757 EXPECT_LT(0u, entries.size());
[email protected]dac358042009-12-18 02:07:483758 int pos = 0;
[email protected]b2fcd0e2010-12-01 15:19:403759 pos = net::ExpectLogContainsSomewhere(entries, 0,
[email protected]351ab642010-08-05 16:55:313760 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
[email protected]9e743cd2010-03-16 07:03:533761 net::NetLog::PHASE_BEGIN);
[email protected]b2fcd0e2010-12-01 15:19:403762 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
[email protected]351ab642010-08-05 16:55:313763 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
[email protected]9e743cd2010-03-16 07:03:533764 net::NetLog::PHASE_END);
[email protected]b2fcd0e2010-12-01 15:19:403765 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
[email protected]351ab642010-08-05 16:55:313766 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
[email protected]9e743cd2010-03-16 07:03:533767 net::NetLog::PHASE_BEGIN);
[email protected]b2fcd0e2010-12-01 15:19:403768 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
[email protected]351ab642010-08-05 16:55:313769 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
[email protected]9e743cd2010-03-16 07:03:533770 net::NetLog::PHASE_END);
[email protected]b2fcd0e2010-12-01 15:19:403771 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
[email protected]351ab642010-08-05 16:55:313772 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
[email protected]9e743cd2010-03-16 07:03:533773 net::NetLog::PHASE_BEGIN);
[email protected]b2fcd0e2010-12-01 15:19:403774 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
[email protected]351ab642010-08-05 16:55:313775 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
[email protected]9e743cd2010-03-16 07:03:533776 net::NetLog::PHASE_END);
[email protected]3deb9a52010-11-11 00:24:403777
3778 // Check that we logged all the headers correctly
3779 pos = net::ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403780 entries, 0,
[email protected]3deb9a52010-11-11 00:24:403781 net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM,
3782 net::NetLog::PHASE_NONE);
[email protected]3deb9a52010-11-11 00:24:403783
[email protected]ea5ef4c2013-06-13 22:50:273784 base::ListValue* header_list;
[email protected]f3da152d2012-06-02 01:00:573785 ASSERT_TRUE(entries[pos].params.get());
3786 ASSERT_TRUE(entries[pos].params->GetList("headers", &header_list));
3787
3788 std::vector<std::string> expected;
[email protected]513963e2013-06-15 01:53:043789 expected.push_back(std::string(spdy_util_.GetHostKey()) + ": www.google.com");
3790 expected.push_back(std::string(spdy_util_.GetPathKey()) + ": /");
3791 expected.push_back(std::string(spdy_util_.GetSchemeKey()) + ": http");
[email protected]513963e2013-06-15 01:53:043792 expected.push_back(std::string(spdy_util_.GetMethodKey()) + ": GET");
[email protected]f3da152d2012-06-02 01:00:573793 expected.push_back("user-agent: Chrome");
[email protected]601e03f12014-04-06 16:26:393794 if (spdy_util_.spdy_version() < SPDY4) {
3795 // SPDY4/HTTP2 eliminates use of the :version header.
3796 expected.push_back(std::string(spdy_util_.GetVersionKey()) + ": HTTP/1.1");
3797 }
[email protected]f3da152d2012-06-02 01:00:573798 EXPECT_EQ(expected.size(), header_list->GetSize());
3799 for (std::vector<std::string>::const_iterator it = expected.begin();
3800 it != expected.end();
3801 ++it) {
3802 base::StringValue header(*it);
3803 EXPECT_NE(header_list->end(), header_list->Find(header)) <<
3804 "Header not found: " << *it;
[email protected]3deb9a52010-11-11 00:24:403805 }
[email protected]dac358042009-12-18 02:07:483806}
3807
[email protected]79d84222010-02-26 00:01:443808// Since we buffer the IO from the stream to the renderer, this test verifies
3809// that when we read out the maximum amount of data (e.g. we received 50 bytes
3810// on the network, but issued a Read for only 5 of those bytes) that the data
3811// flow still works correctly.
[email protected]513963e2013-06-15 01:53:043812TEST_P(SpdyNetworkTransactionTest, BufferFull) {
[email protected]513963e2013-06-15 01:53:043813 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]20d005f2010-07-02 19:55:433814
[email protected]cdf8f7e72013-05-23 10:56:463815 scoped_ptr<SpdyFrame> req(
3816 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]e7f75092010-07-01 22:39:133817 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]79d84222010-02-26 00:01:443818
[email protected]20d005f2010-07-02 19:55:433819 // 2 data frames in a single read.
[email protected]ff98d7f02012-03-22 21:44:193820 scoped_ptr<SpdyFrame> data_frame_1(
3821 framer.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE));
3822 scoped_ptr<SpdyFrame> data_frame_2(
3823 framer.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE));
3824 const SpdyFrame* data_frames[2] = {
[email protected]20d005f2010-07-02 19:55:433825 data_frame_1.get(),
3826 data_frame_2.get(),
[email protected]79d84222010-02-26 00:01:443827 };
[email protected]20d005f2010-07-02 19:55:433828 char combined_data_frames[100];
3829 int combined_data_frames_len =
3830 CombineFrames(data_frames, arraysize(data_frames),
3831 combined_data_frames, arraysize(combined_data_frames));
[email protected]ff98d7f02012-03-22 21:44:193832 scoped_ptr<SpdyFrame> last_frame(
3833 framer.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN));
[email protected]79d84222010-02-26 00:01:443834
[email protected]513963e2013-06-15 01:53:043835 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]79d84222010-02-26 00:01:443836 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133837 CreateMockRead(*resp),
[email protected]8ddf8322012-02-23 18:08:063838 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3839 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
3840 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
[email protected]20d005f2010-07-02 19:55:433841 CreateMockRead(*last_frame),
[email protected]8ddf8322012-02-23 18:08:063842 MockRead(ASYNC, 0, 0) // EOF
[email protected]79d84222010-02-26 00:01:443843 };
3844
[email protected]dd54bd82012-07-19 23:44:573845 DelayedSocketData data(1, reads, arraysize(reads),
3846 writes, arraysize(writes));
[email protected]79d84222010-02-26 00:01:443847
[email protected]49639fa2011-12-20 23:22:413848 TestCompletionCallback callback;
[email protected]79d84222010-02-26 00:01:443849
[email protected]262eec82013-03-19 21:01:363850 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503851 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:473852 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573853 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473854 HttpNetworkTransaction* trans = helper.trans();
[email protected]49639fa2011-12-20 23:22:413855 int rv = trans->Start(
3856 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]79d84222010-02-26 00:01:443857 EXPECT_EQ(ERR_IO_PENDING, rv);
3858
[email protected]3caf5542010-07-16 15:19:473859 TransactionHelperResult out = helper.output();
[email protected]79d84222010-02-26 00:01:443860 out.rv = callback.WaitForResult();
3861 EXPECT_EQ(out.rv, OK);
3862
3863 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503864 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]79d84222010-02-26 00:01:443865 EXPECT_TRUE(response->was_fetched_via_spdy);
3866 out.status_line = response->headers->GetStatusLine();
3867 out.response_info = *response; // Make a copy so we can verify.
3868
3869 // Read Data
[email protected]49639fa2011-12-20 23:22:413870 TestCompletionCallback read_callback;
[email protected]79d84222010-02-26 00:01:443871
3872 std::string content;
3873 do {
3874 // Read small chunks at a time.
3875 const int kSmallReadSize = 3;
[email protected]ad8e04a2010-11-01 04:16:273876 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503877 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
[email protected]79d84222010-02-26 00:01:443878 if (rv == net::ERR_IO_PENDING) {
[email protected]dd54bd82012-07-19 23:44:573879 data.CompleteRead();
[email protected]79d84222010-02-26 00:01:443880 rv = read_callback.WaitForResult();
3881 }
3882 if (rv > 0) {
3883 content.append(buf->data(), rv);
3884 } else if (rv < 0) {
3885 NOTREACHED();
3886 }
3887 } while (rv > 0);
3888
3889 out.response_data.swap(content);
3890
[email protected]30c942b2010-07-21 16:59:593891 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553892 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173893 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553894
[email protected]79d84222010-02-26 00:01:443895 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473896 helper.VerifyDataConsumed();
[email protected]79d84222010-02-26 00:01:443897
3898 EXPECT_EQ(OK, out.rv);
3899 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3900 EXPECT_EQ("goodbye world", out.response_data);
3901}
3902
[email protected]8918d282010-03-02 00:57:553903// Verify that basic buffering works; when multiple data frames arrive
3904// at the same time, ensure that we don't notify a read completion for
3905// each data frame individually.
[email protected]513963e2013-06-15 01:53:043906TEST_P(SpdyNetworkTransactionTest, Buffering) {
[email protected]513963e2013-06-15 01:53:043907 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]20d005f2010-07-02 19:55:433908
[email protected]cdf8f7e72013-05-23 10:56:463909 scoped_ptr<SpdyFrame> req(
3910 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]e7f75092010-07-01 22:39:133911 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]8918d282010-03-02 00:57:553912
3913 // 4 data frames in a single read.
[email protected]ff98d7f02012-03-22 21:44:193914 scoped_ptr<SpdyFrame> data_frame(
3915 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
3916 scoped_ptr<SpdyFrame> data_frame_fin(
3917 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
3918 const SpdyFrame* data_frames[4] = {
[email protected]20d005f2010-07-02 19:55:433919 data_frame.get(),
3920 data_frame.get(),
3921 data_frame.get(),
3922 data_frame_fin.get()
[email protected]8918d282010-03-02 00:57:553923 };
[email protected]20d005f2010-07-02 19:55:433924 char combined_data_frames[100];
3925 int combined_data_frames_len =
3926 CombineFrames(data_frames, arraysize(data_frames),
3927 combined_data_frames, arraysize(combined_data_frames));
[email protected]8918d282010-03-02 00:57:553928
[email protected]513963e2013-06-15 01:53:043929 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8918d282010-03-02 00:57:553930 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133931 CreateMockRead(*resp),
[email protected]8ddf8322012-02-23 18:08:063932 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3933 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
3934 MockRead(ASYNC, 0, 0) // EOF
[email protected]8918d282010-03-02 00:57:553935 };
3936
[email protected]dd54bd82012-07-19 23:44:573937 DelayedSocketData data(1, reads, arraysize(reads),
3938 writes, arraysize(writes));
[email protected]8918d282010-03-02 00:57:553939
[email protected]262eec82013-03-19 21:01:363940 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:503941 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:473942 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:573943 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:473944 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:553945
[email protected]49639fa2011-12-20 23:22:413946 TestCompletionCallback callback;
3947 int rv = trans->Start(
3948 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]8918d282010-03-02 00:57:553949 EXPECT_EQ(ERR_IO_PENDING, rv);
3950
[email protected]3caf5542010-07-16 15:19:473951 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:553952 out.rv = callback.WaitForResult();
3953 EXPECT_EQ(out.rv, OK);
3954
3955 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:503956 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]8918d282010-03-02 00:57:553957 EXPECT_TRUE(response->was_fetched_via_spdy);
3958 out.status_line = response->headers->GetStatusLine();
3959 out.response_info = *response; // Make a copy so we can verify.
3960
3961 // Read Data
[email protected]49639fa2011-12-20 23:22:413962 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:553963
3964 std::string content;
3965 int reads_completed = 0;
3966 do {
3967 // Read small chunks at a time.
3968 const int kSmallReadSize = 14;
[email protected]ad8e04a2010-11-01 04:16:273969 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:503970 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
[email protected]8918d282010-03-02 00:57:553971 if (rv == net::ERR_IO_PENDING) {
[email protected]dd54bd82012-07-19 23:44:573972 data.CompleteRead();
[email protected]8918d282010-03-02 00:57:553973 rv = read_callback.WaitForResult();
3974 }
3975 if (rv > 0) {
3976 EXPECT_EQ(kSmallReadSize, rv);
3977 content.append(buf->data(), rv);
3978 } else if (rv < 0) {
3979 FAIL() << "Unexpected read error: " << rv;
3980 }
3981 reads_completed++;
3982 } while (rv > 0);
3983
3984 EXPECT_EQ(3, reads_completed); // Reads are: 14 bytes, 14 bytes, 0 bytes.
3985
3986 out.response_data.swap(content);
3987
[email protected]30c942b2010-07-21 16:59:593988 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553989 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:173990 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:553991
3992 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473993 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:553994
3995 EXPECT_EQ(OK, out.rv);
3996 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3997 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3998}
3999
4000// Verify the case where we buffer data but read it after it has been buffered.
[email protected]513963e2013-06-15 01:53:044001TEST_P(SpdyNetworkTransactionTest, BufferedAll) {
[email protected]513963e2013-06-15 01:53:044002 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]20d005f2010-07-02 19:55:434003
[email protected]cdf8f7e72013-05-23 10:56:464004 scoped_ptr<SpdyFrame> req(
4005 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]e7f75092010-07-01 22:39:134006 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]8918d282010-03-02 00:57:554007
[email protected]20d005f2010-07-02 19:55:434008 // 5 data frames in a single read.
[email protected]745aa9c2014-06-27 02:21:294009 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]ff98d7f02012-03-22 21:44:194010 scoped_ptr<SpdyFrame> data_frame(
4011 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4012 scoped_ptr<SpdyFrame> data_frame_fin(
4013 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
[email protected]745aa9c2014-06-27 02:21:294014 const SpdyFrame* frames[5] = {reply.get(), data_frame.get(), data_frame.get(),
4015 data_frame.get(), data_frame_fin.get()};
[email protected]20d005f2010-07-02 19:55:434016 char combined_frames[200];
4017 int combined_frames_len =
4018 CombineFrames(frames, arraysize(frames),
4019 combined_frames, arraysize(combined_frames));
[email protected]8918d282010-03-02 00:57:554020
4021 MockRead reads[] = {
[email protected]8ddf8322012-02-23 18:08:064022 MockRead(ASYNC, combined_frames, combined_frames_len),
4023 MockRead(ASYNC, 0, 0) // EOF
[email protected]8918d282010-03-02 00:57:554024 };
4025
[email protected]dd54bd82012-07-19 23:44:574026 DelayedSocketData data(1, reads, arraysize(reads),
4027 writes, arraysize(writes));
[email protected]8918d282010-03-02 00:57:554028
[email protected]262eec82013-03-19 21:01:364029 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504030 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:474031 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574032 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:474033 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:554034
[email protected]49639fa2011-12-20 23:22:414035 TestCompletionCallback callback;
4036 int rv = trans->Start(
4037 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]8918d282010-03-02 00:57:554038 EXPECT_EQ(ERR_IO_PENDING, rv);
4039
[email protected]3caf5542010-07-16 15:19:474040 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:554041 out.rv = callback.WaitForResult();
4042 EXPECT_EQ(out.rv, OK);
4043
4044 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:504045 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]8918d282010-03-02 00:57:554046 EXPECT_TRUE(response->was_fetched_via_spdy);
4047 out.status_line = response->headers->GetStatusLine();
4048 out.response_info = *response; // Make a copy so we can verify.
4049
4050 // Read Data
[email protected]49639fa2011-12-20 23:22:414051 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:554052
4053 std::string content;
4054 int reads_completed = 0;
4055 do {
4056 // Read small chunks at a time.
4057 const int kSmallReadSize = 14;
[email protected]ad8e04a2010-11-01 04:16:274058 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:504059 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
[email protected]8918d282010-03-02 00:57:554060 if (rv > 0) {
4061 EXPECT_EQ(kSmallReadSize, rv);
4062 content.append(buf->data(), rv);
4063 } else if (rv < 0) {
4064 FAIL() << "Unexpected read error: " << rv;
4065 }
4066 reads_completed++;
4067 } while (rv > 0);
4068
4069 EXPECT_EQ(3, reads_completed);
4070
4071 out.response_data.swap(content);
4072
[email protected]30c942b2010-07-21 16:59:594073 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:554074 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:174075 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:554076
4077 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:474078 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:554079
4080 EXPECT_EQ(OK, out.rv);
4081 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4082 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
4083}
4084
4085// Verify the case where we buffer data and close the connection.
[email protected]513963e2013-06-15 01:53:044086TEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
[email protected]513963e2013-06-15 01:53:044087 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]20d005f2010-07-02 19:55:434088
[email protected]cdf8f7e72013-05-23 10:56:464089 scoped_ptr<SpdyFrame> req(
4090 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]e7f75092010-07-01 22:39:134091 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]8918d282010-03-02 00:57:554092
4093 // All data frames in a single read.
[email protected]20d005f2010-07-02 19:55:434094 // NOTE: We don't FIN the stream.
[email protected]ff98d7f02012-03-22 21:44:194095 scoped_ptr<SpdyFrame> data_frame(
4096 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4097 const SpdyFrame* data_frames[4] = {
[email protected]20d005f2010-07-02 19:55:434098 data_frame.get(),
4099 data_frame.get(),
4100 data_frame.get(),
4101 data_frame.get()
[email protected]8918d282010-03-02 00:57:554102 };
[email protected]20d005f2010-07-02 19:55:434103 char combined_data_frames[100];
4104 int combined_data_frames_len =
4105 CombineFrames(data_frames, arraysize(data_frames),
4106 combined_data_frames, arraysize(combined_data_frames));
[email protected]513963e2013-06-15 01:53:044107 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8918d282010-03-02 00:57:554108 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:134109 CreateMockRead(*resp),
[email protected]8ddf8322012-02-23 18:08:064110 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait
4111 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
4112 MockRead(ASYNC, 0, 0) // EOF
[email protected]8918d282010-03-02 00:57:554113 };
4114
[email protected]dd54bd82012-07-19 23:44:574115 DelayedSocketData data(1, reads, arraysize(reads),
4116 writes, arraysize(writes));
[email protected]8918d282010-03-02 00:57:554117
[email protected]262eec82013-03-19 21:01:364118 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504119 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:474120 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574121 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:474122 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:554123
[email protected]49639fa2011-12-20 23:22:414124 TestCompletionCallback callback;
[email protected]8918d282010-03-02 00:57:554125
[email protected]49639fa2011-12-20 23:22:414126 int rv = trans->Start(
4127 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]8918d282010-03-02 00:57:554128 EXPECT_EQ(ERR_IO_PENDING, rv);
4129
[email protected]3caf5542010-07-16 15:19:474130 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:554131 out.rv = callback.WaitForResult();
4132 EXPECT_EQ(out.rv, OK);
4133
4134 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:504135 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]8918d282010-03-02 00:57:554136 EXPECT_TRUE(response->was_fetched_via_spdy);
4137 out.status_line = response->headers->GetStatusLine();
4138 out.response_info = *response; // Make a copy so we can verify.
4139
4140 // Read Data
[email protected]49639fa2011-12-20 23:22:414141 TestCompletionCallback read_callback;
[email protected]8918d282010-03-02 00:57:554142
4143 std::string content;
4144 int reads_completed = 0;
4145 do {
4146 // Read small chunks at a time.
4147 const int kSmallReadSize = 14;
[email protected]ad8e04a2010-11-01 04:16:274148 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
[email protected]90499482013-06-01 00:39:504149 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
[email protected]8918d282010-03-02 00:57:554150 if (rv == net::ERR_IO_PENDING) {
[email protected]dd54bd82012-07-19 23:44:574151 data.CompleteRead();
[email protected]8918d282010-03-02 00:57:554152 rv = read_callback.WaitForResult();
4153 }
4154 if (rv > 0) {
4155 content.append(buf->data(), rv);
4156 } else if (rv < 0) {
4157 // This test intentionally closes the connection, and will get an error.
4158 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
4159 break;
4160 }
4161 reads_completed++;
4162 } while (rv > 0);
4163
4164 EXPECT_EQ(0, reads_completed);
4165
4166 out.response_data.swap(content);
4167
[email protected]30c942b2010-07-21 16:59:594168 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:554169 // MockClientSocketFactory) are still alive.
[email protected]fc9d88472013-08-14 02:31:174170 base::RunLoop().RunUntilIdle();
[email protected]8918d282010-03-02 00:57:554171
4172 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:474173 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:554174}
4175
[email protected]1ed7b3dc2010-03-04 05:41:454176// Verify the case where we buffer data and cancel the transaction.
[email protected]513963e2013-06-15 01:53:044177TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) {
[email protected]513963e2013-06-15 01:53:044178 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
[email protected]20d005f2010-07-02 19:55:434179
[email protected]cdf8f7e72013-05-23 10:56:464180 scoped_ptr<SpdyFrame> req(
4181 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]975da41a2014-06-05 03:36:244182 scoped_ptr<SpdyFrame> rst(
4183 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
4184 MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*rst)};
[email protected]1ed7b3dc2010-03-04 05:41:454185
[email protected]20d005f2010-07-02 19:55:434186 // NOTE: We don't FIN the stream.
[email protected]ff98d7f02012-03-22 21:44:194187 scoped_ptr<SpdyFrame> data_frame(
4188 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
[email protected]1ed7b3dc2010-03-04 05:41:454189
[email protected]513963e2013-06-15 01:53:044190 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]1ed7b3dc2010-03-04 05:41:454191 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:134192 CreateMockRead(*resp),
[email protected]8ddf8322012-02-23 18:08:064193 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait
[email protected]20d005f2010-07-02 19:55:434194 CreateMockRead(*data_frame),
[email protected]8ddf8322012-02-23 18:08:064195 MockRead(ASYNC, 0, 0) // EOF
[email protected]1ed7b3dc2010-03-04 05:41:454196 };
4197
[email protected]dd54bd82012-07-19 23:44:574198 DelayedSocketData data(1, reads, arraysize(reads),
4199 writes, arraysize(writes));
[email protected]1ed7b3dc2010-03-04 05:41:454200
[email protected]262eec82013-03-19 21:01:364201 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504202 BoundNetLog(), GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:474203 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574204 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:474205 HttpNetworkTransaction* trans = helper.trans();
[email protected]49639fa2011-12-20 23:22:414206 TestCompletionCallback callback;
[email protected]1ed7b3dc2010-03-04 05:41:454207
[email protected]49639fa2011-12-20 23:22:414208 int rv = trans->Start(
4209 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]1ed7b3dc2010-03-04 05:41:454210 EXPECT_EQ(ERR_IO_PENDING, rv);
4211
[email protected]3caf5542010-07-16 15:19:474212 TransactionHelperResult out = helper.output();
[email protected]1ed7b3dc2010-03-04 05:41:454213 out.rv = callback.WaitForResult();
4214 EXPECT_EQ(out.rv, OK);
4215
4216 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:504217 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]1ed7b3dc2010-03-04 05:41:454218 EXPECT_TRUE(response->was_fetched_via_spdy);
4219 out.status_line = response->headers->GetStatusLine();
4220 out.response_info = *response; // Make a copy so we can verify.
4221
4222 // Read Data
[email protected]49639fa2011-12-20 23:22:414223 TestCompletionCallback read_callback;
[email protected]1ed7b3dc2010-03-04 05:41:454224
[email protected]88c7b4be2014-03-19 23:04:014225 const int kReadSize = 256;
4226 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kReadSize));
4227 rv = trans->Read(buf.get(), kReadSize, read_callback.callback());
4228 ASSERT_EQ(net::ERR_IO_PENDING, rv) << "Unexpected read: " << rv;
4229
4230 // Complete the read now, which causes buffering to start.
4231 data.CompleteRead();
4232 // Destroy the transaction, causing the stream to get cancelled
4233 // and orphaning the buffered IO task.
4234 helper.ResetTrans();
[email protected]1ed7b3dc2010-03-04 05:41:454235
4236 // Flush the MessageLoop; this will cause the buffered IO task
4237 // to run for the final time.
[email protected]fc9d88472013-08-14 02:31:174238 base::RunLoop().RunUntilIdle();
[email protected]3caf5542010-07-16 15:19:474239
4240 // Verify that we consumed all test data.
4241 helper.VerifyDataConsumed();
[email protected]1ed7b3dc2010-03-04 05:41:454242}
4243
[email protected]74188f22010-04-09 20:18:504244// Test that if the server requests persistence of settings, that we save
[email protected]18b28ab2012-04-18 02:14:424245// the settings in the HttpServerProperties.
[email protected]513963e2013-06-15 01:53:044246TEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
[email protected]8a7bc7a2014-02-28 21:25:224247 if (spdy_util_.spdy_version() >= SPDY4) {
[email protected]745aa9c2014-06-27 02:21:294248 // SPDY4 doesn't support settings persistence.
[email protected]8a7bc7a2014-02-28 21:25:224249 return;
4250 }
[email protected]74188f22010-04-09 20:18:504251 static const SpdyHeaderInfo kSynReplyInfo = {
[email protected]ff98d7f02012-03-22 21:44:194252 SYN_REPLY, // Syn Reply
[email protected]e0935cc2012-03-24 14:12:484253 1, // Stream ID
4254 0, // Associated Stream ID
[email protected]513963e2013-06-15 01:53:044255 ConvertRequestPriorityToSpdyPriority(
4256 LOWEST, spdy_util_.spdy_version()),
4257 kSpdyCredentialSlotUnused,
[email protected]ff98d7f02012-03-22 21:44:194258 CONTROL_FLAG_NONE, // Control Flags
[email protected]e0935cc2012-03-24 14:12:484259 false, // Compressed
[email protected]5a7bb252013-02-09 00:21:054260 RST_STREAM_INVALID, // Status
[email protected]e0935cc2012-03-24 14:12:484261 NULL, // Data
4262 0, // Data Length
[email protected]ff98d7f02012-03-22 21:44:194263 DATA_FLAG_NONE // Data Flags
[email protected]74188f22010-04-09 20:18:504264 };
[email protected]74188f22010-04-09 20:18:504265
[email protected]c0168822011-12-10 01:24:274266 BoundNetLog net_log;
[email protected]262eec82013-03-19 21:01:364267 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4268 net_log, GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:584269 helper.RunPreTestSetup();
[email protected]74188f22010-04-09 20:18:504270
4271 // Verify that no settings exist initially.
[email protected]9e9e842e2010-07-23 23:09:154272 HostPortPair host_port_pair("www.google.com", helper.port());
[email protected]102e27c2011-02-23 01:01:314273 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
[email protected]53bfa31c2011-11-15 19:20:314274 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4275 host_port_pair).empty());
[email protected]74188f22010-04-09 20:18:504276
4277 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:464278 scoped_ptr<SpdyFrame> req(
4279 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]e7f75092010-07-01 22:39:134280 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]74188f22010-04-09 20:18:504281
4282 // Construct the reply.
[email protected]513963e2013-06-15 01:53:044283 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4284 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4285 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
[email protected]ff98d7f02012-03-22 21:44:194286 scoped_ptr<SpdyFrame> reply(
[email protected]513963e2013-06-15 01:53:044287 spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
[email protected]74188f22010-04-09 20:18:504288
[email protected]e0935cc2012-03-24 14:12:484289 const SpdySettingsIds kSampleId1 = SETTINGS_UPLOAD_BANDWIDTH;
[email protected]74188f22010-04-09 20:18:504290 unsigned int kSampleValue1 = 0x0a0a0a0a;
[email protected]e0935cc2012-03-24 14:12:484291 const SpdySettingsIds kSampleId2 = SETTINGS_DOWNLOAD_BANDWIDTH;
[email protected]74188f22010-04-09 20:18:504292 unsigned int kSampleValue2 = 0x0b0b0b0b;
[email protected]e0935cc2012-03-24 14:12:484293 const SpdySettingsIds kSampleId3 = SETTINGS_ROUND_TRIP_TIME;
[email protected]74188f22010-04-09 20:18:504294 unsigned int kSampleValue3 = 0x0c0c0c0c;
[email protected]ff98d7f02012-03-22 21:44:194295 scoped_ptr<SpdyFrame> settings_frame;
[email protected]74188f22010-04-09 20:18:504296 {
4297 // Construct the SETTINGS frame.
[email protected]18b28ab2012-04-18 02:14:424298 SettingsMap settings;
[email protected]e0935cc2012-03-24 14:12:484299 // First add a persisted setting.
[email protected]18b28ab2012-04-18 02:14:424300 settings[kSampleId1] =
4301 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue1);
[email protected]e0935cc2012-03-24 14:12:484302 // Next add a non-persisted setting.
[email protected]18b28ab2012-04-18 02:14:424303 settings[kSampleId2] =
4304 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kSampleValue2);
[email protected]e0935cc2012-03-24 14:12:484305 // Next add another persisted setting.
[email protected]18b28ab2012-04-18 02:14:424306 settings[kSampleId3] =
4307 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue3);
[email protected]c10b20852013-05-15 21:29:204308 settings_frame.reset(spdy_util_.ConstructSpdySettings(settings));
[email protected]74188f22010-04-09 20:18:504309 }
4310
[email protected]513963e2013-06-15 01:53:044311 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]74188f22010-04-09 20:18:504312 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:134313 CreateMockRead(*reply),
4314 CreateMockRead(*body),
4315 CreateMockRead(*settings_frame),
[email protected]8ddf8322012-02-23 18:08:064316 MockRead(ASYNC, 0, 0) // EOF
[email protected]74188f22010-04-09 20:18:504317 };
4318
[email protected]dd54bd82012-07-19 23:44:574319 DelayedSocketData data(1, reads, arraysize(reads),
4320 writes, arraysize(writes));
4321 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:584322 helper.RunDefaultTest();
4323 helper.VerifyDataConsumed();
[email protected]3caf5542010-07-16 15:19:474324 TransactionHelperResult out = helper.output();
[email protected]74188f22010-04-09 20:18:504325 EXPECT_EQ(OK, out.rv);
4326 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4327 EXPECT_EQ("hello!", out.response_data);
4328
4329 {
4330 // Verify we had two persisted settings.
[email protected]e0935cc2012-03-24 14:12:484331 const SettingsMap& settings_map =
[email protected]53bfa31c2011-11-15 19:20:314332 spdy_session_pool->http_server_properties()->GetSpdySettings(
4333 host_port_pair);
[email protected]e0935cc2012-03-24 14:12:484334 ASSERT_EQ(2u, settings_map.size());
[email protected]74188f22010-04-09 20:18:504335
4336 // Verify the first persisted setting.
[email protected]e0935cc2012-03-24 14:12:484337 SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4338 EXPECT_TRUE(it1 != settings_map.end());
4339 SettingsFlagsAndValue flags_and_value1 = it1->second;
4340 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4341 EXPECT_EQ(kSampleValue1, flags_and_value1.second);
[email protected]74188f22010-04-09 20:18:504342
4343 // Verify the second persisted setting.
[email protected]e0935cc2012-03-24 14:12:484344 SettingsMap::const_iterator it3 = settings_map.find(kSampleId3);
4345 EXPECT_TRUE(it3 != settings_map.end());
4346 SettingsFlagsAndValue flags_and_value3 = it3->second;
4347 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value3.first);
4348 EXPECT_EQ(kSampleValue3, flags_and_value3.second);
[email protected]74188f22010-04-09 20:18:504349 }
4350}
4351
4352// Test that when there are settings saved that they are sent back to the
4353// server upon session establishment.
[email protected]513963e2013-06-15 01:53:044354TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) {
[email protected]745aa9c2014-06-27 02:21:294355 if (spdy_util_.spdy_version() >= SPDY4) {
4356 // SPDY4 doesn't support settings persistence.
4357 return;
4358 }
[email protected]74188f22010-04-09 20:18:504359 static const SpdyHeaderInfo kSynReplyInfo = {
[email protected]ff98d7f02012-03-22 21:44:194360 SYN_REPLY, // Syn Reply
[email protected]e0935cc2012-03-24 14:12:484361 1, // Stream ID
4362 0, // Associated Stream ID
[email protected]513963e2013-06-15 01:53:044363 ConvertRequestPriorityToSpdyPriority(
4364 LOWEST, spdy_util_.spdy_version()),
4365 kSpdyCredentialSlotUnused,
[email protected]ff98d7f02012-03-22 21:44:194366 CONTROL_FLAG_NONE, // Control Flags
[email protected]e0935cc2012-03-24 14:12:484367 false, // Compressed
[email protected]5a7bb252013-02-09 00:21:054368 RST_STREAM_INVALID, // Status
[email protected]e0935cc2012-03-24 14:12:484369 NULL, // Data
4370 0, // Data Length
[email protected]ff98d7f02012-03-22 21:44:194371 DATA_FLAG_NONE // Data Flags
[email protected]74188f22010-04-09 20:18:504372 };
[email protected]74188f22010-04-09 20:18:504373
[email protected]c0168822011-12-10 01:24:274374 BoundNetLog net_log;
[email protected]262eec82013-03-19 21:01:364375 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4376 net_log, GetParam(), NULL);
[email protected]e3ebba0f2010-08-05 17:59:584377 helper.RunPreTestSetup();
[email protected]74188f22010-04-09 20:18:504378
[email protected]b40f7fa2013-08-01 16:13:054379 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4380
4381 SpdySessionPoolPeer pool_peer(spdy_session_pool);
4382 pool_peer.SetEnableSendingInitialData(true);
4383
[email protected]74188f22010-04-09 20:18:504384 // Verify that no settings exist initially.
[email protected]9e9e842e2010-07-23 23:09:154385 HostPortPair host_port_pair("www.google.com", helper.port());
[email protected]53bfa31c2011-11-15 19:20:314386 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4387 host_port_pair).empty());
[email protected]74188f22010-04-09 20:18:504388
[email protected]c143f2742014-03-31 00:48:544389 const SpdySettingsIds kSampleId1 = SETTINGS_MAX_CONCURRENT_STREAMS;
[email protected]74188f22010-04-09 20:18:504390 unsigned int kSampleValue1 = 0x0a0a0a0a;
[email protected]c143f2742014-03-31 00:48:544391 const SpdySettingsIds kSampleId2 = SETTINGS_INITIAL_WINDOW_SIZE;
[email protected]74188f22010-04-09 20:18:504392 unsigned int kSampleValue2 = 0x0c0c0c0c;
[email protected]74188f22010-04-09 20:18:504393
[email protected]e0935cc2012-03-24 14:12:484394 // First add a persisted setting.
4395 spdy_session_pool->http_server_properties()->SetSpdySetting(
4396 host_port_pair,
4397 kSampleId1,
4398 SETTINGS_FLAG_PLEASE_PERSIST,
4399 kSampleValue1);
4400
4401 // Next add another persisted setting.
4402 spdy_session_pool->http_server_properties()->SetSpdySetting(
4403 host_port_pair,
4404 kSampleId2,
4405 SETTINGS_FLAG_PLEASE_PERSIST,
4406 kSampleValue2);
[email protected]74188f22010-04-09 20:18:504407
[email protected]53bfa31c2011-11-15 19:20:314408 EXPECT_EQ(2u, spdy_session_pool->http_server_properties()->GetSpdySettings(
4409 host_port_pair).size());
[email protected]74188f22010-04-09 20:18:504410
[email protected]b40f7fa2013-08-01 16:13:054411 // Construct the initial SETTINGS frame.
4412 SettingsMap initial_settings;
4413 initial_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4414 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
4415 scoped_ptr<SpdyFrame> initial_settings_frame(
4416 spdy_util_.ConstructSpdySettings(initial_settings));
4417
4418 // Construct the initial window update.
4419 scoped_ptr<SpdyFrame> initial_window_update(
4420 spdy_util_.ConstructSpdyWindowUpdate(
4421 kSessionFlowControlStreamId,
4422 kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
4423
4424 // Construct the persisted SETTINGS frame.
[email protected]18b28ab2012-04-18 02:14:424425 const SettingsMap& settings =
[email protected]53bfa31c2011-11-15 19:20:314426 spdy_session_pool->http_server_properties()->GetSpdySettings(
4427 host_port_pair);
[email protected]c10b20852013-05-15 21:29:204428 scoped_ptr<SpdyFrame> settings_frame(
4429 spdy_util_.ConstructSpdySettings(settings));
[email protected]74188f22010-04-09 20:18:504430
4431 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:464432 scoped_ptr<SpdyFrame> req(
4433 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]74188f22010-04-09 20:18:504434
[email protected]b40f7fa2013-08-01 16:13:054435 std::vector<MockWrite> writes;
[email protected]d10833bc2014-04-14 17:50:464436 if (GetParam().protocol == kProtoSPDY4) {
[email protected]b40f7fa2013-08-01 16:13:054437 writes.push_back(
4438 MockWrite(ASYNC,
4439 kHttp2ConnectionHeaderPrefix,
4440 kHttp2ConnectionHeaderPrefixSize));
4441 }
4442 writes.push_back(CreateMockWrite(*initial_settings_frame));
4443 if (GetParam().protocol >= kProtoSPDY31) {
4444 writes.push_back(CreateMockWrite(*initial_window_update));
mmenkecbc2b712014-10-09 20:29:074445 }
[email protected]b40f7fa2013-08-01 16:13:054446 writes.push_back(CreateMockWrite(*settings_frame));
4447 writes.push_back(CreateMockWrite(*req));
[email protected]74188f22010-04-09 20:18:504448
4449 // Construct the reply.
[email protected]513963e2013-06-15 01:53:044450 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4451 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4452 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
[email protected]ff98d7f02012-03-22 21:44:194453 scoped_ptr<SpdyFrame> reply(
[email protected]513963e2013-06-15 01:53:044454 spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
[email protected]74188f22010-04-09 20:18:504455
[email protected]513963e2013-06-15 01:53:044456 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]74188f22010-04-09 20:18:504457 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:134458 CreateMockRead(*reply),
4459 CreateMockRead(*body),
[email protected]8ddf8322012-02-23 18:08:064460 MockRead(ASYNC, 0, 0) // EOF
[email protected]74188f22010-04-09 20:18:504461 };
4462
[email protected]dd54bd82012-07-19 23:44:574463 DelayedSocketData data(2, reads, arraysize(reads),
[email protected]b40f7fa2013-08-01 16:13:054464 vector_as_array(&writes), writes.size());
[email protected]dd54bd82012-07-19 23:44:574465 helper.AddData(&data);
[email protected]e3ebba0f2010-08-05 17:59:584466 helper.RunDefaultTest();
4467 helper.VerifyDataConsumed();
[email protected]3caf5542010-07-16 15:19:474468 TransactionHelperResult out = helper.output();
[email protected]74188f22010-04-09 20:18:504469 EXPECT_EQ(OK, out.rv);
4470 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4471 EXPECT_EQ("hello!", out.response_data);
4472
4473 {
4474 // Verify we had two persisted settings.
[email protected]e0935cc2012-03-24 14:12:484475 const SettingsMap& settings_map =
[email protected]53bfa31c2011-11-15 19:20:314476 spdy_session_pool->http_server_properties()->GetSpdySettings(
4477 host_port_pair);
[email protected]e0935cc2012-03-24 14:12:484478 ASSERT_EQ(2u, settings_map.size());
[email protected]74188f22010-04-09 20:18:504479
4480 // Verify the first persisted setting.
[email protected]e0935cc2012-03-24 14:12:484481 SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4482 EXPECT_TRUE(it1 != settings_map.end());
4483 SettingsFlagsAndValue flags_and_value1 = it1->second;
4484 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4485 EXPECT_EQ(kSampleValue1, flags_and_value1.second);
[email protected]74188f22010-04-09 20:18:504486
4487 // Verify the second persisted setting.
[email protected]e0935cc2012-03-24 14:12:484488 SettingsMap::const_iterator it2 = settings_map.find(kSampleId2);
4489 EXPECT_TRUE(it2 != settings_map.end());
4490 SettingsFlagsAndValue flags_and_value2 = it2->second;
4491 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value2.first);
4492 EXPECT_EQ(kSampleValue2, flags_and_value2.second);
[email protected]74188f22010-04-09 20:18:504493 }
4494}
4495
[email protected]513963e2013-06-15 01:53:044496TEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
[email protected]cdf8f7e72013-05-23 10:56:464497 scoped_ptr<SpdyFrame> req(
4498 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]e7f75092010-07-01 22:39:134499 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]69d717bd2010-04-21 18:43:214500
[email protected]c10b20852013-05-15 21:29:204501 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway());
[email protected]69d717bd2010-04-21 18:43:214502 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:134503 CreateMockRead(*go_away),
[email protected]58cebf8f2010-07-31 19:20:164504 };
4505
[email protected]dd54bd82012-07-19 23:44:574506 DelayedSocketData data(1, reads, arraysize(reads),
4507 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:364508 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504509 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:574510 helper.AddData(&data);
4511 helper.RunToCompletion(&data);
[email protected]58cebf8f2010-07-31 19:20:164512 TransactionHelperResult out = helper.output();
[email protected]c9336d22010-08-10 00:04:184513 EXPECT_EQ(ERR_ABORTED, out.rv);
[email protected]69d717bd2010-04-21 18:43:214514}
4515
[email protected]513963e2013-06-15 01:53:044516TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) {
[email protected]cdf8f7e72013-05-23 10:56:464517 scoped_ptr<SpdyFrame> req(
4518 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]e7f75092010-07-01 22:39:134519 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]f5ed21552010-05-04 18:39:544520
[email protected]513963e2013-06-15 01:53:044521 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]f5ed21552010-05-04 18:39:544522 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:134523 CreateMockRead(*resp),
[email protected]8ddf8322012-02-23 18:08:064524 MockRead(SYNCHRONOUS, 0, 0) // EOF
[email protected]f5ed21552010-05-04 18:39:544525 };
4526
[email protected]dd54bd82012-07-19 23:44:574527 DelayedSocketData data(1, reads, arraysize(reads),
4528 writes, arraysize(writes));
[email protected]f5ed21552010-05-04 18:39:544529 BoundNetLog log;
[email protected]262eec82013-03-19 21:01:364530 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504531 log, GetParam(), NULL);
[email protected]3caf5542010-07-16 15:19:474532 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:574533 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:474534 HttpNetworkTransaction* trans = helper.trans();
[email protected]f5ed21552010-05-04 18:39:544535
[email protected]49639fa2011-12-20 23:22:414536 TestCompletionCallback callback;
[email protected]3caf5542010-07-16 15:19:474537 TransactionHelperResult out;
[email protected]49639fa2011-12-20 23:22:414538 out.rv = trans->Start(&CreateGetRequest(), callback.callback(), log);
[email protected]3caf5542010-07-16 15:19:474539
[email protected]f5ed21552010-05-04 18:39:544540 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4541 out.rv = callback.WaitForResult();
4542 EXPECT_EQ(out.rv, OK);
4543
4544 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:504545 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]f5ed21552010-05-04 18:39:544546 EXPECT_TRUE(response->was_fetched_via_spdy);
[email protected]3caf5542010-07-16 15:19:474547 out.rv = ReadTransaction(trans, &out.response_data);
[email protected]f5ed21552010-05-04 18:39:544548 EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv);
4549
4550 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:474551 helper.VerifyDataConsumed();
[email protected]f5ed21552010-05-04 18:39:544552}
[email protected]58cebf8f2010-07-31 19:20:164553
[email protected]b261d0e2010-08-02 19:13:244554// Test to make sure we can correctly connect through a proxy.
[email protected]513963e2013-06-15 01:53:044555TEST_P(SpdyNetworkTransactionTest, ProxyConnect) {
[email protected]262eec82013-03-19 21:01:364556 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504557 BoundNetLog(), GetParam(), NULL);
[email protected]bb88e1d32013-05-03 23:11:074558 helper.session_deps().reset(CreateSpdySessionDependencies(
[email protected]513963e2013-06-15 01:53:044559 GetParam(),
[email protected]733b7a6d2010-08-25 01:38:434560 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
[email protected]00cd9c42010-11-02 20:15:574561 helper.SetSession(make_scoped_refptr(
4562 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
[email protected]b261d0e2010-08-02 19:13:244563 helper.RunPreTestSetup();
4564 HttpNetworkTransaction* trans = helper.trans();
4565
4566 const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4567 "Host: www.google.com\r\n"
4568 "Proxy-Connection: keep-alive\r\n\r\n"};
4569 const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4570 "Host: www.google.com\r\n"
4571 "Proxy-Connection: keep-alive\r\n\r\n"};
4572 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
[email protected]cdf8f7e72013-05-23 10:56:464573 scoped_ptr<SpdyFrame> req(
4574 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:044575 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4576 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:244577
4578 MockWrite writes_SPDYNPN[] = {
[email protected]8ddf8322012-02-23 18:08:064579 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
[email protected]b261d0e2010-08-02 19:13:244580 CreateMockWrite(*req, 2),
4581 };
4582 MockRead reads_SPDYNPN[] = {
[email protected]8ddf8322012-02-23 18:08:064583 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
[email protected]b261d0e2010-08-02 19:13:244584 CreateMockRead(*resp, 3),
4585 CreateMockRead(*body.get(), 4),
[email protected]8ddf8322012-02-23 18:08:064586 MockRead(ASYNC, 0, 0, 5),
[email protected]b261d0e2010-08-02 19:13:244587 };
4588
4589 MockWrite writes_SPDYSSL[] = {
[email protected]8ddf8322012-02-23 18:08:064590 MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0),
[email protected]b261d0e2010-08-02 19:13:244591 CreateMockWrite(*req, 2),
4592 };
4593 MockRead reads_SPDYSSL[] = {
[email protected]8ddf8322012-02-23 18:08:064594 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
[email protected]b261d0e2010-08-02 19:13:244595 CreateMockRead(*resp, 3),
4596 CreateMockRead(*body.get(), 4),
[email protected]8ddf8322012-02-23 18:08:064597 MockRead(ASYNC, 0, 0, 5),
[email protected]b261d0e2010-08-02 19:13:244598 };
4599
4600 MockWrite writes_SPDYNOSSL[] = {
4601 CreateMockWrite(*req, 0),
4602 };
4603
4604 MockRead reads_SPDYNOSSL[] = {
4605 CreateMockRead(*resp, 1),
4606 CreateMockRead(*body.get(), 2),
[email protected]8ddf8322012-02-23 18:08:064607 MockRead(ASYNC, 0, 0, 3),
[email protected]b261d0e2010-08-02 19:13:244608 };
4609
[email protected]a1595312012-01-22 03:25:044610 scoped_ptr<OrderedSocketData> data;
mmenkecbc2b712014-10-09 20:29:074611 switch (GetParam().ssl_type) {
[email protected]b261d0e2010-08-02 19:13:244612 case SPDYNOSSL:
[email protected]a1595312012-01-22 03:25:044613 data.reset(new OrderedSocketData(reads_SPDYNOSSL,
4614 arraysize(reads_SPDYNOSSL),
4615 writes_SPDYNOSSL,
4616 arraysize(writes_SPDYNOSSL)));
[email protected]b261d0e2010-08-02 19:13:244617 break;
4618 case SPDYSSL:
[email protected]a1595312012-01-22 03:25:044619 data.reset(new OrderedSocketData(reads_SPDYSSL,
4620 arraysize(reads_SPDYSSL),
4621 writes_SPDYSSL,
4622 arraysize(writes_SPDYSSL)));
[email protected]b261d0e2010-08-02 19:13:244623 break;
4624 case SPDYNPN:
[email protected]a1595312012-01-22 03:25:044625 data.reset(new OrderedSocketData(reads_SPDYNPN,
4626 arraysize(reads_SPDYNPN),
4627 writes_SPDYNPN,
4628 arraysize(writes_SPDYNPN)));
[email protected]b261d0e2010-08-02 19:13:244629 break;
4630 default:
4631 NOTREACHED();
4632 }
4633
4634 helper.AddData(data.get());
[email protected]49639fa2011-12-20 23:22:414635 TestCompletionCallback callback;
[email protected]b261d0e2010-08-02 19:13:244636
[email protected]49639fa2011-12-20 23:22:414637 int rv = trans->Start(
4638 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]b261d0e2010-08-02 19:13:244639 EXPECT_EQ(ERR_IO_PENDING, rv);
4640
4641 rv = callback.WaitForResult();
4642 EXPECT_EQ(0, rv);
4643
4644 // Verify the SYN_REPLY.
4645 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:504646 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]b261d0e2010-08-02 19:13:244647 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
4648
4649 std::string response_data;
4650 ASSERT_EQ(OK, ReadTransaction(trans, &response_data));
4651 EXPECT_EQ("hello!", response_data);
4652 helper.VerifyDataConsumed();
4653}
4654
4655// Test to make sure we can correctly connect through a proxy to www.google.com,
4656// if there already exists a direct spdy connection to www.google.com. See
4657// http://crbug.com/49874
[email protected]513963e2013-06-15 01:53:044658TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
[email protected]b261d0e2010-08-02 19:13:244659 // When setting up the first transaction, we store the SpdySessionPool so that
4660 // we can use the same pool in the second transaction.
[email protected]262eec82013-03-19 21:01:364661 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504662 BoundNetLog(), GetParam(), NULL);
[email protected]733b7a6d2010-08-25 01:38:434663
4664 // Use a proxy service which returns a proxy fallback list from DIRECT to
4665 // myproxy:70. For this test there will be no fallback, so it is equivalent
4666 // to simply DIRECT. The reason for appending the second proxy is to verify
4667 // that the session pool key used does is just "DIRECT".
[email protected]bb88e1d32013-05-03 23:11:074668 helper.session_deps().reset(CreateSpdySessionDependencies(
[email protected]513963e2013-06-15 01:53:044669 GetParam(),
[email protected]733b7a6d2010-08-25 01:38:434670 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
[email protected]00cd9c42010-11-02 20:15:574671 helper.SetSession(make_scoped_refptr(
4672 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
[email protected]733b7a6d2010-08-25 01:38:434673
[email protected]87bfa3f2010-09-30 14:54:564674 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
[email protected]b261d0e2010-08-02 19:13:244675 helper.RunPreTestSetup();
4676
4677 // Construct and send a simple GET request.
[email protected]cdf8f7e72013-05-23 10:56:464678 scoped_ptr<SpdyFrame> req(
4679 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]b261d0e2010-08-02 19:13:244680 MockWrite writes[] = {
4681 CreateMockWrite(*req, 1),
4682 };
4683
[email protected]513963e2013-06-15 01:53:044684 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4685 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:244686 MockRead reads[] = {
4687 CreateMockRead(*resp, 2),
4688 CreateMockRead(*body, 3),
[email protected]8ddf8322012-02-23 18:08:064689 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause
4690 MockRead(ASYNC, 0, 5) // EOF
[email protected]b261d0e2010-08-02 19:13:244691 };
[email protected]dd54bd82012-07-19 23:44:574692 OrderedSocketData data(reads, arraysize(reads),
4693 writes, arraysize(writes));
4694 helper.AddData(&data);
[email protected]b261d0e2010-08-02 19:13:244695 HttpNetworkTransaction* trans = helper.trans();
4696
[email protected]49639fa2011-12-20 23:22:414697 TestCompletionCallback callback;
[email protected]b261d0e2010-08-02 19:13:244698 TransactionHelperResult out;
[email protected]49639fa2011-12-20 23:22:414699 out.rv = trans->Start(
4700 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]b261d0e2010-08-02 19:13:244701
4702 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4703 out.rv = callback.WaitForResult();
4704 EXPECT_EQ(out.rv, OK);
4705
4706 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:504707 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]b261d0e2010-08-02 19:13:244708 EXPECT_TRUE(response->was_fetched_via_spdy);
4709 out.rv = ReadTransaction(trans, &out.response_data);
4710 EXPECT_EQ(OK, out.rv);
4711 out.status_line = response->headers->GetStatusLine();
4712 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4713 EXPECT_EQ("hello!", out.response_data);
4714
4715 // Check that the SpdySession is still in the SpdySessionPool.
4716 HostPortPair host_port_pair("www.google.com", helper.port());
[email protected]e6d017652013-05-17 18:01:404717 SpdySessionKey session_pool_key_direct(
[email protected]314b03992014-04-01 01:28:534718 host_port_pair, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
[email protected]41d64e82013-07-03 22:44:264719 EXPECT_TRUE(HasSpdySession(spdy_session_pool, session_pool_key_direct));
[email protected]e6d017652013-05-17 18:01:404720 SpdySessionKey session_pool_key_proxy(
[email protected]31e68d72010-08-25 06:36:584721 host_port_pair,
[email protected]e6d017652013-05-17 18:01:404722 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP),
[email protected]314b03992014-04-01 01:28:534723 PRIVACY_MODE_DISABLED);
[email protected]41d64e82013-07-03 22:44:264724 EXPECT_FALSE(HasSpdySession(spdy_session_pool, session_pool_key_proxy));
[email protected]b261d0e2010-08-02 19:13:244725
4726 // Set up data for the proxy connection.
4727 const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4728 "Host: www.google.com\r\n"
4729 "Proxy-Connection: keep-alive\r\n\r\n"};
4730 const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4731 "Host: www.google.com\r\n"
4732 "Proxy-Connection: keep-alive\r\n\r\n"};
4733 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
[email protected]cdf8f7e72013-05-23 10:56:464734 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyGet(
[email protected]b261d0e2010-08-02 19:13:244735 "http://www.google.com/foo.dat", false, 1, LOWEST));
[email protected]513963e2013-06-15 01:53:044736 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4737 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]b261d0e2010-08-02 19:13:244738
4739 MockWrite writes_SPDYNPN[] = {
[email protected]8ddf8322012-02-23 18:08:064740 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
[email protected]b261d0e2010-08-02 19:13:244741 CreateMockWrite(*req2, 2),
4742 };
4743 MockRead reads_SPDYNPN[] = {
[email protected]8ddf8322012-02-23 18:08:064744 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
[email protected]b261d0e2010-08-02 19:13:244745 CreateMockRead(*resp2, 3),
4746 CreateMockRead(*body2, 4),
[email protected]8ddf8322012-02-23 18:08:064747 MockRead(ASYNC, 0, 5) // EOF
[email protected]b261d0e2010-08-02 19:13:244748 };
4749
4750 MockWrite writes_SPDYNOSSL[] = {
4751 CreateMockWrite(*req2, 0),
4752 };
4753 MockRead reads_SPDYNOSSL[] = {
4754 CreateMockRead(*resp2, 1),
4755 CreateMockRead(*body2, 2),
[email protected]8ddf8322012-02-23 18:08:064756 MockRead(ASYNC, 0, 3) // EOF
[email protected]b261d0e2010-08-02 19:13:244757 };
4758
4759 MockWrite writes_SPDYSSL[] = {
[email protected]8ddf8322012-02-23 18:08:064760 MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0),
[email protected]b261d0e2010-08-02 19:13:244761 CreateMockWrite(*req2, 2),
4762 };
4763 MockRead reads_SPDYSSL[] = {
[email protected]8ddf8322012-02-23 18:08:064764 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
[email protected]b261d0e2010-08-02 19:13:244765 CreateMockRead(*resp2, 3),
4766 CreateMockRead(*body2, 4),
[email protected]8ddf8322012-02-23 18:08:064767 MockRead(ASYNC, 0, 0, 5),
[email protected]b261d0e2010-08-02 19:13:244768 };
4769
[email protected]a1595312012-01-22 03:25:044770 scoped_ptr<OrderedSocketData> data_proxy;
mmenkecbc2b712014-10-09 20:29:074771 switch (GetParam().ssl_type) {
[email protected]b261d0e2010-08-02 19:13:244772 case SPDYNPN:
[email protected]a1595312012-01-22 03:25:044773 data_proxy.reset(new OrderedSocketData(reads_SPDYNPN,
4774 arraysize(reads_SPDYNPN),
4775 writes_SPDYNPN,
4776 arraysize(writes_SPDYNPN)));
[email protected]b261d0e2010-08-02 19:13:244777 break;
4778 case SPDYNOSSL:
[email protected]a1595312012-01-22 03:25:044779 data_proxy.reset(new OrderedSocketData(reads_SPDYNOSSL,
4780 arraysize(reads_SPDYNOSSL),
4781 writes_SPDYNOSSL,
4782 arraysize(writes_SPDYNOSSL)));
[email protected]b261d0e2010-08-02 19:13:244783 break;
4784 case SPDYSSL:
[email protected]a1595312012-01-22 03:25:044785 data_proxy.reset(new OrderedSocketData(reads_SPDYSSL,
4786 arraysize(reads_SPDYSSL),
4787 writes_SPDYSSL,
4788 arraysize(writes_SPDYSSL)));
[email protected]b261d0e2010-08-02 19:13:244789 break;
4790 default:
4791 NOTREACHED();
4792 }
4793
4794 // Create another request to www.google.com, but this time through a proxy.
4795 HttpRequestInfo request_proxy;
4796 request_proxy.method = "GET";
4797 request_proxy.url = GURL("http://www.google.com/foo.dat");
4798 request_proxy.load_flags = 0;
[email protected]bb88e1d32013-05-03 23:11:074799 scoped_ptr<SpdySessionDependencies> ssd_proxy(
[email protected]513963e2013-06-15 01:53:044800 CreateSpdySessionDependencies(GetParam()));
[email protected]b261d0e2010-08-02 19:13:244801 // Ensure that this transaction uses the same SpdySessionPool.
[email protected]ad8e04a2010-11-01 04:16:274802 scoped_refptr<HttpNetworkSession> session_proxy(
4803 SpdySessionDependencies::SpdyCreateSession(ssd_proxy.get()));
[email protected]262eec82013-03-19 21:01:364804 NormalSpdyTransactionHelper helper_proxy(request_proxy, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504805 BoundNetLog(), GetParam(), NULL);
[email protected]87bfa3f2010-09-30 14:54:564806 HttpNetworkSessionPeer session_peer(session_proxy);
[email protected]6104ea5d2011-04-27 21:37:124807 scoped_ptr<net::ProxyService> proxy_service(
[email protected]87bfa3f2010-09-30 14:54:564808 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
[email protected]6104ea5d2011-04-27 21:37:124809 session_peer.SetProxyService(proxy_service.get());
[email protected]b261d0e2010-08-02 19:13:244810 helper_proxy.session_deps().swap(ssd_proxy);
[email protected]19ec8a72010-08-23 03:38:234811 helper_proxy.SetSession(session_proxy);
[email protected]b261d0e2010-08-02 19:13:244812 helper_proxy.RunPreTestSetup();
4813 helper_proxy.AddData(data_proxy.get());
4814
4815 HttpNetworkTransaction* trans_proxy = helper_proxy.trans();
[email protected]49639fa2011-12-20 23:22:414816 TestCompletionCallback callback_proxy;
4817 int rv = trans_proxy->Start(
4818 &request_proxy, callback_proxy.callback(), BoundNetLog());
[email protected]b261d0e2010-08-02 19:13:244819 EXPECT_EQ(ERR_IO_PENDING, rv);
4820 rv = callback_proxy.WaitForResult();
4821 EXPECT_EQ(0, rv);
4822
4823 HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo();
[email protected]90499482013-06-01 00:39:504824 EXPECT_TRUE(response_proxy.headers.get() != NULL);
[email protected]b261d0e2010-08-02 19:13:244825 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy.headers->GetStatusLine());
4826
4827 std::string response_data;
4828 ASSERT_EQ(OK, ReadTransaction(trans_proxy, &response_data));
4829 EXPECT_EQ("hello!", response_data);
4830
[email protected]dd54bd82012-07-19 23:44:574831 data.CompleteRead();
[email protected]b261d0e2010-08-02 19:13:244832 helper_proxy.VerifyDataConsumed();
4833}
4834
[email protected]58cebf8f2010-07-31 19:20:164835// When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
4836// on a new connection, if the connection was previously known to be good.
4837// This can happen when a server reboots without saying goodbye, or when
4838// we're behind a NAT that masked the RST.
[email protected]513963e2013-06-15 01:53:044839TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
[email protected]513963e2013-06-15 01:53:044840 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4841 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]58cebf8f2010-07-31 19:20:164842 MockRead reads[] = {
4843 CreateMockRead(*resp),
4844 CreateMockRead(*body),
[email protected]8ddf8322012-02-23 18:08:064845 MockRead(ASYNC, ERR_IO_PENDING),
4846 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]58cebf8f2010-07-31 19:20:164847 };
4848
4849 MockRead reads2[] = {
4850 CreateMockRead(*resp),
4851 CreateMockRead(*body),
[email protected]8ddf8322012-02-23 18:08:064852 MockRead(ASYNC, 0, 0) // EOF
[email protected]58cebf8f2010-07-31 19:20:164853 };
4854
4855 // This test has a couple of variants.
4856 enum {
4857 // Induce the RST while waiting for our transaction to send.
4858 VARIANT_RST_DURING_SEND_COMPLETION,
4859 // Induce the RST while waiting for our transaction to read.
4860 // In this case, the send completed - everything copied into the SNDBUF.
4861 VARIANT_RST_DURING_READ_COMPLETION
4862 };
4863
4864 for (int variant = VARIANT_RST_DURING_SEND_COMPLETION;
4865 variant <= VARIANT_RST_DURING_READ_COMPLETION;
4866 ++variant) {
[email protected]dd54bd82012-07-19 23:44:574867 DelayedSocketData data1(1, reads, arraysize(reads), NULL, 0);
[email protected]58cebf8f2010-07-31 19:20:164868
[email protected]dd54bd82012-07-19 23:44:574869 DelayedSocketData data2(1, reads2, arraysize(reads2), NULL, 0);
[email protected]58cebf8f2010-07-31 19:20:164870
[email protected]262eec82013-03-19 21:01:364871 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504872 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:574873 helper.AddData(&data1);
4874 helper.AddData(&data2);
[email protected]58cebf8f2010-07-31 19:20:164875 helper.RunPreTestSetup();
4876
4877 for (int i = 0; i < 2; ++i) {
4878 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]90499482013-06-01 00:39:504879 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]58cebf8f2010-07-31 19:20:164880
[email protected]49639fa2011-12-20 23:22:414881 TestCompletionCallback callback;
4882 int rv = trans->Start(
4883 &helper.request(), callback.callback(), BoundNetLog());
[email protected]58cebf8f2010-07-31 19:20:164884 EXPECT_EQ(ERR_IO_PENDING, rv);
4885 // On the second transaction, we trigger the RST.
4886 if (i == 1) {
4887 if (variant == VARIANT_RST_DURING_READ_COMPLETION) {
4888 // Writes to the socket complete asynchronously on SPDY by running
4889 // through the message loop. Complete the write here.
[email protected]fc9d88472013-08-14 02:31:174890 base::RunLoop().RunUntilIdle();
[email protected]58cebf8f2010-07-31 19:20:164891 }
4892
4893 // Now schedule the ERR_CONNECTION_RESET.
[email protected]dd54bd82012-07-19 23:44:574894 EXPECT_EQ(3u, data1.read_index());
4895 data1.CompleteRead();
4896 EXPECT_EQ(4u, data1.read_index());
[email protected]58cebf8f2010-07-31 19:20:164897 }
4898 rv = callback.WaitForResult();
4899 EXPECT_EQ(OK, rv);
4900
4901 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]351ab642010-08-05 16:55:314902 ASSERT_TRUE(response != NULL);
[email protected]90499482013-06-01 00:39:504903 EXPECT_TRUE(response->headers.get() != NULL);
[email protected]58cebf8f2010-07-31 19:20:164904 EXPECT_TRUE(response->was_fetched_via_spdy);
4905 std::string response_data;
4906 rv = ReadTransaction(trans.get(), &response_data);
4907 EXPECT_EQ(OK, rv);
4908 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4909 EXPECT_EQ("hello!", response_data);
4910 }
4911
4912 helper.VerifyDataConsumed();
4913 }
4914}
[email protected]1f418ee2010-10-16 19:46:564915
4916// Test that turning SPDY on and off works properly.
[email protected]513963e2013-06-15 01:53:044917TEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) {
[email protected]d7599122014-05-24 03:37:234918 HttpStreamFactory::set_spdy_enabled(true);
[email protected]cdf8f7e72013-05-23 10:56:464919 scoped_ptr<SpdyFrame> req(
4920 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]1f418ee2010-10-16 19:46:564921 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
4922
[email protected]513963e2013-06-15 01:53:044923 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4924 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]1f418ee2010-10-16 19:46:564925 MockRead spdy_reads[] = {
4926 CreateMockRead(*resp),
4927 CreateMockRead(*body),
[email protected]8ddf8322012-02-23 18:08:064928 MockRead(ASYNC, 0, 0) // EOF
[email protected]1f418ee2010-10-16 19:46:564929 };
4930
[email protected]dd54bd82012-07-19 23:44:574931 DelayedSocketData data(1, spdy_reads, arraysize(spdy_reads),
4932 spdy_writes, arraysize(spdy_writes));
[email protected]262eec82013-03-19 21:01:364933 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504934 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:574935 helper.RunToCompletion(&data);
[email protected]1f418ee2010-10-16 19:46:564936 TransactionHelperResult out = helper.output();
4937 EXPECT_EQ(OK, out.rv);
4938 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4939 EXPECT_EQ("hello!", out.response_data);
4940
4941 net::HttpStreamFactory::set_spdy_enabled(false);
4942 MockRead http_reads[] = {
4943 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4944 MockRead("hello from http"),
[email protected]8ddf8322012-02-23 18:08:064945 MockRead(SYNCHRONOUS, OK),
[email protected]1f418ee2010-10-16 19:46:564946 };
[email protected]dd54bd82012-07-19 23:44:574947 DelayedSocketData data2(1, http_reads, arraysize(http_reads), NULL, 0);
[email protected]262eec82013-03-19 21:01:364948 NormalSpdyTransactionHelper helper2(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:504949 BoundNetLog(), GetParam(), NULL);
[email protected]1f418ee2010-10-16 19:46:564950 helper2.SetSpdyDisabled();
[email protected]dd54bd82012-07-19 23:44:574951 helper2.RunToCompletion(&data2);
[email protected]1f418ee2010-10-16 19:46:564952 TransactionHelperResult out2 = helper2.output();
4953 EXPECT_EQ(OK, out2.rv);
4954 EXPECT_EQ("HTTP/1.1 200 OK", out2.status_line);
4955 EXPECT_EQ("hello from http", out2.response_data);
4956
4957 net::HttpStreamFactory::set_spdy_enabled(true);
4958}
[email protected]018aabc2010-10-29 16:16:594959
4960// Tests that Basic authentication works over SPDY
[email protected]513963e2013-06-15 01:53:044961TEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) {
[email protected]018aabc2010-10-29 16:16:594962 net::HttpStreamFactory::set_spdy_enabled(true);
4963
4964 // The first request will be a bare GET, the second request will be a
4965 // GET with an Authorization header.
[email protected]ff98d7f02012-03-22 21:44:194966 scoped_ptr<SpdyFrame> req_get(
[email protected]cdf8f7e72013-05-23 10:56:464967 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]018aabc2010-10-29 16:16:594968 const char* const kExtraAuthorizationHeaders[] = {
[email protected]cdf8f7e72013-05-23 10:56:464969 "authorization", "Basic Zm9vOmJhcg=="
[email protected]018aabc2010-10-29 16:16:594970 };
[email protected]ff98d7f02012-03-22 21:44:194971 scoped_ptr<SpdyFrame> req_get_authorization(
[email protected]cdf8f7e72013-05-23 10:56:464972 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
4973 arraysize(kExtraAuthorizationHeaders) / 2,
4974 false, 3, LOWEST, true));
[email protected]018aabc2010-10-29 16:16:594975 MockWrite spdy_writes[] = {
4976 CreateMockWrite(*req_get, 1),
4977 CreateMockWrite(*req_get_authorization, 4),
4978 };
4979
4980 // The first response is a 401 authentication challenge, and the second
4981 // response will be a 200 response since the second request includes a valid
4982 // Authorization header.
4983 const char* const kExtraAuthenticationHeaders[] = {
[email protected]fb9e4312012-02-17 06:27:264984 "www-authenticate",
[email protected]018aabc2010-10-29 16:16:594985 "Basic realm=\"MyRealm\""
4986 };
[email protected]ff98d7f02012-03-22 21:44:194987 scoped_ptr<SpdyFrame> resp_authentication(
[email protected]513963e2013-06-15 01:53:044988 spdy_util_.ConstructSpdySynReplyError(
[email protected]018aabc2010-10-29 16:16:594989 "401 Authentication Required",
[email protected]d08358502010-12-03 22:04:034990 kExtraAuthenticationHeaders,
4991 arraysize(kExtraAuthenticationHeaders) / 2,
[email protected]018aabc2010-10-29 16:16:594992 1));
[email protected]ff98d7f02012-03-22 21:44:194993 scoped_ptr<SpdyFrame> body_authentication(
[email protected]513963e2013-06-15 01:53:044994 spdy_util_.ConstructSpdyBodyFrame(1, true));
4995 scoped_ptr<SpdyFrame> resp_data(
4996 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4997 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]018aabc2010-10-29 16:16:594998 MockRead spdy_reads[] = {
4999 CreateMockRead(*resp_authentication, 2),
5000 CreateMockRead(*body_authentication, 3),
5001 CreateMockRead(*resp_data, 5),
5002 CreateMockRead(*body_data, 6),
[email protected]8ddf8322012-02-23 18:08:065003 MockRead(ASYNC, 0, 7),
[email protected]018aabc2010-10-29 16:16:595004 };
5005
[email protected]dd54bd82012-07-19 23:44:575006 OrderedSocketData data(spdy_reads, arraysize(spdy_reads),
5007 spdy_writes, arraysize(spdy_writes));
[email protected]018aabc2010-10-29 16:16:595008 HttpRequestInfo request(CreateGetRequest());
5009 BoundNetLog net_log;
[email protected]262eec82013-03-19 21:01:365010 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5011 net_log, GetParam(), NULL);
[email protected]018aabc2010-10-29 16:16:595012
5013 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:575014 helper.AddData(&data);
[email protected]018aabc2010-10-29 16:16:595015 HttpNetworkTransaction* trans = helper.trans();
[email protected]49639fa2011-12-20 23:22:415016 TestCompletionCallback callback;
5017 const int rv_start = trans->Start(&request, callback.callback(), net_log);
[email protected]018aabc2010-10-29 16:16:595018 EXPECT_EQ(ERR_IO_PENDING, rv_start);
[email protected]49639fa2011-12-20 23:22:415019 const int rv_start_complete = callback.WaitForResult();
[email protected]018aabc2010-10-29 16:16:595020 EXPECT_EQ(OK, rv_start_complete);
5021
5022 // Make sure the response has an auth challenge.
5023 const HttpResponseInfo* const response_start = trans->GetResponseInfo();
5024 ASSERT_TRUE(response_start != NULL);
[email protected]90499482013-06-01 00:39:505025 ASSERT_TRUE(response_start->headers.get() != NULL);
[email protected]018aabc2010-10-29 16:16:595026 EXPECT_EQ(401, response_start->headers->response_code());
5027 EXPECT_TRUE(response_start->was_fetched_via_spdy);
[email protected]79cb5c12011-09-12 13:12:045028 AuthChallengeInfo* auth_challenge = response_start->auth_challenge.get();
5029 ASSERT_TRUE(auth_challenge != NULL);
5030 EXPECT_FALSE(auth_challenge->is_proxy);
5031 EXPECT_EQ("basic", auth_challenge->scheme);
5032 EXPECT_EQ("MyRealm", auth_challenge->realm);
[email protected]018aabc2010-10-29 16:16:595033
5034 // Restart with a username/password.
[email protected]ad65a3e2013-12-25 18:18:015035 AuthCredentials credentials(base::ASCIIToUTF16("foo"),
5036 base::ASCIIToUTF16("bar"));
[email protected]49639fa2011-12-20 23:22:415037 TestCompletionCallback callback_restart;
5038 const int rv_restart = trans->RestartWithAuth(
5039 credentials, callback_restart.callback());
[email protected]018aabc2010-10-29 16:16:595040 EXPECT_EQ(ERR_IO_PENDING, rv_restart);
5041 const int rv_restart_complete = callback_restart.WaitForResult();
5042 EXPECT_EQ(OK, rv_restart_complete);
5043 // TODO(cbentzel): This is actually the same response object as before, but
5044 // data has changed.
5045 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
5046 ASSERT_TRUE(response_restart != NULL);
[email protected]90499482013-06-01 00:39:505047 ASSERT_TRUE(response_restart->headers.get() != NULL);
[email protected]018aabc2010-10-29 16:16:595048 EXPECT_EQ(200, response_restart->headers->response_code());
5049 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
5050}
5051
[email protected]513963e2013-06-15 01:53:045052TEST_P(SpdyNetworkTransactionTest, ServerPushWithHeaders) {
[email protected]cdf8f7e72013-05-23 10:56:465053 scoped_ptr<SpdyFrame> stream1_syn(
5054 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:045055 scoped_ptr<SpdyFrame> stream1_body(
5056 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d08358502010-12-03 22:04:035057 MockWrite writes[] = {
5058 CreateMockWrite(*stream1_syn, 1),
5059 };
5060
[email protected]513963e2013-06-15 01:53:045061 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5062 spdy_util_.AddUrlToHeaderBlock(
5063 "http://www.google.com/foo.dat", initial_headers.get());
[email protected]4bd46222013-05-14 19:32:235064 scoped_ptr<SpdyFrame> stream2_syn(
[email protected]0338bc62014-06-20 17:09:565065 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
[email protected]513963e2013-06-15 01:53:045066
5067 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5068 (*late_headers)["hello"] = "bye";
5069 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5070 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
[email protected]4bd46222013-05-14 19:32:235071 scoped_ptr<SpdyFrame> stream2_headers(
[email protected]513963e2013-06-15 01:53:045072 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235073 false,
5074 2,
5075 LOWEST,
5076 HEADERS,
5077 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235078 0));
[email protected]d08358502010-12-03 22:04:035079
[email protected]ff98d7f02012-03-22 21:44:195080 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045081 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8a0fc822013-06-27 20:52:435082 const char kPushedData[] = "pushed";
5083 scoped_ptr<SpdyFrame> stream2_body(
5084 spdy_util_.ConstructSpdyBodyFrame(
5085 2, kPushedData, strlen(kPushedData), true));
[email protected]d08358502010-12-03 22:04:035086 MockRead reads[] = {
5087 CreateMockRead(*stream1_reply, 2),
5088 CreateMockRead(*stream2_syn, 3),
5089 CreateMockRead(*stream2_headers, 4),
[email protected]8ddf8322012-02-23 18:08:065090 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
[email protected]8a0fc822013-06-27 20:52:435091 CreateMockRead(*stream2_body, 5),
[email protected]8ddf8322012-02-23 18:08:065092 MockRead(ASYNC, ERR_IO_PENDING, 7), // Force a pause
[email protected]d08358502010-12-03 22:04:035093 };
5094
5095 HttpResponseInfo response;
5096 HttpResponseInfo response2;
5097 std::string expected_push_result("pushed");
[email protected]dd54bd82012-07-19 23:44:575098 OrderedSocketData data(reads, arraysize(reads),
5099 writes, arraysize(writes));
5100 RunServerPushTest(&data,
[email protected]d08358502010-12-03 22:04:035101 &response,
5102 &response2,
5103 expected_push_result);
5104
5105 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:505106 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]d08358502010-12-03 22:04:035107 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5108
5109 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:505110 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]d08358502010-12-03 22:04:035111 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5112}
5113
[email protected]513963e2013-06-15 01:53:045114TEST_P(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
[email protected]d08358502010-12-03 22:04:035115 // We push a stream and attempt to claim it before the headers come down.
[email protected]cdf8f7e72013-05-23 10:56:465116 scoped_ptr<SpdyFrame> stream1_syn(
5117 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:045118 scoped_ptr<SpdyFrame> stream1_body(
5119 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d08358502010-12-03 22:04:035120 MockWrite writes[] = {
[email protected]8ddf8322012-02-23 18:08:065121 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
[email protected]d08358502010-12-03 22:04:035122 };
5123
[email protected]513963e2013-06-15 01:53:045124 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5125 spdy_util_.AddUrlToHeaderBlock(
5126 "http://www.google.com/foo.dat", initial_headers.get());
[email protected]4bd46222013-05-14 19:32:235127 scoped_ptr<SpdyFrame> stream2_syn(
[email protected]0338bc62014-06-20 17:09:565128 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
[email protected]513963e2013-06-15 01:53:045129
5130 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5131 (*late_headers)["hello"] = "bye";
5132 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5133 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
[email protected]4bd46222013-05-14 19:32:235134 scoped_ptr<SpdyFrame> stream2_headers(
[email protected]513963e2013-06-15 01:53:045135 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235136 false,
5137 2,
5138 LOWEST,
5139 HEADERS,
5140 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235141 0));
[email protected]d08358502010-12-03 22:04:035142
[email protected]ff98d7f02012-03-22 21:44:195143 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045144 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8a0fc822013-06-27 20:52:435145 const char kPushedData[] = "pushed";
5146 scoped_ptr<SpdyFrame> stream2_body(
5147 spdy_util_.ConstructSpdyBodyFrame(
5148 2, kPushedData, strlen(kPushedData), true));
[email protected]d08358502010-12-03 22:04:035149 MockRead reads[] = {
5150 CreateMockRead(*stream1_reply, 1),
5151 CreateMockRead(*stream2_syn, 2),
5152 CreateMockRead(*stream1_body, 3),
5153 CreateMockRead(*stream2_headers, 4),
[email protected]8a0fc822013-06-27 20:52:435154 CreateMockRead(*stream2_body, 5),
[email protected]d55b30a2012-07-21 00:35:395155 MockRead(ASYNC, 0, 6), // EOF
[email protected]d08358502010-12-03 22:04:035156 };
5157
5158 HttpResponseInfo response;
5159 HttpResponseInfo response2;
5160 std::string expected_push_result("pushed");
[email protected]dd54bd82012-07-19 23:44:575161 DeterministicSocketData data(reads, arraysize(reads),
5162 writes, arraysize(writes));
[email protected]d08358502010-12-03 22:04:035163
[email protected]262eec82013-03-19 21:01:365164 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505165 BoundNetLog(), GetParam(), NULL);
[email protected]d08358502010-12-03 22:04:035166 helper.SetDeterministic();
[email protected]dd54bd82012-07-19 23:44:575167 helper.AddDeterministicData(&data);
[email protected]d08358502010-12-03 22:04:035168 helper.RunPreTestSetup();
5169
5170 HttpNetworkTransaction* trans = helper.trans();
5171
5172 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5173 // and the body of the primary stream, but before we've received the HEADERS
5174 // for the pushed stream.
[email protected]dd54bd82012-07-19 23:44:575175 data.SetStop(3);
[email protected]d08358502010-12-03 22:04:035176
5177 // Start the transaction.
[email protected]49639fa2011-12-20 23:22:415178 TestCompletionCallback callback;
5179 int rv = trans->Start(
5180 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]d08358502010-12-03 22:04:035181 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]dd54bd82012-07-19 23:44:575182 data.Run();
[email protected]d08358502010-12-03 22:04:035183 rv = callback.WaitForResult();
5184 EXPECT_EQ(0, rv);
5185
5186 // Request the pushed path. At this point, we've received the push, but the
5187 // headers are not yet complete.
5188 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:505189 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]49639fa2011-12-20 23:22:415190 rv = trans2->Start(
5191 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
[email protected]d08358502010-12-03 22:04:035192 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]dd54bd82012-07-19 23:44:575193 data.RunFor(3);
[email protected]fc9d88472013-08-14 02:31:175194 base::RunLoop().RunUntilIdle();
[email protected]d08358502010-12-03 22:04:035195
5196 // Read the server push body.
5197 std::string result2;
[email protected]dd54bd82012-07-19 23:44:575198 ReadResult(trans2.get(), &data, &result2);
[email protected]d08358502010-12-03 22:04:035199 // Read the response body.
5200 std::string result;
[email protected]dd54bd82012-07-19 23:44:575201 ReadResult(trans, &data, &result);
[email protected]d08358502010-12-03 22:04:035202
[email protected]d08358502010-12-03 22:04:035203 // Verify that the received push data is same as the expected push data.
5204 EXPECT_EQ(result2.compare(expected_push_result), 0)
5205 << "Received data: "
5206 << result2
5207 << "||||| Expected data: "
5208 << expected_push_result;
5209
5210 // Verify the SYN_REPLY.
5211 // Copy the response info, because trans goes away.
5212 response = *trans->GetResponseInfo();
5213 response2 = *trans2->GetResponseInfo();
5214
5215 VerifyStreamsClosed(helper);
5216
5217 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:505218 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]d08358502010-12-03 22:04:035219 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5220
5221 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:505222 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]d08358502010-12-03 22:04:035223 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
[email protected]d55b30a2012-07-21 00:35:395224
5225 // Read the final EOF (which will close the session)
5226 data.RunFor(1);
5227
5228 // Verify that we consumed all test data.
5229 EXPECT_TRUE(data.at_read_eof());
5230 EXPECT_TRUE(data.at_write_eof());
[email protected]d08358502010-12-03 22:04:035231}
5232
[email protected]6cd63ba2014-06-12 16:14:565233// TODO(baranovich): HTTP 2 does not allow multiple HEADERS frames
[email protected]513963e2013-06-15 01:53:045234TEST_P(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) {
[email protected]d08358502010-12-03 22:04:035235 // We push a stream and attempt to claim it before the headers come down.
[email protected]cdf8f7e72013-05-23 10:56:465236 scoped_ptr<SpdyFrame> stream1_syn(
5237 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:045238 scoped_ptr<SpdyFrame> stream1_body(
5239 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d08358502010-12-03 22:04:035240 MockWrite writes[] = {
[email protected]8ddf8322012-02-23 18:08:065241 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
[email protected]d08358502010-12-03 22:04:035242 };
5243
[email protected]513963e2013-06-15 01:53:045244 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
[email protected]0338bc62014-06-20 17:09:565245 if (spdy_util_.spdy_version() < SPDY4) {
5246 // In SPDY4 PUSH_PROMISE headers won't show up in the response headers.
5247 (*initial_headers)["alpha"] = "beta";
5248 }
[email protected]513963e2013-06-15 01:53:045249 spdy_util_.AddUrlToHeaderBlock(
5250 "http://www.google.com/foo.dat", initial_headers.get());
[email protected]4bd46222013-05-14 19:32:235251 scoped_ptr<SpdyFrame> stream2_syn(
[email protected]0338bc62014-06-20 17:09:565252 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
[email protected]513963e2013-06-15 01:53:045253
5254 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5255 (*middle_headers)["hello"] = "bye";
[email protected]4bd46222013-05-14 19:32:235256 scoped_ptr<SpdyFrame> stream2_headers1(
[email protected]513963e2013-06-15 01:53:045257 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235258 false,
5259 2,
5260 LOWEST,
5261 HEADERS,
5262 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235263 0));
[email protected]513963e2013-06-15 01:53:045264
5265 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5266 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
[email protected]601e03f12014-04-06 16:26:395267 if (spdy_util_.spdy_version() < SPDY4) {
5268 // SPDY4/HTTP2 eliminates use of the :version header.
5269 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5270 }
[email protected]4bd46222013-05-14 19:32:235271 scoped_ptr<SpdyFrame> stream2_headers2(
[email protected]513963e2013-06-15 01:53:045272 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235273 false,
5274 2,
5275 LOWEST,
5276 HEADERS,
5277 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235278 0));
[email protected]d08358502010-12-03 22:04:035279
[email protected]ff98d7f02012-03-22 21:44:195280 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045281 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8a0fc822013-06-27 20:52:435282 const char kPushedData[] = "pushed";
5283 scoped_ptr<SpdyFrame> stream2_body(
5284 spdy_util_.ConstructSpdyBodyFrame(
5285 2, kPushedData, strlen(kPushedData), true));
[email protected]d08358502010-12-03 22:04:035286 MockRead reads[] = {
5287 CreateMockRead(*stream1_reply, 1),
5288 CreateMockRead(*stream2_syn, 2),
5289 CreateMockRead(*stream1_body, 3),
5290 CreateMockRead(*stream2_headers1, 4),
5291 CreateMockRead(*stream2_headers2, 5),
[email protected]8a0fc822013-06-27 20:52:435292 CreateMockRead(*stream2_body, 6),
[email protected]d55b30a2012-07-21 00:35:395293 MockRead(ASYNC, 0, 7), // EOF
[email protected]d08358502010-12-03 22:04:035294 };
5295
5296 HttpResponseInfo response;
5297 HttpResponseInfo response2;
5298 std::string expected_push_result("pushed");
[email protected]dd54bd82012-07-19 23:44:575299 DeterministicSocketData data(reads, arraysize(reads),
5300 writes, arraysize(writes));
[email protected]d08358502010-12-03 22:04:035301
[email protected]262eec82013-03-19 21:01:365302 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505303 BoundNetLog(), GetParam(), NULL);
[email protected]d08358502010-12-03 22:04:035304 helper.SetDeterministic();
[email protected]dd54bd82012-07-19 23:44:575305 helper.AddDeterministicData(&data);
[email protected]d08358502010-12-03 22:04:035306 helper.RunPreTestSetup();
5307
5308 HttpNetworkTransaction* trans = helper.trans();
5309
5310 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5311 // the first HEADERS frame, and the body of the primary stream, but before
5312 // we've received the final HEADERS for the pushed stream.
[email protected]dd54bd82012-07-19 23:44:575313 data.SetStop(4);
[email protected]d08358502010-12-03 22:04:035314
5315 // Start the transaction.
[email protected]49639fa2011-12-20 23:22:415316 TestCompletionCallback callback;
5317 int rv = trans->Start(
5318 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]d08358502010-12-03 22:04:035319 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]dd54bd82012-07-19 23:44:575320 data.Run();
[email protected]d08358502010-12-03 22:04:035321 rv = callback.WaitForResult();
5322 EXPECT_EQ(0, rv);
5323
5324 // Request the pushed path. At this point, we've received the push, but the
5325 // headers are not yet complete.
5326 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:505327 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]49639fa2011-12-20 23:22:415328 rv = trans2->Start(
5329 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
[email protected]d08358502010-12-03 22:04:035330 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]dd54bd82012-07-19 23:44:575331 data.RunFor(3);
[email protected]fc9d88472013-08-14 02:31:175332 base::RunLoop().RunUntilIdle();
[email protected]d08358502010-12-03 22:04:035333
5334 // Read the server push body.
5335 std::string result2;
[email protected]dd54bd82012-07-19 23:44:575336 ReadResult(trans2.get(), &data, &result2);
[email protected]d08358502010-12-03 22:04:035337 // Read the response body.
5338 std::string result;
[email protected]dd54bd82012-07-19 23:44:575339 ReadResult(trans, &data, &result);
[email protected]d08358502010-12-03 22:04:035340
[email protected]d08358502010-12-03 22:04:035341 // Verify that the received push data is same as the expected push data.
[email protected]6d116e1a2013-06-24 07:42:155342 EXPECT_EQ(expected_push_result, result2);
[email protected]d08358502010-12-03 22:04:035343
5344 // Verify the SYN_REPLY.
5345 // Copy the response info, because trans goes away.
5346 response = *trans->GetResponseInfo();
5347 response2 = *trans2->GetResponseInfo();
5348
5349 VerifyStreamsClosed(helper);
5350
5351 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:505352 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]d08358502010-12-03 22:04:035353 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5354
5355 // Verify the pushed stream.
[email protected]90499482013-06-01 00:39:505356 EXPECT_TRUE(response2.headers.get() != NULL);
[email protected]d08358502010-12-03 22:04:035357 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5358
[email protected]6cd63ba2014-06-12 16:14:565359 // Verify we got all the headers from all header blocks.
[email protected]0338bc62014-06-20 17:09:565360 if (spdy_util_.spdy_version() < SPDY4)
5361 EXPECT_TRUE(response2.headers->HasHeaderValue("alpha", "beta"));
[email protected]d08358502010-12-03 22:04:035362 EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye"));
5363 EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200"));
[email protected]d55b30a2012-07-21 00:35:395364
5365 // Read the final EOF (which will close the session)
5366 data.RunFor(1);
5367
5368 // Verify that we consumed all test data.
5369 EXPECT_TRUE(data.at_read_eof());
5370 EXPECT_TRUE(data.at_write_eof());
[email protected]d08358502010-12-03 22:04:035371}
5372
[email protected]513963e2013-06-15 01:53:045373TEST_P(SpdyNetworkTransactionTest, ServerPushWithNoStatusHeaderFrames) {
[email protected]5c6908e2012-08-06 18:53:475374 // We push a stream and attempt to claim it before the headers come down.
[email protected]cdf8f7e72013-05-23 10:56:465375 scoped_ptr<SpdyFrame> stream1_syn(
5376 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]513963e2013-06-15 01:53:045377 scoped_ptr<SpdyFrame> stream1_body(
5378 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]5c6908e2012-08-06 18:53:475379 MockWrite writes[] = {
5380 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5381 };
5382
[email protected]513963e2013-06-15 01:53:045383 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5384 spdy_util_.AddUrlToHeaderBlock(
5385 "http://www.google.com/foo.dat", initial_headers.get());
[email protected]4bd46222013-05-14 19:32:235386 scoped_ptr<SpdyFrame> stream2_syn(
[email protected]0338bc62014-06-20 17:09:565387 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
[email protected]513963e2013-06-15 01:53:045388
5389 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5390 (*middle_headers)["hello"] = "bye";
[email protected]4bd46222013-05-14 19:32:235391 scoped_ptr<SpdyFrame> stream2_headers1(
[email protected]513963e2013-06-15 01:53:045392 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235393 false,
5394 2,
5395 LOWEST,
5396 HEADERS,
5397 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235398 0));
[email protected]5c6908e2012-08-06 18:53:475399
5400 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045401 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8a0fc822013-06-27 20:52:435402 const char kPushedData[] = "pushed";
5403 scoped_ptr<SpdyFrame> stream2_body(
5404 spdy_util_.ConstructSpdyBodyFrame(
5405 2, kPushedData, strlen(kPushedData), true));
[email protected]5c6908e2012-08-06 18:53:475406 MockRead reads[] = {
5407 CreateMockRead(*stream1_reply, 1),
5408 CreateMockRead(*stream2_syn, 2),
5409 CreateMockRead(*stream1_body, 3),
5410 CreateMockRead(*stream2_headers1, 4),
[email protected]8a0fc822013-06-27 20:52:435411 CreateMockRead(*stream2_body, 5),
[email protected]5c6908e2012-08-06 18:53:475412 MockRead(ASYNC, 0, 6), // EOF
5413 };
5414
5415 DeterministicSocketData data(reads, arraysize(reads),
5416 writes, arraysize(writes));
5417
[email protected]262eec82013-03-19 21:01:365418 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]5c6908e2012-08-06 18:53:475419 BoundNetLog(), GetParam(), NULL);
5420 helper.SetDeterministic();
5421 helper.AddDeterministicData(&data);
5422 helper.RunPreTestSetup();
5423
5424 HttpNetworkTransaction* trans = helper.trans();
5425
5426 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5427 // the first HEADERS frame, and the body of the primary stream, but before
5428 // we've received the final HEADERS for the pushed stream.
5429 data.SetStop(4);
5430
5431 // Start the transaction.
5432 TestCompletionCallback callback;
5433 int rv = trans->Start(
5434 &CreateGetRequest(), callback.callback(), BoundNetLog());
5435 EXPECT_EQ(ERR_IO_PENDING, rv);
5436 data.Run();
5437 rv = callback.WaitForResult();
5438 EXPECT_EQ(0, rv);
5439
5440 // Request the pushed path. At this point, we've received the push, but the
5441 // headers are not yet complete.
5442 scoped_ptr<HttpNetworkTransaction> trans2(
[email protected]90499482013-06-01 00:39:505443 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
[email protected]5c6908e2012-08-06 18:53:475444 rv = trans2->Start(
5445 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5446 EXPECT_EQ(ERR_IO_PENDING, rv);
5447 data.RunFor(2);
[email protected]fc9d88472013-08-14 02:31:175448 base::RunLoop().RunUntilIdle();
[email protected]5c6908e2012-08-06 18:53:475449
5450 // Read the server push body.
5451 std::string result2;
5452 ReadResult(trans2.get(), &data, &result2);
5453 // Read the response body.
5454 std::string result;
5455 ReadResult(trans, &data, &result);
5456 EXPECT_EQ("hello!", result);
5457
5458 // Verify that we haven't received any push data.
5459 EXPECT_EQ("", result2);
5460
5461 // Verify the SYN_REPLY.
5462 // Copy the response info, because trans goes away.
5463 HttpResponseInfo response = *trans->GetResponseInfo();
5464 ASSERT_TRUE(trans2->GetResponseInfo() == NULL);
5465
5466 VerifyStreamsClosed(helper);
5467
5468 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:505469 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]5c6908e2012-08-06 18:53:475470 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5471
5472 // Read the final EOF (which will close the session).
5473 data.RunFor(1);
5474
5475 // Verify that we consumed all test data.
5476 EXPECT_TRUE(data.at_read_eof());
5477 EXPECT_TRUE(data.at_write_eof());
5478}
5479
[email protected]513963e2013-06-15 01:53:045480TEST_P(SpdyNetworkTransactionTest, SynReplyWithHeaders) {
[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[] = {
[email protected]745aa9c2014-06-27 02:21:295486 CreateMockWrite(*req), CreateMockWrite(*rst),
5487 };
[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, true));
[email protected]d08358502010-12-03 22:04:035504 MockRead reads[] = {
5505 CreateMockRead(*stream1_reply),
5506 CreateMockRead(*stream1_headers),
5507 CreateMockRead(*stream1_body),
[email protected]8ddf8322012-02-23 18:08:065508 MockRead(ASYNC, 0, 0) // EOF
[email protected]d08358502010-12-03 22:04:035509 };
5510
[email protected]dd54bd82012-07-19 23:44:575511 DelayedSocketData data(1, reads, arraysize(reads),
5512 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:365513 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505514 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:575515 helper.RunToCompletion(&data);
[email protected]d08358502010-12-03 22:04:035516 TransactionHelperResult out = helper.output();
[email protected]b771bb72013-06-24 09:55:415517 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]d08358502010-12-03 22:04:035518}
5519
[email protected]513963e2013-06-15 01:53:045520TEST_P(SpdyNetworkTransactionTest, SynReplyWithLateHeaders) {
[email protected]cdf8f7e72013-05-23 10:56:465521 scoped_ptr<SpdyFrame> req(
5522 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
[email protected]b771bb72013-06-24 09:55:415523 scoped_ptr<SpdyFrame> rst(
5524 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
5525 MockWrite writes[] = {
5526 CreateMockWrite(*req),
5527 CreateMockWrite(*rst),
5528 };
[email protected]d08358502010-12-03 22:04:035529
[email protected]4bd46222013-05-14 19:32:235530 scoped_ptr<SpdyFrame> stream1_reply(
[email protected]745aa9c2014-06-27 02:21:295531 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]513963e2013-06-15 01:53:045532
5533 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5534 (*late_headers)["hello"] = "bye";
[email protected]4bd46222013-05-14 19:32:235535 scoped_ptr<SpdyFrame> stream1_headers(
[email protected]513963e2013-06-15 01:53:045536 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
[email protected]4bd46222013-05-14 19:32:235537 false,
5538 1,
5539 LOWEST,
5540 HEADERS,
5541 CONTROL_FLAG_NONE,
[email protected]4bd46222013-05-14 19:32:235542 0));
[email protected]513963e2013-06-15 01:53:045543 scoped_ptr<SpdyFrame> stream1_body(
5544 spdy_util_.ConstructSpdyBodyFrame(1, false));
5545 scoped_ptr<SpdyFrame> stream1_body2(
5546 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]d08358502010-12-03 22:04:035547 MockRead reads[] = {
5548 CreateMockRead(*stream1_reply),
5549 CreateMockRead(*stream1_body),
5550 CreateMockRead(*stream1_headers),
5551 CreateMockRead(*stream1_body2),
[email protected]8ddf8322012-02-23 18:08:065552 MockRead(ASYNC, 0, 0) // EOF
[email protected]d08358502010-12-03 22:04:035553 };
5554
[email protected]dd54bd82012-07-19 23:44:575555 DelayedSocketData data(1, reads, arraysize(reads),
5556 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:365557 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505558 BoundNetLog(), GetParam(), NULL);
[email protected]dd54bd82012-07-19 23:44:575559 helper.RunToCompletion(&data);
[email protected]d08358502010-12-03 22:04:035560 TransactionHelperResult out = helper.output();
[email protected]b771bb72013-06-24 09:55:415561 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]d08358502010-12-03 22:04:035562}
5563
[email protected]513963e2013-06-15 01:53:045564TEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
[email protected]a7a265ef2010-12-08 18:05:575565 // In this test we want to verify that we can't accidentally push content
5566 // which can't be pushed by this content server.
5567 // This test assumes that:
5568 // - if we're requesting http://www.foo.com/barbaz
5569 // - the browser has made a connection to "www.foo.com".
5570
5571 // A list of the URL to fetch, followed by the URL being pushed.
5572 static const char* const kTestCases[] = {
5573 "http://www.google.com/foo.html",
5574 "http://www.google.com:81/foo.js", // Bad port
5575
5576 "http://www.google.com/foo.html",
5577 "https://www.google.com/foo.js", // Bad protocol
5578
5579 "http://www.google.com/foo.html",
5580 "ftp://www.google.com/foo.js", // Invalid Protocol
5581
5582 "http://www.google.com/foo.html",
5583 "http://blat.www.google.com/foo.js", // Cross subdomain
5584
5585 "http://www.google.com/foo.html",
5586 "http://www.foo.com/foo.js", // Cross domain
5587 };
5588
[email protected]b3f899332010-12-08 18:20:445589 for (size_t index = 0; index < arraysize(kTestCases); index += 2) {
[email protected]a7a265ef2010-12-08 18:05:575590 const char* url_to_fetch = kTestCases[index];
5591 const char* url_to_push = kTestCases[index + 1];
5592
[email protected]cdf8f7e72013-05-23 10:56:465593 scoped_ptr<SpdyFrame> stream1_syn(
5594 spdy_util_.ConstructSpdyGet(url_to_fetch, false, 1, LOWEST));
[email protected]513963e2013-06-15 01:53:045595 scoped_ptr<SpdyFrame> stream1_body(
5596 spdy_util_.ConstructSpdyBodyFrame(1, true));
[email protected]ff98d7f02012-03-22 21:44:195597 scoped_ptr<SpdyFrame> push_rst(
[email protected]c10b20852013-05-15 21:29:205598 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
[email protected]a7a265ef2010-12-08 18:05:575599 MockWrite writes[] = {
5600 CreateMockWrite(*stream1_syn, 1),
5601 CreateMockWrite(*push_rst, 4),
5602 };
5603
[email protected]ff98d7f02012-03-22 21:44:195604 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045605 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]ff98d7f02012-03-22 21:44:195606 scoped_ptr<SpdyFrame>
[email protected]513963e2013-06-15 01:53:045607 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
5608 0,
5609 2,
5610 1,
5611 url_to_push));
[email protected]8a0fc822013-06-27 20:52:435612 const char kPushedData[] = "pushed";
5613 scoped_ptr<SpdyFrame> stream2_body(
5614 spdy_util_.ConstructSpdyBodyFrame(
5615 2, kPushedData, strlen(kPushedData), true));
[email protected]ff98d7f02012-03-22 21:44:195616 scoped_ptr<SpdyFrame> rst(
[email protected]c10b20852013-05-15 21:29:205617 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
[email protected]a7a265ef2010-12-08 18:05:575618
5619 MockRead reads[] = {
5620 CreateMockRead(*stream1_reply, 2),
5621 CreateMockRead(*stream2_syn, 3),
[email protected]8ddf8322012-02-23 18:08:065622 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
[email protected]8a0fc822013-06-27 20:52:435623 CreateMockRead(*stream2_body, 6),
[email protected]8ddf8322012-02-23 18:08:065624 MockRead(ASYNC, ERR_IO_PENDING, 7), // Force a pause
[email protected]a7a265ef2010-12-08 18:05:575625 };
5626
5627 HttpResponseInfo response;
[email protected]dd54bd82012-07-19 23:44:575628 OrderedSocketData data(reads, arraysize(reads),
5629 writes, arraysize(writes));
[email protected]a7a265ef2010-12-08 18:05:575630
5631 HttpRequestInfo request;
5632 request.method = "GET";
5633 request.url = GURL(url_to_fetch);
5634 request.load_flags = 0;
[email protected]a7a265ef2010-12-08 18:05:575635
[email protected]7c6f7ba2012-04-03 04:09:295636 // Enable cross-origin push. Since we are not using a proxy, this should
5637 // not actually enable cross-origin SPDY push.
[email protected]61b4efc2012-04-27 18:12:505638 scoped_ptr<SpdySessionDependencies> session_deps(
[email protected]513963e2013-06-15 01:53:045639 CreateSpdySessionDependencies(GetParam()));
[email protected]61b4efc2012-04-27 18:12:505640 session_deps->trusted_spdy_proxy = "123.45.67.89:8080";
[email protected]262eec82013-03-19 21:01:365641 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505642 BoundNetLog(), GetParam(),
5643 session_deps.release());
5644 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:575645 helper.AddData(&data);
[email protected]7c6f7ba2012-04-03 04:09:295646
[email protected]a7a265ef2010-12-08 18:05:575647 HttpNetworkTransaction* trans = helper.trans();
5648
5649 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:415650 TestCompletionCallback callback;
[email protected]a7a265ef2010-12-08 18:05:575651
[email protected]49639fa2011-12-20 23:22:415652 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]a7a265ef2010-12-08 18:05:575653 EXPECT_EQ(ERR_IO_PENDING, rv);
5654 rv = callback.WaitForResult();
5655
5656 // Read the response body.
5657 std::string result;
[email protected]dd54bd82012-07-19 23:44:575658 ReadResult(trans, &data, &result);
[email protected]a7a265ef2010-12-08 18:05:575659
5660 // Verify that we consumed all test data.
[email protected]dd54bd82012-07-19 23:44:575661 EXPECT_TRUE(data.at_read_eof());
5662 EXPECT_TRUE(data.at_write_eof());
[email protected]a7a265ef2010-12-08 18:05:575663
5664 // Verify the SYN_REPLY.
5665 // Copy the response info, because trans goes away.
5666 response = *trans->GetResponseInfo();
5667
5668 VerifyStreamsClosed(helper);
5669
5670 // Verify the SYN_REPLY.
[email protected]90499482013-06-01 00:39:505671 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]a7a265ef2010-12-08 18:05:575672 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5673 }
5674}
5675
[email protected]513963e2013-06-15 01:53:045676TEST_P(SpdyNetworkTransactionTest, RetryAfterRefused) {
[email protected]721c0ce2011-10-13 02:41:005677 // Construct the request.
[email protected]cdf8f7e72013-05-23 10:56:465678 scoped_ptr<SpdyFrame> req(
5679 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5680 scoped_ptr<SpdyFrame> req2(
5681 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
[email protected]721c0ce2011-10-13 02:41:005682 MockWrite writes[] = {
5683 CreateMockWrite(*req, 1),
5684 CreateMockWrite(*req2, 3),
5685 };
5686
[email protected]ff98d7f02012-03-22 21:44:195687 scoped_ptr<SpdyFrame> refused(
[email protected]c10b20852013-05-15 21:29:205688 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
[email protected]513963e2013-06-15 01:53:045689 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5690 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(3, true));
[email protected]721c0ce2011-10-13 02:41:005691 MockRead reads[] = {
5692 CreateMockRead(*refused, 2),
5693 CreateMockRead(*resp, 4),
5694 CreateMockRead(*body, 5),
[email protected]8ddf8322012-02-23 18:08:065695 MockRead(ASYNC, 0, 6) // EOF
[email protected]721c0ce2011-10-13 02:41:005696 };
5697
[email protected]dd54bd82012-07-19 23:44:575698 OrderedSocketData data(reads, arraysize(reads),
5699 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:365700 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
[email protected]61b4efc2012-04-27 18:12:505701 BoundNetLog(), GetParam(), NULL);
[email protected]721c0ce2011-10-13 02:41:005702
5703 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:575704 helper.AddData(&data);
[email protected]721c0ce2011-10-13 02:41:005705
5706 HttpNetworkTransaction* trans = helper.trans();
5707
5708 // Start the transaction with basic parameters.
[email protected]49639fa2011-12-20 23:22:415709 TestCompletionCallback callback;
5710 int rv = trans->Start(
5711 &CreateGetRequest(), callback.callback(), BoundNetLog());
[email protected]721c0ce2011-10-13 02:41:005712 EXPECT_EQ(ERR_IO_PENDING, rv);
5713 rv = callback.WaitForResult();
5714 EXPECT_EQ(OK, rv);
5715
5716 // Verify that we consumed all test data.
[email protected]dd54bd82012-07-19 23:44:575717 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
5718 << data.read_count()
[email protected]721c0ce2011-10-13 02:41:005719 << " Read index: "
[email protected]dd54bd82012-07-19 23:44:575720 << data.read_index();
5721 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
5722 << data.write_count()
[email protected]721c0ce2011-10-13 02:41:005723 << " Write index: "
[email protected]dd54bd82012-07-19 23:44:575724 << data.write_index();
[email protected]721c0ce2011-10-13 02:41:005725
5726 // Verify the SYN_REPLY.
5727 HttpResponseInfo response = *trans->GetResponseInfo();
[email protected]90499482013-06-01 00:39:505728 EXPECT_TRUE(response.headers.get() != NULL);
[email protected]721c0ce2011-10-13 02:41:005729 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5730}
5731
[email protected]513963e2013-06-15 01:53:045732TEST_P(SpdyNetworkTransactionTest, OutOfOrderSynStream) {
[email protected]e1f58efa2012-05-15 18:23:405733 // This first request will start to establish the SpdySession.
5734 // Then we will start the second (MEDIUM priority) and then third
5735 // (HIGHEST priority) request in such a way that the third will actually
[email protected]c92f4b4542012-07-26 23:53:215736 // start before the second, causing the second to be numbered differently
[email protected]513963e2013-06-15 01:53:045737 // than the order they were created.
[email protected]cdf8f7e72013-05-23 10:56:465738 scoped_ptr<SpdyFrame> req1(
5739 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5740 scoped_ptr<SpdyFrame> req2(
5741 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, HIGHEST, true));
5742 scoped_ptr<SpdyFrame> req3(
5743 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, MEDIUM, true));
[email protected]e1f58efa2012-05-15 18:23:405744 MockWrite writes[] = {
5745 CreateMockWrite(*req1, 0),
5746 CreateMockWrite(*req2, 3),
5747 CreateMockWrite(*req3, 4),
5748 };
5749
[email protected]513963e2013-06-15 01:53:045750 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5751 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
5752 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5753 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
5754 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
5755 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
[email protected]e1f58efa2012-05-15 18:23:405756 MockRead reads[] = {
5757 CreateMockRead(*resp1, 1),
5758 CreateMockRead(*body1, 2),
5759 CreateMockRead(*resp2, 5),
5760 CreateMockRead(*body2, 6),
5761 CreateMockRead(*resp3, 7),
5762 CreateMockRead(*body3, 8),
5763 MockRead(ASYNC, 0, 9) // EOF
5764 };
5765
[email protected]dd54bd82012-07-19 23:44:575766 DeterministicSocketData data(reads, arraysize(reads),
[email protected]513963e2013-06-15 01:53:045767 writes, arraysize(writes));
[email protected]262eec82013-03-19 21:01:365768 NormalSpdyTransactionHelper helper(CreateGetRequest(), LOWEST,
[email protected]e1f58efa2012-05-15 18:23:405769 BoundNetLog(), GetParam(), NULL);
5770 helper.SetDeterministic();
5771 helper.RunPreTestSetup();
[email protected]dd54bd82012-07-19 23:44:575772 helper.AddDeterministicData(&data);
[email protected]e1f58efa2012-05-15 18:23:405773
5774 // Start the first transaction to set up the SpdySession
5775 HttpNetworkTransaction* trans = helper.trans();
5776 TestCompletionCallback callback;
5777 HttpRequestInfo info1 = CreateGetRequest();
[email protected]e1f58efa2012-05-15 18:23:405778 int rv = trans->Start(&info1, callback.callback(), BoundNetLog());
5779 EXPECT_EQ(ERR_IO_PENDING, rv);
5780
5781 // Run the message loop, but do not allow the write to complete.
5782 // This leaves the SpdySession with a write pending, which prevents
5783 // SpdySession from attempting subsequent writes until this write completes.
[email protected]fc9d88472013-08-14 02:31:175784 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:405785
5786 // Now, start both new transactions
5787 HttpRequestInfo info2 = CreateGetRequest();
[email protected]e1f58efa2012-05-15 18:23:405788 TestCompletionCallback callback2;
[email protected]90499482013-06-01 00:39:505789 scoped_ptr<HttpNetworkTransaction> trans2(
5790 new HttpNetworkTransaction(MEDIUM, helper.session().get()));
[email protected]e1f58efa2012-05-15 18:23:405791 rv = trans2->Start(&info2, callback2.callback(), BoundNetLog());
5792 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]fc9d88472013-08-14 02:31:175793 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:405794
5795 HttpRequestInfo info3 = CreateGetRequest();
[email protected]e1f58efa2012-05-15 18:23:405796 TestCompletionCallback callback3;
5797 scoped_ptr<HttpNetworkTransaction> trans3(
[email protected]90499482013-06-01 00:39:505798 new HttpNetworkTransaction(HIGHEST, helper.session().get()));
[email protected]e1f58efa2012-05-15 18:23:405799 rv = trans3->Start(&info3, callback3.callback(), BoundNetLog());
5800 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]fc9d88472013-08-14 02:31:175801 base::RunLoop().RunUntilIdle();
[email protected]e1f58efa2012-05-15 18:23:405802
5803 // We now have two SYN_STREAM frames queued up which will be
5804 // dequeued only once the first write completes, which we
5805 // now allow to happen.
[email protected]dd54bd82012-07-19 23:44:575806 data.RunFor(2);
[email protected]e1f58efa2012-05-15 18:23:405807 EXPECT_EQ(OK, callback.WaitForResult());
5808
5809 // And now we can allow everything else to run to completion.
[email protected]dd54bd82012-07-19 23:44:575810 data.SetStop(10);
5811 data.Run();
[email protected]e1f58efa2012-05-15 18:23:405812 EXPECT_EQ(OK, callback2.WaitForResult());
5813 EXPECT_EQ(OK, callback3.WaitForResult());
5814
5815 helper.VerifyDataConsumed();
5816}
5817
[email protected]d11b6912013-06-27 23:07:325818// The tests below are only for SPDY/3 and above.
5819
5820// Test that sent data frames and received WINDOW_UPDATE frames change
5821// the send_window_size_ correctly.
5822
5823// WINDOW_UPDATE is different than most other frames in that it can arrive
5824// while the client is still sending the request body. In order to enforce
5825// this scenario, we feed a couple of dummy frames and give a delay of 0 to
5826// socket data provider, so that initial read that is done as soon as the
5827// stream is created, succeeds and schedules another read. This way reads
5828// and writes are interleaved; after doing a full frame write, SpdyStream
5829// will break out of DoLoop and will read and process a WINDOW_UPDATE.
5830// Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
5831// since request has not been completely written, therefore we feed
5832// enough number of WINDOW_UPDATEs to finish the first read and cause a
5833// write, leading to a complete write of request body; after that we send
5834// a reply with a body, to cause a graceful shutdown.
5835
5836// TODO(agayev): develop a socket data provider where both, reads and
5837// writes are ordered so that writing tests like these are easy and rewrite
5838// all these tests using it. Right now we are working around the
5839// limitations as described above and it's not deterministic, tests may
5840// fail under specific circumstances.
5841TEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) {
5842 if (GetParam().protocol < kProtoSPDY3)
5843 return;
5844
5845 static int kFrameCount = 2;
5846 scoped_ptr<std::string> content(
5847 new std::string(kMaxSpdyFrameChunkSize, 'a'));
5848 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
5849 kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
5850 scoped_ptr<SpdyFrame> body(
5851 spdy_util_.ConstructSpdyBodyFrame(
5852 1, content->c_str(), content->size(), false));
5853 scoped_ptr<SpdyFrame> body_end(
5854 spdy_util_.ConstructSpdyBodyFrame(
5855 1, content->c_str(), content->size(), true));
5856
5857 MockWrite writes[] = {
5858 CreateMockWrite(*req, 0),
5859 CreateMockWrite(*body, 1),
5860 CreateMockWrite(*body_end, 2),
5861 };
5862
5863 static const int32 kDeltaWindowSize = 0xff;
5864 static const int kDeltaCount = 4;
5865 scoped_ptr<SpdyFrame> window_update(
5866 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
5867 scoped_ptr<SpdyFrame> window_update_dummy(
5868 spdy_util_.ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
5869 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
5870 MockRead reads[] = {
5871 CreateMockRead(*window_update_dummy, 3),
5872 CreateMockRead(*window_update_dummy, 4),
5873 CreateMockRead(*window_update_dummy, 5),
5874 CreateMockRead(*window_update, 6), // Four updates, therefore window
5875 CreateMockRead(*window_update, 7), // size should increase by
5876 CreateMockRead(*window_update, 8), // kDeltaWindowSize * 4
5877 CreateMockRead(*window_update, 9),
5878 CreateMockRead(*resp, 10),
5879 CreateMockRead(*body_end, 11),
5880 MockRead(ASYNC, 0, 0, 12) // EOF
5881 };
5882
5883 DeterministicSocketData data(reads, arraysize(reads),
5884 writes, arraysize(writes));
5885
5886 ScopedVector<UploadElementReader> element_readers;
5887 for (int i = 0; i < kFrameCount; ++i) {
5888 element_readers.push_back(
5889 new UploadBytesElementReader(content->c_str(), content->size()));
5890 }
mmenkecbc2b712014-10-09 20:29:075891 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]d11b6912013-06-27 23:07:325892
5893 // Setup the request
5894 HttpRequestInfo request;
5895 request.method = "POST";
5896 request.url = GURL(kDefaultURL);
5897 request.upload_data_stream = &upload_data_stream;
5898
5899 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5900 BoundNetLog(), GetParam(), NULL);
5901 helper.SetDeterministic();
5902 helper.AddDeterministicData(&data);
5903 helper.RunPreTestSetup();
5904
5905 HttpNetworkTransaction* trans = helper.trans();
5906
5907 TestCompletionCallback callback;
5908 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5909
5910 EXPECT_EQ(ERR_IO_PENDING, rv);
5911
5912 data.RunFor(11);
5913
5914 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
5915 ASSERT_TRUE(stream != NULL);
5916 ASSERT_TRUE(stream->stream() != NULL);
5917 EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize) +
5918 kDeltaWindowSize * kDeltaCount -
5919 kMaxSpdyFrameChunkSize * kFrameCount,
5920 stream->stream()->send_window_size());
5921
5922 data.RunFor(1);
5923
5924 rv = callback.WaitForResult();
5925 EXPECT_EQ(OK, rv);
5926
5927 helper.VerifyDataConsumed();
5928}
5929
5930// Test that received data frames and sent WINDOW_UPDATE frames change
5931// the recv_window_size_ correctly.
5932TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) {
5933 if (GetParam().protocol < kProtoSPDY3)
5934 return;
5935
[email protected]251029e2014-03-19 06:04:405936 // Amount of body required to trigger a sent window update.
5937 const size_t kTargetSize = kSpdyStreamInitialWindowSize / 2 + 1;
[email protected]d11b6912013-06-27 23:07:325938
5939 scoped_ptr<SpdyFrame> req(
5940 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5941 scoped_ptr<SpdyFrame> session_window_update(
[email protected]251029e2014-03-19 06:04:405942 spdy_util_.ConstructSpdyWindowUpdate(0, kTargetSize));
[email protected]d11b6912013-06-27 23:07:325943 scoped_ptr<SpdyFrame> window_update(
[email protected]251029e2014-03-19 06:04:405944 spdy_util_.ConstructSpdyWindowUpdate(1, kTargetSize));
[email protected]d11b6912013-06-27 23:07:325945
5946 std::vector<MockWrite> writes;
5947 writes.push_back(CreateMockWrite(*req));
5948 if (GetParam().protocol >= kProtoSPDY31)
5949 writes.push_back(CreateMockWrite(*session_window_update));
5950 writes.push_back(CreateMockWrite(*window_update));
5951
[email protected]251029e2014-03-19 06:04:405952 std::vector<MockRead> reads;
[email protected]d11b6912013-06-27 23:07:325953 scoped_ptr<SpdyFrame> resp(
5954 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]251029e2014-03-19 06:04:405955 reads.push_back(CreateMockRead(*resp));
[email protected]d11b6912013-06-27 23:07:325956
[email protected]251029e2014-03-19 06:04:405957 ScopedVector<SpdyFrame> body_frames;
5958 const std::string body_data(4096, 'x');
5959 for (size_t remaining = kTargetSize; remaining != 0;) {
5960 size_t frame_size = std::min(remaining, body_data.size());
5961 body_frames.push_back(spdy_util_.ConstructSpdyBodyFrame(
5962 1, body_data.data(), frame_size, false));
5963 reads.push_back(CreateMockRead(*body_frames.back()));
5964 remaining -= frame_size;
5965 }
5966 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, 0)); // Yield.
5967
5968 DelayedSocketData data(1, vector_as_array(&reads), reads.size(),
[email protected]d11b6912013-06-27 23:07:325969 vector_as_array(&writes), writes.size());
5970
5971 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5972 BoundNetLog(), GetParam(), NULL);
5973 helper.AddData(&data);
5974 helper.RunPreTestSetup();
5975 HttpNetworkTransaction* trans = helper.trans();
5976
5977 TestCompletionCallback callback;
5978 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5979
5980 EXPECT_EQ(ERR_IO_PENDING, rv);
5981 rv = callback.WaitForResult();
5982 EXPECT_EQ(OK, rv);
5983
5984 SpdyHttpStream* stream =
5985 static_cast<SpdyHttpStream*>(trans->stream_.get());
5986 ASSERT_TRUE(stream != NULL);
5987 ASSERT_TRUE(stream->stream() != NULL);
5988
[email protected]251029e2014-03-19 06:04:405989 // All data has been read, but not consumed. The window reflects this.
5990 EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize - kTargetSize),
5991 stream->stream()->recv_window_size());
[email protected]d11b6912013-06-27 23:07:325992
5993 const HttpResponseInfo* response = trans->GetResponseInfo();
5994 ASSERT_TRUE(response != NULL);
5995 ASSERT_TRUE(response->headers.get() != NULL);
5996 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5997 EXPECT_TRUE(response->was_fetched_via_spdy);
5998
5999 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
6000 // size increased to default.
[email protected]251029e2014-03-19 06:04:406001 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kTargetSize));
6002 EXPECT_EQ(static_cast<int>(kTargetSize),
6003 trans->Read(buf.get(), kTargetSize, CompletionCallback()));
6004 EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize),
6005 stream->stream()->recv_window_size());
6006 EXPECT_THAT(base::StringPiece(buf->data(), kTargetSize), Each(Eq('x')));
[email protected]d11b6912013-06-27 23:07:326007
[email protected]251029e2014-03-19 06:04:406008 // Allow scheduled WINDOW_UPDATE frames to write.
[email protected]fc9d88472013-08-14 02:31:176009 base::RunLoop().RunUntilIdle();
[email protected]d11b6912013-06-27 23:07:326010 helper.VerifyDataConsumed();
6011}
6012
6013// Test that WINDOW_UPDATE frame causing overflow is handled correctly.
6014TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
6015 if (GetParam().protocol < kProtoSPDY3)
6016 return;
6017
6018 // Number of full frames we hope to write (but will not, used to
6019 // set content-length header correctly)
6020 static int kFrameCount = 3;
6021
6022 scoped_ptr<std::string> content(
6023 new std::string(kMaxSpdyFrameChunkSize, 'a'));
6024 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6025 kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
6026 scoped_ptr<SpdyFrame> body(
6027 spdy_util_.ConstructSpdyBodyFrame(
6028 1, content->c_str(), content->size(), false));
6029 scoped_ptr<SpdyFrame> rst(
6030 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
6031
6032 // We're not going to write a data frame with FIN, we'll receive a bad
6033 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
6034 MockWrite writes[] = {
6035 CreateMockWrite(*req, 0),
6036 CreateMockWrite(*body, 2),
6037 CreateMockWrite(*rst, 3),
6038 };
6039
6040 static const int32 kDeltaWindowSize = 0x7fffffff; // cause an overflow
6041 scoped_ptr<SpdyFrame> window_update(
6042 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
6043 MockRead reads[] = {
6044 CreateMockRead(*window_update, 1),
6045 MockRead(ASYNC, 0, 4) // EOF
6046 };
6047
6048 DeterministicSocketData data(reads, arraysize(reads),
6049 writes, arraysize(writes));
6050
6051 ScopedVector<UploadElementReader> element_readers;
6052 for (int i = 0; i < kFrameCount; ++i) {
6053 element_readers.push_back(
6054 new UploadBytesElementReader(content->c_str(), content->size()));
6055 }
mmenkecbc2b712014-10-09 20:29:076056 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]d11b6912013-06-27 23:07:326057
6058 // Setup the request
6059 HttpRequestInfo request;
6060 request.method = "POST";
6061 request.url = GURL("http://www.google.com/");
6062 request.upload_data_stream = &upload_data_stream;
6063
6064 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6065 BoundNetLog(), GetParam(), NULL);
6066 helper.SetDeterministic();
6067 helper.RunPreTestSetup();
6068 helper.AddDeterministicData(&data);
6069 HttpNetworkTransaction* trans = helper.trans();
6070
6071 TestCompletionCallback callback;
6072 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6073 ASSERT_EQ(ERR_IO_PENDING, rv);
6074
6075 data.RunFor(5);
6076 ASSERT_TRUE(callback.have_result());
6077 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, callback.WaitForResult());
6078 helper.VerifyDataConsumed();
6079}
6080
6081// Test that after hitting a send window size of 0, the write process
6082// stalls and upon receiving WINDOW_UPDATE frame write resumes.
6083
6084// This test constructs a POST request followed by enough data frames
6085// containing 'a' that would make the window size 0, followed by another
6086// data frame containing default content (which is "hello!") and this frame
6087// also contains a FIN flag. DelayedSocketData is used to enforce all
6088// writes go through before a read could happen. However, the last frame
6089// ("hello!") is not supposed to go through since by the time its turn
6090// arrives, window size is 0. At this point MessageLoop::Run() called via
6091// callback would block. Therefore we call MessageLoop::RunUntilIdle()
6092// which returns after performing all possible writes. We use DCHECKS to
6093// ensure that last data frame is still there and stream has stalled.
6094// After that, next read is artifically enforced, which causes a
6095// WINDOW_UPDATE to be read and I/O process resumes.
6096TEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) {
6097 if (GetParam().protocol < kProtoSPDY3)
6098 return;
6099
6100 // Number of frames we need to send to zero out the window size: data
6101 // frames plus SYN_STREAM plus the last data frame; also we need another
6102 // data frame that we will send once the WINDOW_UPDATE is received,
6103 // therefore +3.
6104 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
6105
6106 // Calculate last frame's size; 0 size data frame is legal.
6107 size_t last_frame_size =
6108 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
6109
6110 // Construct content for a data frame of maximum size.
6111 std::string content(kMaxSpdyFrameChunkSize, 'a');
6112
6113 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6114 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
6115 LOWEST, NULL, 0));
6116
6117 // Full frames.
6118 scoped_ptr<SpdyFrame> body1(
6119 spdy_util_.ConstructSpdyBodyFrame(
6120 1, content.c_str(), content.size(), false));
6121
6122 // Last frame to zero out the window size.
6123 scoped_ptr<SpdyFrame> body2(
6124 spdy_util_.ConstructSpdyBodyFrame(
6125 1, content.c_str(), last_frame_size, false));
6126
6127 // Data frame to be sent once WINDOW_UPDATE frame is received.
6128 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6129
6130 // Fill in mock writes.
6131 scoped_ptr<MockWrite[]> writes(new MockWrite[num_writes]);
6132 size_t i = 0;
6133 writes[i] = CreateMockWrite(*req);
6134 for (i = 1; i < num_writes - 2; i++)
6135 writes[i] = CreateMockWrite(*body1);
6136 writes[i++] = CreateMockWrite(*body2);
6137 writes[i] = CreateMockWrite(*body3);
6138
6139 // Construct read frame, give enough space to upload the rest of the
6140 // data.
6141 scoped_ptr<SpdyFrame> session_window_update(
6142 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6143 scoped_ptr<SpdyFrame> window_update(
6144 spdy_util_.ConstructSpdyWindowUpdate(1, kUploadDataSize));
6145 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6146 MockRead reads[] = {
6147 CreateMockRead(*session_window_update),
6148 CreateMockRead(*session_window_update),
6149 CreateMockRead(*window_update),
6150 CreateMockRead(*window_update),
6151 CreateMockRead(*reply),
6152 CreateMockRead(*body2),
6153 CreateMockRead(*body3),
6154 MockRead(ASYNC, 0, 0) // EOF
6155 };
6156
6157 // Skip the session window updates unless we're using SPDY/3.1 and
6158 // above.
6159 size_t read_offset = (GetParam().protocol >= kProtoSPDY31) ? 0 : 2;
6160 size_t num_reads = arraysize(reads) - read_offset;
6161
6162 // Force all writes to happen before any read, last write will not
6163 // actually queue a frame, due to window size being 0.
6164 DelayedSocketData data(num_writes, reads + read_offset, num_reads,
6165 writes.get(), num_writes);
6166
6167 ScopedVector<UploadElementReader> element_readers;
6168 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
6169 upload_data_string.append(kUploadData, kUploadDataSize);
6170 element_readers.push_back(new UploadBytesElementReader(
6171 upload_data_string.c_str(), upload_data_string.size()));
mmenkecbc2b712014-10-09 20:29:076172 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]d11b6912013-06-27 23:07:326173
6174 HttpRequestInfo request;
6175 request.method = "POST";
6176 request.url = GURL("http://www.google.com/");
6177 request.upload_data_stream = &upload_data_stream;
6178 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6179 BoundNetLog(), GetParam(), NULL);
6180 helper.AddData(&data);
6181 helper.RunPreTestSetup();
6182
6183 HttpNetworkTransaction* trans = helper.trans();
6184
6185 TestCompletionCallback callback;
6186 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6187 EXPECT_EQ(ERR_IO_PENDING, rv);
6188
[email protected]fc9d88472013-08-14 02:31:176189 base::RunLoop().RunUntilIdle(); // Write as much as we can.
[email protected]d11b6912013-06-27 23:07:326190
6191 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6192 ASSERT_TRUE(stream != NULL);
6193 ASSERT_TRUE(stream->stream() != NULL);
6194 EXPECT_EQ(0, stream->stream()->send_window_size());
6195 // All the body data should have been read.
6196 // TODO(satorux): This is because of the weirdness in reading the request
6197 // body in OnSendBodyComplete(). See crbug.com/113107.
6198 EXPECT_TRUE(upload_data_stream.IsEOF());
6199 // But the body is not yet fully sent (kUploadData is not yet sent)
6200 // since we're send-stalled.
6201 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6202
6203 data.ForceNextRead(); // Read in WINDOW_UPDATE frame.
6204 rv = callback.WaitForResult();
6205 helper.VerifyDataConsumed();
6206}
6207
6208// Test we correctly handle the case where the SETTINGS frame results in
6209// unstalling the send window.
6210TEST_P(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
6211 if (GetParam().protocol < kProtoSPDY3)
6212 return;
6213
6214 // Number of frames we need to send to zero out the window size: data
6215 // frames plus SYN_STREAM plus the last data frame; also we need another
6216 // data frame that we will send once the SETTING is received, therefore +3.
6217 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
6218
6219 // Calculate last frame's size; 0 size data frame is legal.
6220 size_t last_frame_size =
6221 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
6222
6223 // Construct content for a data frame of maximum size.
6224 std::string content(kMaxSpdyFrameChunkSize, 'a');
6225
6226 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6227 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
6228 LOWEST, NULL, 0));
6229
6230 // Full frames.
6231 scoped_ptr<SpdyFrame> body1(
6232 spdy_util_.ConstructSpdyBodyFrame(
6233 1, content.c_str(), content.size(), false));
6234
6235 // Last frame to zero out the window size.
6236 scoped_ptr<SpdyFrame> body2(
6237 spdy_util_.ConstructSpdyBodyFrame(
6238 1, content.c_str(), last_frame_size, false));
6239
6240 // Data frame to be sent once SETTINGS frame is received.
6241 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6242
6243 // Fill in mock reads/writes.
6244 std::vector<MockRead> reads;
6245 std::vector<MockWrite> writes;
6246 size_t i = 0;
6247 writes.push_back(CreateMockWrite(*req, i++));
6248 while (i < num_writes - 2)
6249 writes.push_back(CreateMockWrite(*body1, i++));
6250 writes.push_back(CreateMockWrite(*body2, i++));
6251
6252 // Construct read frame for SETTINGS that gives enough space to upload the
6253 // rest of the data.
6254 SettingsMap settings;
6255 settings[SETTINGS_INITIAL_WINDOW_SIZE] =
6256 SettingsFlagsAndValue(
6257 SETTINGS_FLAG_NONE, kSpdyStreamInitialWindowSize * 2);
6258 scoped_ptr<SpdyFrame> settings_frame_large(
6259 spdy_util_.ConstructSpdySettings(settings));
6260
6261 reads.push_back(CreateMockRead(*settings_frame_large, i++));
6262
6263 scoped_ptr<SpdyFrame> session_window_update(
6264 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6265 if (GetParam().protocol >= kProtoSPDY31)
6266 reads.push_back(CreateMockRead(*session_window_update, i++));
6267
[email protected]d4a77c12014-05-15 20:45:216268 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
6269 writes.push_back(CreateMockWrite(*settings_ack, i++));
6270
[email protected]d11b6912013-06-27 23:07:326271 writes.push_back(CreateMockWrite(*body3, i++));
6272
6273 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6274 reads.push_back(CreateMockRead(*reply, i++));
6275 reads.push_back(CreateMockRead(*body2, i++));
6276 reads.push_back(CreateMockRead(*body3, i++));
6277 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6278
6279 // Force all writes to happen before any read, last write will not
6280 // actually queue a frame, due to window size being 0.
6281 DeterministicSocketData data(vector_as_array(&reads), reads.size(),
6282 vector_as_array(&writes), writes.size());
6283
6284 ScopedVector<UploadElementReader> element_readers;
6285 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
6286 upload_data_string.append(kUploadData, kUploadDataSize);
6287 element_readers.push_back(new UploadBytesElementReader(
6288 upload_data_string.c_str(), upload_data_string.size()));
mmenkecbc2b712014-10-09 20:29:076289 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]d11b6912013-06-27 23:07:326290
6291 HttpRequestInfo request;
6292 request.method = "POST";
6293 request.url = GURL("http://www.google.com/");
6294 request.upload_data_stream = &upload_data_stream;
6295 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6296 BoundNetLog(), GetParam(), NULL);
6297 helper.SetDeterministic();
6298 helper.RunPreTestSetup();
6299 helper.AddDeterministicData(&data);
6300
6301 HttpNetworkTransaction* trans = helper.trans();
6302
6303 TestCompletionCallback callback;
6304 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6305 EXPECT_EQ(ERR_IO_PENDING, rv);
6306
6307 data.RunFor(num_writes - 1); // Write as much as we can.
6308
6309 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6310 ASSERT_TRUE(stream != NULL);
6311 ASSERT_TRUE(stream->stream() != NULL);
6312 EXPECT_EQ(0, stream->stream()->send_window_size());
6313
6314 // All the body data should have been read.
6315 // TODO(satorux): This is because of the weirdness in reading the request
6316 // body in OnSendBodyComplete(). See crbug.com/113107.
6317 EXPECT_TRUE(upload_data_stream.IsEOF());
6318 // But the body is not yet fully sent (kUploadData is not yet sent)
6319 // since we're send-stalled.
6320 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6321
[email protected]d4a77c12014-05-15 20:45:216322 data.RunFor(7); // Read in SETTINGS frame to unstall.
[email protected]d11b6912013-06-27 23:07:326323 rv = callback.WaitForResult();
6324 helper.VerifyDataConsumed();
6325 // If stream is NULL, that means it was unstalled and closed.
6326 EXPECT_TRUE(stream->stream() == NULL);
6327}
6328
6329// Test we correctly handle the case where the SETTINGS frame results in a
6330// negative send window size.
6331TEST_P(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
6332 if (GetParam().protocol < kProtoSPDY3)
6333 return;
6334
6335 // Number of frames we need to send to zero out the window size: data
6336 // frames plus SYN_STREAM plus the last data frame; also we need another
6337 // data frame that we will send once the SETTING is received, therefore +3.
6338 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
6339
6340 // Calculate last frame's size; 0 size data frame is legal.
6341 size_t last_frame_size =
6342 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
6343
6344 // Construct content for a data frame of maximum size.
6345 std::string content(kMaxSpdyFrameChunkSize, 'a');
6346
6347 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6348 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
6349 LOWEST, NULL, 0));
6350
6351 // Full frames.
6352 scoped_ptr<SpdyFrame> body1(
6353 spdy_util_.ConstructSpdyBodyFrame(
6354 1, content.c_str(), content.size(), false));
6355
6356 // Last frame to zero out the window size.
6357 scoped_ptr<SpdyFrame> body2(
6358 spdy_util_.ConstructSpdyBodyFrame(
6359 1, content.c_str(), last_frame_size, false));
6360
6361 // Data frame to be sent once SETTINGS frame is received.
6362 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6363
6364 // Fill in mock reads/writes.
6365 std::vector<MockRead> reads;
6366 std::vector<MockWrite> writes;
6367 size_t i = 0;
6368 writes.push_back(CreateMockWrite(*req, i++));
6369 while (i < num_writes - 2)
6370 writes.push_back(CreateMockWrite(*body1, i++));
6371 writes.push_back(CreateMockWrite(*body2, i++));
6372
6373 // Construct read frame for SETTINGS that makes the send_window_size
6374 // negative.
6375 SettingsMap new_settings;
6376 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
6377 SettingsFlagsAndValue(
6378 SETTINGS_FLAG_NONE, kSpdyStreamInitialWindowSize / 2);
6379 scoped_ptr<SpdyFrame> settings_frame_small(
6380 spdy_util_.ConstructSpdySettings(new_settings));
6381 // Construct read frames for WINDOW_UPDATE that makes the send_window_size
6382 // positive.
6383 scoped_ptr<SpdyFrame> session_window_update_init_size(
6384 spdy_util_.ConstructSpdyWindowUpdate(0, kSpdyStreamInitialWindowSize));
6385 scoped_ptr<SpdyFrame> window_update_init_size(
6386 spdy_util_.ConstructSpdyWindowUpdate(1, kSpdyStreamInitialWindowSize));
6387
6388 reads.push_back(CreateMockRead(*settings_frame_small, i++));
6389
6390 if (GetParam().protocol >= kProtoSPDY3)
6391 reads.push_back(CreateMockRead(*session_window_update_init_size, i++));
6392
6393 reads.push_back(CreateMockRead(*window_update_init_size, i++));
6394
[email protected]d4a77c12014-05-15 20:45:216395 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
6396 writes.push_back(CreateMockWrite(*settings_ack, i++));
6397
[email protected]d11b6912013-06-27 23:07:326398 writes.push_back(CreateMockWrite(*body3, i++));
6399
6400 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6401 reads.push_back(CreateMockRead(*reply, i++));
6402 reads.push_back(CreateMockRead(*body2, i++));
6403 reads.push_back(CreateMockRead(*body3, i++));
6404 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6405
6406 // Force all writes to happen before any read, last write will not
6407 // actually queue a frame, due to window size being 0.
6408 DeterministicSocketData data(vector_as_array(&reads), reads.size(),
6409 vector_as_array(&writes), writes.size());
6410
6411 ScopedVector<UploadElementReader> element_readers;
6412 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
6413 upload_data_string.append(kUploadData, kUploadDataSize);
6414 element_readers.push_back(new UploadBytesElementReader(
6415 upload_data_string.c_str(), upload_data_string.size()));
mmenkecbc2b712014-10-09 20:29:076416 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
[email protected]d11b6912013-06-27 23:07:326417
6418 HttpRequestInfo request;
6419 request.method = "POST";
6420 request.url = GURL("http://www.google.com/");
6421 request.upload_data_stream = &upload_data_stream;
6422 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6423 BoundNetLog(), GetParam(), NULL);
6424 helper.SetDeterministic();
6425 helper.RunPreTestSetup();
6426 helper.AddDeterministicData(&data);
6427
6428 HttpNetworkTransaction* trans = helper.trans();
6429
6430 TestCompletionCallback callback;
6431 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6432 EXPECT_EQ(ERR_IO_PENDING, rv);
6433
6434 data.RunFor(num_writes - 1); // Write as much as we can.
6435
6436 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6437 ASSERT_TRUE(stream != NULL);
6438 ASSERT_TRUE(stream->stream() != NULL);
6439 EXPECT_EQ(0, stream->stream()->send_window_size());
6440
6441 // All the body data should have been read.
6442 // TODO(satorux): This is because of the weirdness in reading the request
6443 // body in OnSendBodyComplete(). See crbug.com/113107.
6444 EXPECT_TRUE(upload_data_stream.IsEOF());
6445 // But the body is not yet fully sent (kUploadData is not yet sent)
6446 // since we're send-stalled.
6447 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6448
6449 // Read in WINDOW_UPDATE or SETTINGS frame.
[email protected]d4a77c12014-05-15 20:45:216450 data.RunFor((GetParam().protocol >= kProtoSPDY31) ? 9 : 8);
[email protected]d11b6912013-06-27 23:07:326451 rv = callback.WaitForResult();
6452 helper.VerifyDataConsumed();
6453}
6454
baranovich212a1292014-09-02 21:45:316455TEST_P(SpdyNetworkTransactionTest, GoAwayOnOddPushStreamId) {
6456 if (spdy_util_.spdy_version() < SPDY3)
6457 return;
6458
6459 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
6460 spdy_util_.AddUrlToHeaderBlock("http://www.google.com/a.dat",
6461 push_headers.get());
6462 scoped_ptr<SpdyFrame> push(
6463 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 3, 1));
6464 MockRead reads[] = {CreateMockRead(*push, 1)};
6465
6466 scoped_ptr<SpdyFrame> req(
6467 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
6468 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
6469 0, GOAWAY_PROTOCOL_ERROR, "Odd push stream id."));
6470 MockWrite writes[] = {
6471 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2),
6472 };
6473
6474 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
6475 NormalSpdyTransactionHelper helper(
6476 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6477 helper.RunToCompletion(&data);
6478 TransactionHelperResult out = helper.output();
6479 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
6480}
6481
6482TEST_P(SpdyNetworkTransactionTest,
6483 GoAwayOnPushStreamIdLesserOrEqualThanLastAccepted) {
6484 if (spdy_util_.spdy_version() < SPDY3)
6485 return;
6486
6487 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
6488 NULL, 0, 4, 1, "http://www.google.com/a.dat"));
6489 scoped_ptr<SpdyHeaderBlock> push_b_headers(new SpdyHeaderBlock);
6490 spdy_util_.AddUrlToHeaderBlock("http://www.google.com/b.dat",
6491 push_b_headers.get());
6492 scoped_ptr<SpdyFrame> push_b(
6493 spdy_util_.ConstructInitialSpdyPushFrame(push_b_headers.Pass(), 2, 1));
6494 MockRead reads[] = {
6495 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
6496 };
6497
6498 scoped_ptr<SpdyFrame> req(
6499 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
6500 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
6501 4,
6502 GOAWAY_PROTOCOL_ERROR,
6503 "New push stream id must be greater than the last accepted."));
6504 MockWrite writes[] = {
6505 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 3),
6506 };
6507
6508 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
6509 NormalSpdyTransactionHelper helper(
6510 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6511 helper.RunToCompletion(&data);
6512 TransactionHelperResult out = helper.output();
6513 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
6514}
6515
[email protected]514aeaf2014-05-23 10:31:516516class SpdyNetworkTransactionNoTLSUsageCheckTest
6517 : public SpdyNetworkTransactionTest {
6518 protected:
6519 void RunNoTLSUsageCheckTest(scoped_ptr<SSLSocketDataProvider> ssl_provider) {
6520 // Construct the request.
6521 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyGet(
6522 "https://www.google.com/", false, 1, LOWEST));
6523 MockWrite writes[] = {CreateMockWrite(*req)};
6524
6525 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6526 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6527 MockRead reads[] = {
6528 CreateMockRead(*resp), CreateMockRead(*body),
6529 MockRead(ASYNC, 0, 0) // EOF
6530 };
6531
6532 DelayedSocketData data(
6533 1, reads, arraysize(reads), writes, arraysize(writes));
6534 HttpRequestInfo request;
6535 request.method = "GET";
6536 request.url = GURL("https://www.google.com/");
6537 NormalSpdyTransactionHelper helper(
6538 request, DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6539 helper.RunToCompletionWithSSLData(&data, ssl_provider.Pass());
6540 TransactionHelperResult out = helper.output();
6541 EXPECT_EQ(OK, out.rv);
6542 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
6543 EXPECT_EQ("hello!", out.response_data);
6544 }
6545};
6546
6547//-----------------------------------------------------------------------------
6548// All tests are run with three different connection types: SPDY after NPN
6549// negotiation, SPDY without SSL, and SPDY with SSL.
6550//
6551// TODO(akalin): Use ::testing::Combine() when we are able to use
6552// <tr1/tuple>.
6553INSTANTIATE_TEST_CASE_P(
6554 Spdy,
6555 SpdyNetworkTransactionNoTLSUsageCheckTest,
6556 ::testing::Values(SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2,
6557 SPDYNPN),
6558 SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYNPN),
6559 SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNPN)));
6560
6561TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest, TLSVersionTooOld) {
6562 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6563 new SSLSocketDataProvider(ASYNC, OK));
6564 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6565 &ssl_provider->connection_status);
6566
6567 RunNoTLSUsageCheckTest(ssl_provider.Pass());
6568}
6569
6570TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest, TLSCipherSuiteSucky) {
6571 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6572 new SSLSocketDataProvider(ASYNC, OK));
6573 // Set to TLS_RSA_WITH_NULL_MD5
6574 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider->connection_status);
6575
6576 RunNoTLSUsageCheckTest(ssl_provider.Pass());
6577}
6578
6579class SpdyNetworkTransactionTLSUsageCheckTest
6580 : public SpdyNetworkTransactionTest {
6581 protected:
6582 void RunTLSUsageCheckTest(scoped_ptr<SSLSocketDataProvider> ssl_provider) {
[email protected]bdd1b222014-06-10 11:08:396583 scoped_ptr<SpdyFrame> goaway(
6584 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_INADEQUATE_SECURITY, ""));
6585 MockWrite writes[] = {CreateMockWrite(*goaway)};
[email protected]514aeaf2014-05-23 10:31:516586
[email protected]bdd1b222014-06-10 11:08:396587 DelayedSocketData data(1, NULL, 0, writes, arraysize(writes));
[email protected]514aeaf2014-05-23 10:31:516588 HttpRequestInfo request;
6589 request.method = "GET";
6590 request.url = GURL("https://www.google.com/");
6591 NormalSpdyTransactionHelper helper(
6592 request, DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6593 helper.RunToCompletionWithSSLData(&data, ssl_provider.Pass());
6594 TransactionHelperResult out = helper.output();
6595 EXPECT_EQ(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY, out.rv);
6596 }
6597};
6598
6599INSTANTIATE_TEST_CASE_P(
6600 Spdy,
6601 SpdyNetworkTransactionTLSUsageCheckTest,
6602 ::testing::Values(SpdyNetworkTransactionTestParams(kProtoSPDY4, SPDYNPN)));
6603
6604TEST_P(SpdyNetworkTransactionTLSUsageCheckTest, TLSVersionTooOld) {
6605 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6606 new SSLSocketDataProvider(ASYNC, OK));
6607 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6608 &ssl_provider->connection_status);
6609
6610 RunTLSUsageCheckTest(ssl_provider.Pass());
6611}
6612
6613TEST_P(SpdyNetworkTransactionTLSUsageCheckTest, TLSCipherSuiteSucky) {
6614 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6615 new SSLSocketDataProvider(ASYNC, OK));
6616 // Set to TLS_RSA_WITH_NULL_MD5
6617 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider->connection_status);
6618
6619 RunTLSUsageCheckTest(ssl_provider.Pass());
6620}
6621
[email protected]aea80602009-09-18 00:55:086622} // namespace net