Remove the apps grid page switcher from the experimental app list.
[chromium-blink-merge.git] / net / spdy / spdy_network_transaction_unittest.cc
blob17dee75b4797069238db5b03ec7eee92e921a021
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <string>
6 #include <vector>
8 #include "base/bind.h"
9 #include "base/bind_helpers.h"
10 #include "base/file_util.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/memory/scoped_vector.h"
13 #include "base/run_loop.h"
14 #include "base/stl_util.h"
15 #include "base/strings/string_piece.h"
16 #include "base/test/test_file_util.h"
17 #include "net/base/auth.h"
18 #include "net/base/net_log_unittest.h"
19 #include "net/base/request_priority.h"
20 #include "net/base/upload_bytes_element_reader.h"
21 #include "net/base/upload_data_stream.h"
22 #include "net/base/upload_file_element_reader.h"
23 #include "net/http/http_network_session_peer.h"
24 #include "net/http/http_network_transaction.h"
25 #include "net/http/http_server_properties.h"
26 #include "net/http/http_transaction_test_util.h"
27 #include "net/socket/client_socket_pool_base.h"
28 #include "net/socket/next_proto.h"
29 #include "net/spdy/buffered_spdy_framer.h"
30 #include "net/spdy/spdy_http_stream.h"
31 #include "net/spdy/spdy_http_utils.h"
32 #include "net/spdy/spdy_session.h"
33 #include "net/spdy/spdy_session_pool.h"
34 #include "net/spdy/spdy_test_util_common.h"
35 #include "net/spdy/spdy_test_utils.h"
36 #include "net/ssl/ssl_connection_status_flags.h"
37 #include "net/url_request/url_request_test_util.h"
38 #include "testing/gmock/include/gmock/gmock.h"
39 #include "testing/platform_test.h"
41 //-----------------------------------------------------------------------------
43 namespace net {
45 namespace {
47 using testing::Each;
48 using testing::Eq;
50 const char kRequestUrl[] = "http://www.google.com/";
52 enum SpdyNetworkTransactionTestSSLType {
53 SPDYNPN,
54 SPDYNOSSL,
55 SPDYSSL,
58 struct SpdyNetworkTransactionTestParams {
59 SpdyNetworkTransactionTestParams()
60 : protocol(kProtoSPDY3),
61 ssl_type(SPDYNPN) {}
63 SpdyNetworkTransactionTestParams(
64 NextProto protocol,
65 SpdyNetworkTransactionTestSSLType ssl_type)
66 : protocol(protocol),
67 ssl_type(ssl_type) {}
69 NextProto protocol;
70 SpdyNetworkTransactionTestSSLType ssl_type;
73 void UpdateSpdySessionDependencies(
74 SpdyNetworkTransactionTestParams test_params,
75 SpdySessionDependencies* session_deps) {
76 switch (test_params.ssl_type) {
77 case SPDYNPN:
78 session_deps->http_server_properties.SetAlternateProtocol(
79 HostPortPair("www.google.com", 80), 443,
80 AlternateProtocolFromNextProto(test_params.protocol), 1);
81 session_deps->use_alternate_protocols = true;
82 session_deps->next_protos = SpdyNextProtos();
83 break;
84 case SPDYNOSSL:
85 session_deps->force_spdy_over_ssl = false;
86 session_deps->force_spdy_always = true;
87 break;
88 case SPDYSSL:
89 session_deps->force_spdy_over_ssl = true;
90 session_deps->force_spdy_always = true;
91 break;
92 default:
93 NOTREACHED();
97 SpdySessionDependencies* CreateSpdySessionDependencies(
98 SpdyNetworkTransactionTestParams test_params) {
99 SpdySessionDependencies* session_deps =
100 new SpdySessionDependencies(test_params.protocol);
101 UpdateSpdySessionDependencies(test_params, session_deps);
102 return session_deps;
105 SpdySessionDependencies* CreateSpdySessionDependencies(
106 SpdyNetworkTransactionTestParams test_params,
107 ProxyService* proxy_service) {
108 SpdySessionDependencies* session_deps =
109 new SpdySessionDependencies(test_params.protocol, proxy_service);
110 UpdateSpdySessionDependencies(test_params, session_deps);
111 return session_deps;
114 } // namespace
116 class SpdyNetworkTransactionTest
117 : public ::testing::TestWithParam<SpdyNetworkTransactionTestParams> {
118 protected:
119 SpdyNetworkTransactionTest() : spdy_util_(GetParam().protocol) {
122 virtual ~SpdyNetworkTransactionTest() {
123 // UploadDataStream posts deletion tasks back to the message loop on
124 // destruction.
125 upload_data_stream_.reset();
126 base::RunLoop().RunUntilIdle();
129 virtual void SetUp() {
130 google_get_request_initialized_ = false;
131 google_post_request_initialized_ = false;
132 google_chunked_post_request_initialized_ = false;
133 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
136 struct TransactionHelperResult {
137 int rv;
138 std::string status_line;
139 std::string response_data;
140 HttpResponseInfo response_info;
143 // A helper class that handles all the initial npn/ssl setup.
144 class NormalSpdyTransactionHelper {
145 public:
146 NormalSpdyTransactionHelper(const HttpRequestInfo& request,
147 RequestPriority priority,
148 const BoundNetLog& log,
149 SpdyNetworkTransactionTestParams test_params,
150 SpdySessionDependencies* session_deps)
151 : request_(request),
152 priority_(priority),
153 session_deps_(session_deps == NULL ?
154 CreateSpdySessionDependencies(test_params) :
155 session_deps),
156 session_(SpdySessionDependencies::SpdyCreateSession(
157 session_deps_.get())),
158 log_(log),
159 test_params_(test_params),
160 deterministic_(false),
161 spdy_enabled_(true) {
162 switch (test_params_.ssl_type) {
163 case SPDYNOSSL:
164 case SPDYSSL:
165 port_ = 80;
166 break;
167 case SPDYNPN:
168 port_ = 443;
169 break;
170 default:
171 NOTREACHED();
175 ~NormalSpdyTransactionHelper() {
176 // Any test which doesn't close the socket by sending it an EOF will
177 // have a valid session left open, which leaks the entire session pool.
178 // This is just fine - in fact, some of our tests intentionally do this
179 // so that we can check consistency of the SpdySessionPool as the test
180 // finishes. If we had put an EOF on the socket, the SpdySession would
181 // have closed and we wouldn't be able to check the consistency.
183 // Forcefully close existing sessions here.
184 session()->spdy_session_pool()->CloseAllSessions();
187 void SetDeterministic() {
188 session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
189 session_deps_.get());
190 deterministic_ = true;
193 void SetSpdyDisabled() {
194 spdy_enabled_ = false;
195 port_ = 80;
198 void RunPreTestSetup() {
199 if (!session_deps_.get())
200 session_deps_.reset(CreateSpdySessionDependencies(test_params_));
201 if (!session_.get()) {
202 session_ = SpdySessionDependencies::SpdyCreateSession(
203 session_deps_.get());
206 // We're now ready to use SSL-npn SPDY.
207 trans_.reset(new HttpNetworkTransaction(priority_, session_.get()));
210 // Start the transaction, read some data, finish.
211 void RunDefaultTest() {
212 if (!StartDefaultTest())
213 return;
214 FinishDefaultTest();
217 bool StartDefaultTest() {
218 output_.rv = trans_->Start(&request_, callback_.callback(), log_);
220 // We expect an IO Pending or some sort of error.
221 EXPECT_LT(output_.rv, 0);
222 return output_.rv == ERR_IO_PENDING;
225 void FinishDefaultTest() {
226 output_.rv = callback_.WaitForResult();
227 if (output_.rv != OK) {
228 session_->spdy_session_pool()->CloseCurrentSessions(net::ERR_ABORTED);
229 return;
232 // Verify responses.
233 const HttpResponseInfo* response = trans_->GetResponseInfo();
234 ASSERT_TRUE(response != NULL);
235 ASSERT_TRUE(response->headers.get() != NULL);
236 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
237 EXPECT_EQ(spdy_enabled_, response->was_fetched_via_spdy);
238 if (HttpStreamFactory::spdy_enabled()) {
239 EXPECT_EQ(
240 HttpResponseInfo::ConnectionInfoFromNextProto(
241 test_params_.protocol),
242 response->connection_info);
243 } else {
244 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1,
245 response->connection_info);
247 if (test_params_.ssl_type == SPDYNPN && spdy_enabled_) {
248 EXPECT_TRUE(response->was_npn_negotiated);
249 } else {
250 EXPECT_TRUE(!response->was_npn_negotiated);
252 // If SPDY is not enabled, a HTTP request should not be diverted
253 // over a SSL session.
254 if (!spdy_enabled_) {
255 EXPECT_EQ(request_.url.SchemeIs("https"),
256 response->was_npn_negotiated);
258 EXPECT_EQ("127.0.0.1", response->socket_address.host());
259 EXPECT_EQ(port_, response->socket_address.port());
260 output_.status_line = response->headers->GetStatusLine();
261 output_.response_info = *response; // Make a copy so we can verify.
262 output_.rv = ReadTransaction(trans_.get(), &output_.response_data);
265 // Most tests will want to call this function. In particular, the MockReads
266 // should end with an empty read, and that read needs to be processed to
267 // ensure proper deletion of the spdy_session_pool.
268 void VerifyDataConsumed() {
269 for (DataVector::iterator it = data_vector_.begin();
270 it != data_vector_.end(); ++it) {
271 EXPECT_TRUE((*it)->at_read_eof()) << "Read count: "
272 << (*it)->read_count()
273 << " Read index: "
274 << (*it)->read_index();
275 EXPECT_TRUE((*it)->at_write_eof()) << "Write count: "
276 << (*it)->write_count()
277 << " Write index: "
278 << (*it)->write_index();
282 // Occasionally a test will expect to error out before certain reads are
283 // processed. In that case we want to explicitly ensure that the reads were
284 // not processed.
285 void VerifyDataNotConsumed() {
286 for (DataVector::iterator it = data_vector_.begin();
287 it != data_vector_.end(); ++it) {
288 EXPECT_TRUE(!(*it)->at_read_eof()) << "Read count: "
289 << (*it)->read_count()
290 << " Read index: "
291 << (*it)->read_index();
292 EXPECT_TRUE(!(*it)->at_write_eof()) << "Write count: "
293 << (*it)->write_count()
294 << " Write index: "
295 << (*it)->write_index();
299 void RunToCompletion(StaticSocketDataProvider* data) {
300 RunPreTestSetup();
301 AddData(data);
302 RunDefaultTest();
303 VerifyDataConsumed();
306 void RunToCompletionWithSSLData(
307 StaticSocketDataProvider* data,
308 scoped_ptr<SSLSocketDataProvider> ssl_provider) {
309 RunPreTestSetup();
310 AddDataWithSSLSocketDataProvider(data, ssl_provider.Pass());
311 RunDefaultTest();
312 VerifyDataConsumed();
315 void AddData(StaticSocketDataProvider* data) {
316 scoped_ptr<SSLSocketDataProvider> ssl_provider(
317 new SSLSocketDataProvider(ASYNC, OK));
318 AddDataWithSSLSocketDataProvider(data, ssl_provider.Pass());
321 void AddDataWithSSLSocketDataProvider(
322 StaticSocketDataProvider* data,
323 scoped_ptr<SSLSocketDataProvider> ssl_provider) {
324 DCHECK(!deterministic_);
325 data_vector_.push_back(data);
326 if (test_params_.ssl_type == SPDYNPN)
327 ssl_provider->SetNextProto(test_params_.protocol);
329 if (test_params_.ssl_type == SPDYNPN ||
330 test_params_.ssl_type == SPDYSSL) {
331 session_deps_->socket_factory->AddSSLSocketDataProvider(
332 ssl_provider.get());
334 ssl_vector_.push_back(ssl_provider.release());
336 session_deps_->socket_factory->AddSocketDataProvider(data);
337 if (test_params_.ssl_type == SPDYNPN) {
338 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
339 StaticSocketDataProvider* hanging_non_alternate_protocol_socket =
340 new StaticSocketDataProvider(NULL, 0, NULL, 0);
341 hanging_non_alternate_protocol_socket->set_connect_data(
342 never_finishing_connect);
343 session_deps_->socket_factory->AddSocketDataProvider(
344 hanging_non_alternate_protocol_socket);
345 alternate_vector_.push_back(hanging_non_alternate_protocol_socket);
349 void AddDeterministicData(DeterministicSocketData* data) {
350 DCHECK(deterministic_);
351 data_vector_.push_back(data);
352 SSLSocketDataProvider* ssl_provider =
353 new SSLSocketDataProvider(ASYNC, OK);
354 if (test_params_.ssl_type == SPDYNPN)
355 ssl_provider->SetNextProto(test_params_.protocol);
357 ssl_vector_.push_back(ssl_provider);
358 if (test_params_.ssl_type == SPDYNPN ||
359 test_params_.ssl_type == SPDYSSL) {
360 session_deps_->deterministic_socket_factory->
361 AddSSLSocketDataProvider(ssl_provider);
363 session_deps_->deterministic_socket_factory->AddSocketDataProvider(data);
364 if (test_params_.ssl_type == SPDYNPN) {
365 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
366 DeterministicSocketData* hanging_non_alternate_protocol_socket =
367 new DeterministicSocketData(NULL, 0, NULL, 0);
368 hanging_non_alternate_protocol_socket->set_connect_data(
369 never_finishing_connect);
370 session_deps_->deterministic_socket_factory->AddSocketDataProvider(
371 hanging_non_alternate_protocol_socket);
372 alternate_deterministic_vector_.push_back(
373 hanging_non_alternate_protocol_socket);
377 void SetSession(const scoped_refptr<HttpNetworkSession>& session) {
378 session_ = session;
380 HttpNetworkTransaction* trans() { return trans_.get(); }
381 void ResetTrans() { trans_.reset(); }
382 TransactionHelperResult& output() { return output_; }
383 const HttpRequestInfo& request() const { return request_; }
384 const scoped_refptr<HttpNetworkSession>& session() const {
385 return session_;
387 scoped_ptr<SpdySessionDependencies>& session_deps() {
388 return session_deps_;
390 int port() const { return port_; }
391 SpdyNetworkTransactionTestParams test_params() const {
392 return test_params_;
395 private:
396 typedef std::vector<StaticSocketDataProvider*> DataVector;
397 typedef ScopedVector<SSLSocketDataProvider> SSLVector;
398 typedef ScopedVector<StaticSocketDataProvider> AlternateVector;
399 typedef ScopedVector<DeterministicSocketData> AlternateDeterministicVector;
400 HttpRequestInfo request_;
401 RequestPriority priority_;
402 scoped_ptr<SpdySessionDependencies> session_deps_;
403 scoped_refptr<HttpNetworkSession> session_;
404 TransactionHelperResult output_;
405 scoped_ptr<StaticSocketDataProvider> first_transaction_;
406 SSLVector ssl_vector_;
407 TestCompletionCallback callback_;
408 scoped_ptr<HttpNetworkTransaction> trans_;
409 scoped_ptr<HttpNetworkTransaction> trans_http_;
410 DataVector data_vector_;
411 AlternateVector alternate_vector_;
412 AlternateDeterministicVector alternate_deterministic_vector_;
413 const BoundNetLog& log_;
414 SpdyNetworkTransactionTestParams test_params_;
415 int port_;
416 bool deterministic_;
417 bool spdy_enabled_;
420 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
421 int expected_status);
423 void ConnectStatusHelper(const MockRead& status);
425 const HttpRequestInfo& CreateGetPushRequest() {
426 google_get_push_request_.method = "GET";
427 google_get_push_request_.url = GURL("http://www.google.com/foo.dat");
428 google_get_push_request_.load_flags = 0;
429 return google_get_push_request_;
432 const HttpRequestInfo& CreateGetRequest() {
433 if (!google_get_request_initialized_) {
434 google_get_request_.method = "GET";
435 google_get_request_.url = GURL(kDefaultURL);
436 google_get_request_.load_flags = 0;
437 google_get_request_initialized_ = true;
439 return google_get_request_;
442 const HttpRequestInfo& CreateGetRequestWithUserAgent() {
443 if (!google_get_request_initialized_) {
444 google_get_request_.method = "GET";
445 google_get_request_.url = GURL(kDefaultURL);
446 google_get_request_.load_flags = 0;
447 google_get_request_.extra_headers.SetHeader("User-Agent", "Chrome");
448 google_get_request_initialized_ = true;
450 return google_get_request_;
453 const HttpRequestInfo& CreatePostRequest() {
454 if (!google_post_request_initialized_) {
455 ScopedVector<UploadElementReader> element_readers;
456 element_readers.push_back(
457 new UploadBytesElementReader(kUploadData, kUploadDataSize));
458 upload_data_stream_.reset(
459 new UploadDataStream(element_readers.Pass(), 0));
461 google_post_request_.method = "POST";
462 google_post_request_.url = GURL(kDefaultURL);
463 google_post_request_.upload_data_stream = upload_data_stream_.get();
464 google_post_request_initialized_ = true;
466 return google_post_request_;
469 const HttpRequestInfo& CreateFilePostRequest() {
470 if (!google_post_request_initialized_) {
471 base::FilePath file_path;
472 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
473 CHECK_EQ(static_cast<int>(kUploadDataSize),
474 base::WriteFile(file_path, kUploadData, kUploadDataSize));
476 ScopedVector<UploadElementReader> element_readers;
477 element_readers.push_back(
478 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
479 file_path,
481 kUploadDataSize,
482 base::Time()));
483 upload_data_stream_.reset(
484 new UploadDataStream(element_readers.Pass(), 0));
486 google_post_request_.method = "POST";
487 google_post_request_.url = GURL(kDefaultURL);
488 google_post_request_.upload_data_stream = upload_data_stream_.get();
489 google_post_request_initialized_ = true;
491 return google_post_request_;
494 const HttpRequestInfo& CreateUnreadableFilePostRequest() {
495 if (google_post_request_initialized_)
496 return google_post_request_;
498 base::FilePath file_path;
499 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
500 CHECK_EQ(static_cast<int>(kUploadDataSize),
501 base::WriteFile(file_path, kUploadData, kUploadDataSize));
502 CHECK(base::MakeFileUnreadable(file_path));
504 ScopedVector<UploadElementReader> element_readers;
505 element_readers.push_back(
506 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
507 file_path,
509 kUploadDataSize,
510 base::Time()));
511 upload_data_stream_.reset(
512 new UploadDataStream(element_readers.Pass(), 0));
514 google_post_request_.method = "POST";
515 google_post_request_.url = GURL(kDefaultURL);
516 google_post_request_.upload_data_stream = upload_data_stream_.get();
517 google_post_request_initialized_ = true;
518 return google_post_request_;
521 const HttpRequestInfo& CreateComplexPostRequest() {
522 if (!google_post_request_initialized_) {
523 const int kFileRangeOffset = 1;
524 const int kFileRangeLength = 3;
525 CHECK_LT(kFileRangeOffset + kFileRangeLength, kUploadDataSize);
527 base::FilePath file_path;
528 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
529 CHECK_EQ(static_cast<int>(kUploadDataSize),
530 base::WriteFile(file_path, kUploadData, kUploadDataSize));
532 ScopedVector<UploadElementReader> element_readers;
533 element_readers.push_back(
534 new UploadBytesElementReader(kUploadData, kFileRangeOffset));
535 element_readers.push_back(
536 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
537 file_path,
538 kFileRangeOffset,
539 kFileRangeLength,
540 base::Time()));
541 element_readers.push_back(new UploadBytesElementReader(
542 kUploadData + kFileRangeOffset + kFileRangeLength,
543 kUploadDataSize - (kFileRangeOffset + kFileRangeLength)));
544 upload_data_stream_.reset(
545 new UploadDataStream(element_readers.Pass(), 0));
547 google_post_request_.method = "POST";
548 google_post_request_.url = GURL(kDefaultURL);
549 google_post_request_.upload_data_stream = upload_data_stream_.get();
550 google_post_request_initialized_ = true;
552 return google_post_request_;
555 const HttpRequestInfo& CreateChunkedPostRequest() {
556 if (!google_chunked_post_request_initialized_) {
557 upload_data_stream_.reset(
558 new UploadDataStream(UploadDataStream::CHUNKED, 0));
559 google_chunked_post_request_.method = "POST";
560 google_chunked_post_request_.url = GURL(kDefaultURL);
561 google_chunked_post_request_.upload_data_stream =
562 upload_data_stream_.get();
563 google_chunked_post_request_initialized_ = true;
565 return google_chunked_post_request_;
568 // 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,
573 StaticSocketDataProvider* data,
574 std::string* result) {
575 const int kSize = 3000;
577 int bytes_read = 0;
578 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(kSize));
579 TestCompletionCallback callback;
580 while (true) {
581 int rv = trans->Read(buf.get(), kSize, callback.callback());
582 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();
587 base::RunLoop().RunUntilIdle();
589 rv = callback.WaitForResult();
590 } else if (rv <= 0) {
591 break;
593 result->append(buf->data(), rv);
594 bytes_read += rv;
596 return bytes_read;
599 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;
604 int port = helper.test_params().ssl_type == SPDYNPN ? 443 : 80;
605 HostPortPair host_port_pair(url.host(), port);
606 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
607 PRIVACY_MODE_DISABLED);
608 BoundNetLog log;
609 const scoped_refptr<HttpNetworkSession>& session = helper.session();
610 base::WeakPtr<SpdySession> spdy_session =
611 session->spdy_session_pool()->FindAvailableSession(key, log);
612 ASSERT_TRUE(spdy_session != NULL);
613 EXPECT_EQ(0u, spdy_session->num_active_streams());
614 EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams());
617 void RunServerPushTest(OrderedSocketData* data,
618 HttpResponseInfo* response,
619 HttpResponseInfo* push_response,
620 const std::string& expected) {
621 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
622 BoundNetLog(), GetParam(), NULL);
623 helper.RunPreTestSetup();
624 helper.AddData(data);
626 HttpNetworkTransaction* trans = helper.trans();
628 // Start the transaction with basic parameters.
629 TestCompletionCallback callback;
630 int rv = trans->Start(
631 &CreateGetRequest(), callback.callback(), BoundNetLog());
632 EXPECT_EQ(ERR_IO_PENDING, rv);
633 rv = callback.WaitForResult();
635 // Request the pushed path.
636 scoped_ptr<HttpNetworkTransaction> trans2(
637 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
638 rv = trans2->Start(
639 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
640 EXPECT_EQ(ERR_IO_PENDING, rv);
641 base::RunLoop().RunUntilIdle();
643 // The data for the pushed path may be coming in more than 1 frame. Compile
644 // the results into a single string.
646 // Read the server push body.
647 std::string result2;
648 ReadResult(trans2.get(), data, &result2);
649 // Read the response body.
650 std::string result;
651 ReadResult(trans, data, &result);
653 // Verify that we consumed all test data.
654 EXPECT_TRUE(data->at_read_eof());
655 EXPECT_TRUE(data->at_write_eof());
657 // Verify that the received push data is same as the expected push data.
658 EXPECT_EQ(result2.compare(expected), 0) << "Received data: "
659 << result2
660 << "||||| Expected data: "
661 << expected;
663 // Verify the SYN_REPLY.
664 // Copy the response info, because trans goes away.
665 *response = *trans->GetResponseInfo();
666 *push_response = *trans2->GetResponseInfo();
668 VerifyStreamsClosed(helper);
671 static void DeleteSessionCallback(NormalSpdyTransactionHelper* helper,
672 int result) {
673 helper->ResetTrans();
676 static void StartTransactionCallback(
677 const scoped_refptr<HttpNetworkSession>& session,
678 int result) {
679 scoped_ptr<HttpNetworkTransaction> trans(
680 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
681 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();
691 SpdyTestUtil spdy_util_;
693 private:
694 scoped_ptr<UploadDataStream> upload_data_stream_;
695 bool google_get_request_initialized_;
696 bool google_post_request_initialized_;
697 bool google_chunked_post_request_initialized_;
698 HttpRequestInfo google_get_request_;
699 HttpRequestInfo google_post_request_;
700 HttpRequestInfo google_chunked_post_request_;
701 HttpRequestInfo google_get_push_request_;
702 base::ScopedTempDir temp_dir_;
705 //-----------------------------------------------------------------------------
706 // All tests are run with three different connection types: SPDY after NPN
707 // negotiation, SPDY without SSL, and SPDY with SSL.
709 // TODO(akalin): Use ::testing::Combine() when we are able to use
710 // <tr1/tuple>.
711 INSTANTIATE_TEST_CASE_P(
712 Spdy,
713 SpdyNetworkTransactionTest,
714 ::testing::Values(
715 SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2, SPDYNOSSL),
716 SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2, SPDYSSL),
717 SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2, SPDYNPN),
718 SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYNOSSL),
719 SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYSSL),
720 SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYNPN),
721 SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNOSSL),
722 SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYSSL),
723 SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNPN),
724 SpdyNetworkTransactionTestParams(kProtoSPDY4, SPDYNOSSL),
725 SpdyNetworkTransactionTestParams(kProtoSPDY4, SPDYSSL),
726 SpdyNetworkTransactionTestParams(kProtoSPDY4, SPDYNPN)));
728 // Verify HttpNetworkTransaction constructor.
729 TEST_P(SpdyNetworkTransactionTest, Constructor) {
730 scoped_ptr<SpdySessionDependencies> session_deps(
731 CreateSpdySessionDependencies(GetParam()));
732 scoped_refptr<HttpNetworkSession> session(
733 SpdySessionDependencies::SpdyCreateSession(session_deps.get()));
734 scoped_ptr<HttpTransaction> trans(
735 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
738 TEST_P(SpdyNetworkTransactionTest, Get) {
739 // Construct the request.
740 scoped_ptr<SpdyFrame> req(
741 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
742 MockWrite writes[] = { CreateMockWrite(*req) };
744 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
745 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
746 MockRead reads[] = {
747 CreateMockRead(*resp),
748 CreateMockRead(*body),
749 MockRead(ASYNC, 0, 0) // EOF
752 DelayedSocketData data(1, reads, arraysize(reads),
753 writes, arraysize(writes));
754 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
755 BoundNetLog(), GetParam(), NULL);
756 helper.RunToCompletion(&data);
757 TransactionHelperResult out = helper.output();
758 EXPECT_EQ(OK, out.rv);
759 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
760 EXPECT_EQ("hello!", out.response_data);
763 TEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) {
764 for (RequestPriority p = MINIMUM_PRIORITY; p <= MAXIMUM_PRIORITY;
765 p = RequestPriority(p + 1)) {
766 // Construct the request.
767 scoped_ptr<SpdyFrame> req(
768 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, p, true));
769 MockWrite writes[] = { CreateMockWrite(*req) };
771 SpdyPriority spdy_prio = 0;
772 EXPECT_TRUE(GetSpdyPriority(spdy_util_.spdy_version(), *req, &spdy_prio));
773 // this repeats the RequestPriority-->SpdyPriority mapping from
774 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
775 // sure it's being done right.
776 if (spdy_util_.spdy_version() < SPDY3) {
777 switch(p) {
778 case HIGHEST:
779 EXPECT_EQ(0, spdy_prio);
780 break;
781 case MEDIUM:
782 EXPECT_EQ(1, spdy_prio);
783 break;
784 case LOW:
785 case LOWEST:
786 EXPECT_EQ(2, spdy_prio);
787 break;
788 case IDLE:
789 EXPECT_EQ(3, spdy_prio);
790 break;
791 default:
792 FAIL();
794 } else {
795 switch(p) {
796 case HIGHEST:
797 EXPECT_EQ(0, spdy_prio);
798 break;
799 case MEDIUM:
800 EXPECT_EQ(1, spdy_prio);
801 break;
802 case LOW:
803 EXPECT_EQ(2, spdy_prio);
804 break;
805 case LOWEST:
806 EXPECT_EQ(3, spdy_prio);
807 break;
808 case IDLE:
809 EXPECT_EQ(4, spdy_prio);
810 break;
811 default:
812 FAIL();
816 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
817 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
818 MockRead reads[] = {
819 CreateMockRead(*resp),
820 CreateMockRead(*body),
821 MockRead(ASYNC, 0, 0) // EOF
824 DelayedSocketData data(1, reads, arraysize(reads),
825 writes, arraysize(writes));
826 HttpRequestInfo http_req = CreateGetRequest();
828 NormalSpdyTransactionHelper helper(http_req, p, BoundNetLog(),
829 GetParam(), NULL);
830 helper.RunToCompletion(&data);
831 TransactionHelperResult out = helper.output();
832 EXPECT_EQ(OK, out.rv);
833 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
834 EXPECT_EQ("hello!", out.response_data);
838 // Start three gets simultaniously; making sure that multiplexed
839 // streams work properly.
841 // This can't use the TransactionHelper method, since it only
842 // handles a single transaction, and finishes them as soon
843 // as it launches them.
845 // TODO(gavinp): create a working generalized TransactionHelper that
846 // can allow multiple streams in flight.
848 TEST_P(SpdyNetworkTransactionTest, ThreeGets) {
849 scoped_ptr<SpdyFrame> req(
850 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
851 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
852 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
853 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
855 scoped_ptr<SpdyFrame> req2(
856 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
857 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
858 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
859 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
861 scoped_ptr<SpdyFrame> req3(
862 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
863 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
864 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
865 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
867 MockWrite writes[] = {
868 CreateMockWrite(*req),
869 CreateMockWrite(*req2),
870 CreateMockWrite(*req3),
872 MockRead reads[] = {
873 CreateMockRead(*resp, 1),
874 CreateMockRead(*body),
875 CreateMockRead(*resp2, 4),
876 CreateMockRead(*body2),
877 CreateMockRead(*resp3, 7),
878 CreateMockRead(*body3),
880 CreateMockRead(*fbody),
881 CreateMockRead(*fbody2),
882 CreateMockRead(*fbody3),
884 MockRead(ASYNC, 0, 0), // EOF
886 OrderedSocketData data(reads, arraysize(reads),
887 writes, arraysize(writes));
888 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
890 BoundNetLog log;
891 TransactionHelperResult out;
892 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
893 BoundNetLog(), GetParam(), NULL);
894 helper.RunPreTestSetup();
895 helper.AddData(&data);
896 // We require placeholder data because three get requests are sent out, so
897 // there needs to be three sets of SSL connection data.
898 helper.AddData(&data_placeholder);
899 helper.AddData(&data_placeholder);
900 scoped_ptr<HttpNetworkTransaction> trans1(
901 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
902 scoped_ptr<HttpNetworkTransaction> trans2(
903 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
904 scoped_ptr<HttpNetworkTransaction> trans3(
905 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
907 TestCompletionCallback callback1;
908 TestCompletionCallback callback2;
909 TestCompletionCallback callback3;
911 HttpRequestInfo httpreq1 = CreateGetRequest();
912 HttpRequestInfo httpreq2 = CreateGetRequest();
913 HttpRequestInfo httpreq3 = CreateGetRequest();
915 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
916 ASSERT_EQ(ERR_IO_PENDING, out.rv);
917 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
918 ASSERT_EQ(ERR_IO_PENDING, out.rv);
919 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
920 ASSERT_EQ(ERR_IO_PENDING, out.rv);
922 out.rv = callback1.WaitForResult();
923 ASSERT_EQ(OK, out.rv);
924 out.rv = callback3.WaitForResult();
925 ASSERT_EQ(OK, out.rv);
927 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
928 EXPECT_TRUE(response1->headers.get() != NULL);
929 EXPECT_TRUE(response1->was_fetched_via_spdy);
930 out.status_line = response1->headers->GetStatusLine();
931 out.response_info = *response1;
933 trans2->GetResponseInfo();
935 out.rv = ReadTransaction(trans1.get(), &out.response_data);
936 helper.VerifyDataConsumed();
937 EXPECT_EQ(OK, out.rv);
939 EXPECT_EQ(OK, out.rv);
940 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
941 EXPECT_EQ("hello!hello!", out.response_data);
944 TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
945 scoped_ptr<SpdyFrame> req(
946 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
947 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
948 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
949 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
951 scoped_ptr<SpdyFrame> req2(
952 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
953 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
954 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
955 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
957 MockWrite writes[] = {
958 CreateMockWrite(*req),
959 CreateMockWrite(*req2),
961 MockRead reads[] = {
962 CreateMockRead(*resp, 1),
963 CreateMockRead(*body),
964 CreateMockRead(*resp2, 4),
965 CreateMockRead(*body2),
966 CreateMockRead(*fbody),
967 CreateMockRead(*fbody2),
968 MockRead(ASYNC, 0, 0), // EOF
970 OrderedSocketData data(reads, arraysize(reads),
971 writes, arraysize(writes));
973 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
975 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
976 data_placeholder.set_connect_data(never_finishing_connect);
978 BoundNetLog log;
979 TransactionHelperResult out;
980 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
981 BoundNetLog(), GetParam(), NULL);
982 helper.RunPreTestSetup();
983 helper.AddData(&data);
984 // We require placeholder data because two get requests are sent out, so
985 // there needs to be two sets of SSL connection data.
986 helper.AddData(&data_placeholder);
987 scoped_ptr<HttpNetworkTransaction> trans1(
988 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
989 scoped_ptr<HttpNetworkTransaction> trans2(
990 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
992 TestCompletionCallback callback1;
993 TestCompletionCallback callback2;
995 HttpRequestInfo httpreq1 = CreateGetRequest();
996 HttpRequestInfo httpreq2 = CreateGetRequest();
998 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
999 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1000 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1001 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1003 out.rv = callback1.WaitForResult();
1004 ASSERT_EQ(OK, out.rv);
1005 out.rv = callback2.WaitForResult();
1006 ASSERT_EQ(OK, out.rv);
1008 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1009 EXPECT_TRUE(response1->headers.get() != NULL);
1010 EXPECT_TRUE(response1->was_fetched_via_spdy);
1011 out.status_line = response1->headers->GetStatusLine();
1012 out.response_info = *response1;
1013 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1014 EXPECT_EQ(OK, out.rv);
1015 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1016 EXPECT_EQ("hello!hello!", out.response_data);
1018 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1019 EXPECT_TRUE(response2->headers.get() != NULL);
1020 EXPECT_TRUE(response2->was_fetched_via_spdy);
1021 out.status_line = response2->headers->GetStatusLine();
1022 out.response_info = *response2;
1023 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1024 EXPECT_EQ(OK, out.rv);
1025 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1026 EXPECT_EQ("hello!hello!", out.response_data);
1028 helper.VerifyDataConsumed();
1031 TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
1032 scoped_ptr<SpdyFrame> req(
1033 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1034 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1035 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1036 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
1038 scoped_ptr<SpdyFrame> req2(
1039 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1040 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1041 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1042 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1044 MockWrite writes[] = {
1045 CreateMockWrite(*req),
1046 CreateMockWrite(*req2),
1048 MockRead reads[] = {
1049 CreateMockRead(*resp, 1),
1050 CreateMockRead(*body),
1051 CreateMockRead(*resp2, 4),
1052 CreateMockRead(*body2),
1053 CreateMockRead(*fbody),
1054 CreateMockRead(*fbody2),
1055 MockRead(ASYNC, 0, 0), // EOF
1057 OrderedSocketData preconnect_data(reads, arraysize(reads),
1058 writes, arraysize(writes));
1060 MockConnect never_finishing_connect(ASYNC, ERR_IO_PENDING);
1062 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1063 data_placeholder.set_connect_data(never_finishing_connect);
1065 BoundNetLog log;
1066 TransactionHelperResult out;
1067 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1068 BoundNetLog(), GetParam(), NULL);
1069 helper.RunPreTestSetup();
1070 helper.AddData(&preconnect_data);
1071 // We require placeholder data because 3 connections are attempted (first is
1072 // the preconnect, 2nd and 3rd are the never finished connections.
1073 helper.AddData(&data_placeholder);
1074 helper.AddData(&data_placeholder);
1076 scoped_ptr<HttpNetworkTransaction> trans1(
1077 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1078 scoped_ptr<HttpNetworkTransaction> trans2(
1079 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1081 TestCompletionCallback callback1;
1082 TestCompletionCallback callback2;
1084 HttpRequestInfo httpreq = CreateGetRequest();
1086 // Preconnect the first.
1087 SSLConfig preconnect_ssl_config;
1088 helper.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config);
1089 HttpStreamFactory* http_stream_factory =
1090 helper.session()->http_stream_factory();
1091 helper.session()->GetNextProtos(&preconnect_ssl_config.next_protos);
1093 http_stream_factory->PreconnectStreams(
1094 1, httpreq, DEFAULT_PRIORITY,
1095 preconnect_ssl_config, preconnect_ssl_config);
1097 out.rv = trans1->Start(&httpreq, callback1.callback(), log);
1098 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1099 out.rv = trans2->Start(&httpreq, callback2.callback(), log);
1100 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1102 out.rv = callback1.WaitForResult();
1103 ASSERT_EQ(OK, out.rv);
1104 out.rv = callback2.WaitForResult();
1105 ASSERT_EQ(OK, out.rv);
1107 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1108 EXPECT_TRUE(response1->headers.get() != NULL);
1109 EXPECT_TRUE(response1->was_fetched_via_spdy);
1110 out.status_line = response1->headers->GetStatusLine();
1111 out.response_info = *response1;
1112 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1113 EXPECT_EQ(OK, out.rv);
1114 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1115 EXPECT_EQ("hello!hello!", out.response_data);
1117 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1118 EXPECT_TRUE(response2->headers.get() != NULL);
1119 EXPECT_TRUE(response2->was_fetched_via_spdy);
1120 out.status_line = response2->headers->GetStatusLine();
1121 out.response_info = *response2;
1122 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1123 EXPECT_EQ(OK, out.rv);
1124 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1125 EXPECT_EQ("hello!hello!", out.response_data);
1127 helper.VerifyDataConsumed();
1130 // Similar to ThreeGets above, however this test adds a SETTINGS
1131 // frame. The SETTINGS frame is read during the IO loop waiting on
1132 // the first transaction completion, and sets a maximum concurrent
1133 // stream limit of 1. This means that our IO loop exists after the
1134 // second transaction completes, so we can assert on read_index().
1135 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
1136 // Construct the request.
1137 scoped_ptr<SpdyFrame> req(
1138 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1139 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1140 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1141 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
1143 scoped_ptr<SpdyFrame> req2(
1144 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1145 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1146 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1147 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1149 scoped_ptr<SpdyFrame> req3(
1150 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
1151 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
1152 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
1153 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
1155 SettingsMap settings;
1156 const uint32 max_concurrent_streams = 1;
1157 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1158 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1159 scoped_ptr<SpdyFrame> settings_frame(
1160 spdy_util_.ConstructSpdySettings(settings));
1161 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1163 MockWrite writes[] = {
1164 CreateMockWrite(*req),
1165 CreateMockWrite(*settings_ack, 2),
1166 CreateMockWrite(*req2),
1167 CreateMockWrite(*req3),
1170 MockRead reads[] = {
1171 CreateMockRead(*settings_frame, 1),
1172 CreateMockRead(*resp),
1173 CreateMockRead(*body),
1174 CreateMockRead(*fbody),
1175 CreateMockRead(*resp2, 8),
1176 CreateMockRead(*body2),
1177 CreateMockRead(*fbody2),
1178 CreateMockRead(*resp3, 13),
1179 CreateMockRead(*body3),
1180 CreateMockRead(*fbody3),
1182 MockRead(ASYNC, 0, 0), // EOF
1185 OrderedSocketData data(reads, arraysize(reads),
1186 writes, arraysize(writes));
1187 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1189 BoundNetLog log;
1190 TransactionHelperResult out;
1192 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1193 BoundNetLog(), GetParam(), NULL);
1194 helper.RunPreTestSetup();
1195 helper.AddData(&data);
1196 // We require placeholder data because three get requests are sent out, so
1197 // there needs to be three sets of SSL connection data.
1198 helper.AddData(&data_placeholder);
1199 helper.AddData(&data_placeholder);
1200 scoped_ptr<HttpNetworkTransaction> trans1(
1201 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1202 scoped_ptr<HttpNetworkTransaction> trans2(
1203 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1204 scoped_ptr<HttpNetworkTransaction> trans3(
1205 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1207 TestCompletionCallback callback1;
1208 TestCompletionCallback callback2;
1209 TestCompletionCallback callback3;
1211 HttpRequestInfo httpreq1 = CreateGetRequest();
1212 HttpRequestInfo httpreq2 = CreateGetRequest();
1213 HttpRequestInfo httpreq3 = CreateGetRequest();
1215 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1216 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1217 // Run transaction 1 through quickly to force a read of our SETTINGS
1218 // frame.
1219 out.rv = callback1.WaitForResult();
1220 ASSERT_EQ(OK, out.rv);
1222 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1223 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1224 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1225 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1226 out.rv = callback2.WaitForResult();
1227 ASSERT_EQ(OK, out.rv);
1228 EXPECT_EQ(7U, data.read_index()); // i.e. the third trans was queued
1230 out.rv = callback3.WaitForResult();
1231 ASSERT_EQ(OK, out.rv);
1233 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1234 ASSERT_TRUE(response1 != NULL);
1235 EXPECT_TRUE(response1->headers.get() != NULL);
1236 EXPECT_TRUE(response1->was_fetched_via_spdy);
1237 out.status_line = response1->headers->GetStatusLine();
1238 out.response_info = *response1;
1239 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1240 EXPECT_EQ(OK, out.rv);
1241 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1242 EXPECT_EQ("hello!hello!", out.response_data);
1244 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1245 out.status_line = response2->headers->GetStatusLine();
1246 out.response_info = *response2;
1247 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1248 EXPECT_EQ(OK, out.rv);
1249 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1250 EXPECT_EQ("hello!hello!", out.response_data);
1252 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1253 out.status_line = response3->headers->GetStatusLine();
1254 out.response_info = *response3;
1255 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1256 EXPECT_EQ(OK, out.rv);
1257 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1258 EXPECT_EQ("hello!hello!", out.response_data);
1260 helper.VerifyDataConsumed();
1262 EXPECT_EQ(OK, out.rv);
1265 // Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1266 // a fourth transaction. The third and fourth transactions have
1267 // different data ("hello!" vs "hello!hello!") and because of the
1268 // user specified priority, we expect to see them inverted in
1269 // the response from the server.
1270 TEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
1271 // Construct the request.
1272 scoped_ptr<SpdyFrame> req(
1273 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1274 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1275 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1276 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
1278 scoped_ptr<SpdyFrame> req2(
1279 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1280 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1281 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1282 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1284 scoped_ptr<SpdyFrame> req4(
1285 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, HIGHEST, true));
1286 scoped_ptr<SpdyFrame> resp4(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
1287 scoped_ptr<SpdyFrame> fbody4(spdy_util_.ConstructSpdyBodyFrame(5, true));
1289 scoped_ptr<SpdyFrame> req3(
1290 spdy_util_.ConstructSpdyGet(NULL, 0, false, 7, LOWEST, true));
1291 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 7));
1292 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(7, false));
1293 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(7, true));
1295 SettingsMap settings;
1296 const uint32 max_concurrent_streams = 1;
1297 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1298 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1299 scoped_ptr<SpdyFrame> settings_frame(
1300 spdy_util_.ConstructSpdySettings(settings));
1301 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1303 MockWrite writes[] = { CreateMockWrite(*req),
1304 CreateMockWrite(*settings_ack, 2),
1305 CreateMockWrite(*req2),
1306 CreateMockWrite(*req4),
1307 CreateMockWrite(*req3),
1309 MockRead reads[] = {
1310 CreateMockRead(*settings_frame, 1),
1311 CreateMockRead(*resp),
1312 CreateMockRead(*body),
1313 CreateMockRead(*fbody),
1314 CreateMockRead(*resp2, 8),
1315 CreateMockRead(*body2),
1316 CreateMockRead(*fbody2),
1317 CreateMockRead(*resp4, 14),
1318 CreateMockRead(*fbody4),
1319 CreateMockRead(*resp3, 17),
1320 CreateMockRead(*body3),
1321 CreateMockRead(*fbody3),
1323 MockRead(ASYNC, 0, 0), // EOF
1326 OrderedSocketData data(reads, arraysize(reads),
1327 writes, arraysize(writes));
1328 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1330 BoundNetLog log;
1331 TransactionHelperResult out;
1332 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1333 BoundNetLog(), GetParam(), NULL);
1334 helper.RunPreTestSetup();
1335 helper.AddData(&data);
1336 // We require placeholder data because four get requests are sent out, so
1337 // there needs to be four sets of SSL connection data.
1338 helper.AddData(&data_placeholder);
1339 helper.AddData(&data_placeholder);
1340 helper.AddData(&data_placeholder);
1341 scoped_ptr<HttpNetworkTransaction> trans1(
1342 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1343 scoped_ptr<HttpNetworkTransaction> trans2(
1344 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1345 scoped_ptr<HttpNetworkTransaction> trans3(
1346 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1347 scoped_ptr<HttpNetworkTransaction> trans4(
1348 new HttpNetworkTransaction(HIGHEST, helper.session().get()));
1350 TestCompletionCallback callback1;
1351 TestCompletionCallback callback2;
1352 TestCompletionCallback callback3;
1353 TestCompletionCallback callback4;
1355 HttpRequestInfo httpreq1 = CreateGetRequest();
1356 HttpRequestInfo httpreq2 = CreateGetRequest();
1357 HttpRequestInfo httpreq3 = CreateGetRequest();
1358 HttpRequestInfo httpreq4 = CreateGetRequest();
1360 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1361 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1362 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1363 out.rv = callback1.WaitForResult();
1364 ASSERT_EQ(OK, out.rv);
1366 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1367 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1368 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1369 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1370 out.rv = trans4->Start(&httpreq4, callback4.callback(), log);
1371 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1373 out.rv = callback2.WaitForResult();
1374 ASSERT_EQ(OK, out.rv);
1375 EXPECT_EQ(data.read_index(), 7U); // i.e. the third & fourth trans queued
1377 out.rv = callback3.WaitForResult();
1378 ASSERT_EQ(OK, out.rv);
1380 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1381 EXPECT_TRUE(response1->headers.get() != NULL);
1382 EXPECT_TRUE(response1->was_fetched_via_spdy);
1383 out.status_line = response1->headers->GetStatusLine();
1384 out.response_info = *response1;
1385 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1386 EXPECT_EQ(OK, out.rv);
1387 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1388 EXPECT_EQ("hello!hello!", out.response_data);
1390 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1391 out.status_line = response2->headers->GetStatusLine();
1392 out.response_info = *response2;
1393 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1394 EXPECT_EQ(OK, out.rv);
1395 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1396 EXPECT_EQ("hello!hello!", out.response_data);
1398 // notice: response3 gets two hellos, response4 gets one
1399 // hello, so we know dequeuing priority was respected.
1400 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1401 out.status_line = response3->headers->GetStatusLine();
1402 out.response_info = *response3;
1403 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1404 EXPECT_EQ(OK, out.rv);
1405 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1406 EXPECT_EQ("hello!hello!", out.response_data);
1408 out.rv = callback4.WaitForResult();
1409 EXPECT_EQ(OK, out.rv);
1410 const HttpResponseInfo* response4 = trans4->GetResponseInfo();
1411 out.status_line = response4->headers->GetStatusLine();
1412 out.response_info = *response4;
1413 out.rv = ReadTransaction(trans4.get(), &out.response_data);
1414 EXPECT_EQ(OK, out.rv);
1415 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1416 EXPECT_EQ("hello!", out.response_data);
1417 helper.VerifyDataConsumed();
1418 EXPECT_EQ(OK, out.rv);
1421 // Similar to ThreeGetsMaxConcurrrent above, however, this test
1422 // deletes a session in the middle of the transaction to insure
1423 // that we properly remove pendingcreatestream objects from
1424 // the spdy_session
1425 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
1426 // Construct the request.
1427 scoped_ptr<SpdyFrame> req(
1428 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1429 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1430 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1431 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
1433 scoped_ptr<SpdyFrame> req2(
1434 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1435 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1436 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1437 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1439 SettingsMap settings;
1440 const uint32 max_concurrent_streams = 1;
1441 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1442 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1443 scoped_ptr<SpdyFrame> settings_frame(
1444 spdy_util_.ConstructSpdySettings(settings));
1445 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1447 MockWrite writes[] = {
1448 CreateMockWrite(*req),
1449 CreateMockWrite(*settings_ack, 2),
1450 CreateMockWrite(*req2),
1452 MockRead reads[] = {
1453 CreateMockRead(*settings_frame, 1),
1454 CreateMockRead(*resp),
1455 CreateMockRead(*body),
1456 CreateMockRead(*fbody),
1457 CreateMockRead(*resp2, 8),
1458 CreateMockRead(*body2),
1459 CreateMockRead(*fbody2),
1460 MockRead(ASYNC, 0, 0), // EOF
1463 OrderedSocketData data(reads, arraysize(reads),
1464 writes, arraysize(writes));
1465 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1467 BoundNetLog log;
1468 TransactionHelperResult out;
1469 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1470 BoundNetLog(), GetParam(), NULL);
1471 helper.RunPreTestSetup();
1472 helper.AddData(&data);
1473 // We require placeholder data because three get requests are sent out, so
1474 // there needs to be three sets of SSL connection data.
1475 helper.AddData(&data_placeholder);
1476 helper.AddData(&data_placeholder);
1477 scoped_ptr<HttpNetworkTransaction> trans1(
1478 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1479 scoped_ptr<HttpNetworkTransaction> trans2(
1480 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1481 scoped_ptr<HttpNetworkTransaction> trans3(
1482 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1484 TestCompletionCallback callback1;
1485 TestCompletionCallback callback2;
1486 TestCompletionCallback callback3;
1488 HttpRequestInfo httpreq1 = CreateGetRequest();
1489 HttpRequestInfo httpreq2 = CreateGetRequest();
1490 HttpRequestInfo httpreq3 = CreateGetRequest();
1492 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1493 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1494 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1495 out.rv = callback1.WaitForResult();
1496 ASSERT_EQ(OK, out.rv);
1498 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1499 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1500 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1501 delete trans3.release();
1502 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1503 out.rv = callback2.WaitForResult();
1504 ASSERT_EQ(OK, out.rv);
1506 EXPECT_EQ(8U, data.read_index());
1508 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1509 ASSERT_TRUE(response1 != NULL);
1510 EXPECT_TRUE(response1->headers.get() != NULL);
1511 EXPECT_TRUE(response1->was_fetched_via_spdy);
1512 out.status_line = response1->headers->GetStatusLine();
1513 out.response_info = *response1;
1514 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1515 EXPECT_EQ(OK, out.rv);
1516 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1517 EXPECT_EQ("hello!hello!", out.response_data);
1519 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1520 ASSERT_TRUE(response2 != NULL);
1521 out.status_line = response2->headers->GetStatusLine();
1522 out.response_info = *response2;
1523 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1524 EXPECT_EQ(OK, out.rv);
1525 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1526 EXPECT_EQ("hello!hello!", out.response_data);
1527 helper.VerifyDataConsumed();
1528 EXPECT_EQ(OK, out.rv);
1531 namespace {
1533 // The KillerCallback will delete the transaction on error as part of the
1534 // callback.
1535 class KillerCallback : public TestCompletionCallbackBase {
1536 public:
1537 explicit KillerCallback(HttpNetworkTransaction* transaction)
1538 : transaction_(transaction),
1539 callback_(base::Bind(&KillerCallback::OnComplete,
1540 base::Unretained(this))) {
1543 virtual ~KillerCallback() {}
1545 const CompletionCallback& callback() const { return callback_; }
1547 private:
1548 void OnComplete(int result) {
1549 if (result < 0)
1550 delete transaction_;
1552 SetResult(result);
1555 HttpNetworkTransaction* transaction_;
1556 CompletionCallback callback_;
1559 } // namespace
1561 // Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1562 // closes the socket while we have a pending transaction waiting for
1563 // a pending stream creation. http://crbug.com/52901
1564 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
1565 // Construct the request.
1566 scoped_ptr<SpdyFrame> req(
1567 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1568 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1569 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1570 scoped_ptr<SpdyFrame> fin_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1572 scoped_ptr<SpdyFrame> req2(
1573 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1574 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1576 SettingsMap settings;
1577 const uint32 max_concurrent_streams = 1;
1578 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1579 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1580 scoped_ptr<SpdyFrame> settings_frame(
1581 spdy_util_.ConstructSpdySettings(settings));
1582 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1584 MockWrite writes[] = {
1585 CreateMockWrite(*req),
1586 CreateMockWrite(*settings_ack, 2),
1587 CreateMockWrite(*req2),
1589 MockRead reads[] = {
1590 CreateMockRead(*settings_frame, 1),
1591 CreateMockRead(*resp),
1592 CreateMockRead(*body),
1593 CreateMockRead(*fin_body),
1594 CreateMockRead(*resp2, 8),
1595 MockRead(ASYNC, ERR_CONNECTION_RESET, 0), // Abort!
1598 OrderedSocketData data(reads, arraysize(reads),
1599 writes, arraysize(writes));
1600 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1602 BoundNetLog log;
1603 TransactionHelperResult out;
1604 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1605 BoundNetLog(), GetParam(), NULL);
1606 helper.RunPreTestSetup();
1607 helper.AddData(&data);
1608 // We require placeholder data because three get requests are sent out, so
1609 // there needs to be three sets of SSL connection data.
1610 helper.AddData(&data_placeholder);
1611 helper.AddData(&data_placeholder);
1612 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session().get());
1613 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session().get());
1614 HttpNetworkTransaction* trans3(
1615 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1617 TestCompletionCallback callback1;
1618 TestCompletionCallback callback2;
1619 KillerCallback callback3(trans3);
1621 HttpRequestInfo httpreq1 = CreateGetRequest();
1622 HttpRequestInfo httpreq2 = CreateGetRequest();
1623 HttpRequestInfo httpreq3 = CreateGetRequest();
1625 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
1626 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1627 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1628 out.rv = callback1.WaitForResult();
1629 ASSERT_EQ(OK, out.rv);
1631 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
1632 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1633 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1634 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1635 out.rv = callback3.WaitForResult();
1636 ASSERT_EQ(ERR_ABORTED, out.rv);
1638 EXPECT_EQ(6U, data.read_index());
1640 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
1641 ASSERT_TRUE(response1 != NULL);
1642 EXPECT_TRUE(response1->headers.get() != NULL);
1643 EXPECT_TRUE(response1->was_fetched_via_spdy);
1644 out.status_line = response1->headers->GetStatusLine();
1645 out.response_info = *response1;
1646 out.rv = ReadTransaction(&trans1, &out.response_data);
1647 EXPECT_EQ(OK, out.rv);
1649 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
1650 ASSERT_TRUE(response2 != NULL);
1651 out.status_line = response2->headers->GetStatusLine();
1652 out.response_info = *response2;
1653 out.rv = ReadTransaction(&trans2, &out.response_data);
1654 EXPECT_EQ(ERR_CONNECTION_RESET, out.rv);
1656 helper.VerifyDataConsumed();
1659 // Test that a simple PUT request works.
1660 TEST_P(SpdyNetworkTransactionTest, Put) {
1661 // Setup the request
1662 HttpRequestInfo request;
1663 request.method = "PUT";
1664 request.url = GURL("http://www.google.com/");
1666 scoped_ptr<SpdyHeaderBlock> put_headers(
1667 spdy_util_.ConstructPutHeaderBlock("http://www.google.com", 0));
1668 scoped_ptr<SpdyFrame> req(
1669 spdy_util_.ConstructSpdySyn(1, *put_headers, LOWEST, false, true));
1670 MockWrite writes[] = {
1671 CreateMockWrite(*req),
1674 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1675 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1676 MockRead reads[] = {
1677 CreateMockRead(*resp),
1678 CreateMockRead(*body),
1679 MockRead(ASYNC, 0, 0) // EOF
1682 DelayedSocketData data(1, reads, arraysize(reads),
1683 writes, arraysize(writes));
1684 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1685 BoundNetLog(), GetParam(), NULL);
1686 helper.RunToCompletion(&data);
1687 TransactionHelperResult out = helper.output();
1689 EXPECT_EQ(OK, out.rv);
1690 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1693 // Test that a simple HEAD request works.
1694 TEST_P(SpdyNetworkTransactionTest, Head) {
1695 // Setup the request
1696 HttpRequestInfo request;
1697 request.method = "HEAD";
1698 request.url = GURL("http://www.google.com/");
1700 scoped_ptr<SpdyHeaderBlock> head_headers(
1701 spdy_util_.ConstructHeadHeaderBlock("http://www.google.com", 0));
1702 scoped_ptr<SpdyFrame> req(
1703 spdy_util_.ConstructSpdySyn(1, *head_headers, LOWEST, false, true));
1704 MockWrite writes[] = {
1705 CreateMockWrite(*req),
1708 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1709 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1710 MockRead reads[] = {
1711 CreateMockRead(*resp),
1712 CreateMockRead(*body),
1713 MockRead(ASYNC, 0, 0) // EOF
1716 DelayedSocketData data(1, reads, arraysize(reads),
1717 writes, arraysize(writes));
1718 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1719 BoundNetLog(), GetParam(), NULL);
1720 helper.RunToCompletion(&data);
1721 TransactionHelperResult out = helper.output();
1723 EXPECT_EQ(OK, out.rv);
1724 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1727 // Test that a simple POST works.
1728 TEST_P(SpdyNetworkTransactionTest, Post) {
1729 scoped_ptr<SpdyFrame> req(
1730 spdy_util_.ConstructSpdyPost(
1731 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
1732 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1733 MockWrite writes[] = {
1734 CreateMockWrite(*req),
1735 CreateMockWrite(*body), // POST upload frame
1738 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1739 MockRead reads[] = {
1740 CreateMockRead(*resp),
1741 CreateMockRead(*body),
1742 MockRead(ASYNC, 0, 0) // EOF
1745 DelayedSocketData data(2, reads, arraysize(reads),
1746 writes, arraysize(writes));
1747 NormalSpdyTransactionHelper helper(CreatePostRequest(), DEFAULT_PRIORITY,
1748 BoundNetLog(), GetParam(), NULL);
1749 helper.RunToCompletion(&data);
1750 TransactionHelperResult out = helper.output();
1751 EXPECT_EQ(OK, out.rv);
1752 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1753 EXPECT_EQ("hello!", out.response_data);
1756 // Test that a POST with a file works.
1757 TEST_P(SpdyNetworkTransactionTest, FilePost) {
1758 scoped_ptr<SpdyFrame> req(
1759 spdy_util_.ConstructSpdyPost(
1760 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
1761 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1762 MockWrite writes[] = {
1763 CreateMockWrite(*req),
1764 CreateMockWrite(*body), // POST upload frame
1767 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1768 MockRead reads[] = {
1769 CreateMockRead(*resp),
1770 CreateMockRead(*body),
1771 MockRead(ASYNC, 0, 0) // EOF
1774 DelayedSocketData data(2, reads, arraysize(reads),
1775 writes, arraysize(writes));
1776 NormalSpdyTransactionHelper helper(CreateFilePostRequest(), DEFAULT_PRIORITY,
1777 BoundNetLog(), GetParam(), NULL);
1778 helper.RunToCompletion(&data);
1779 TransactionHelperResult out = helper.output();
1780 EXPECT_EQ(OK, out.rv);
1781 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1782 EXPECT_EQ("hello!", out.response_data);
1785 // Test that a POST with a unreadable file fails.
1786 TEST_P(SpdyNetworkTransactionTest, UnreadableFilePost) {
1787 MockWrite writes[] = {
1788 MockWrite(ASYNC, 0, 0) // EOF
1790 MockRead reads[] = {
1791 MockRead(ASYNC, 0, 0) // EOF
1794 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
1795 NormalSpdyTransactionHelper helper(CreateUnreadableFilePostRequest(),
1796 DEFAULT_PRIORITY,
1797 BoundNetLog(), GetParam(), NULL);
1798 helper.RunPreTestSetup();
1799 helper.AddData(&data);
1800 helper.RunDefaultTest();
1802 base::RunLoop().RunUntilIdle();
1803 helper.VerifyDataNotConsumed();
1804 EXPECT_EQ(ERR_ACCESS_DENIED, helper.output().rv);
1807 // Test that a complex POST works.
1808 TEST_P(SpdyNetworkTransactionTest, ComplexPost) {
1809 scoped_ptr<SpdyFrame> req(
1810 spdy_util_.ConstructSpdyPost(
1811 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
1812 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1813 MockWrite writes[] = {
1814 CreateMockWrite(*req),
1815 CreateMockWrite(*body), // POST upload frame
1818 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1819 MockRead reads[] = {
1820 CreateMockRead(*resp),
1821 CreateMockRead(*body),
1822 MockRead(ASYNC, 0, 0) // EOF
1825 DelayedSocketData data(2, reads, arraysize(reads),
1826 writes, arraysize(writes));
1827 NormalSpdyTransactionHelper helper(CreateComplexPostRequest(),
1828 DEFAULT_PRIORITY,
1829 BoundNetLog(), GetParam(), NULL);
1830 helper.RunToCompletion(&data);
1831 TransactionHelperResult out = helper.output();
1832 EXPECT_EQ(OK, out.rv);
1833 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1834 EXPECT_EQ("hello!", out.response_data);
1837 // Test that a chunked POST works.
1838 TEST_P(SpdyNetworkTransactionTest, ChunkedPost) {
1839 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1840 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1841 MockWrite writes[] = {
1842 CreateMockWrite(*req),
1843 CreateMockWrite(*body),
1846 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1847 MockRead reads[] = {
1848 CreateMockRead(*resp),
1849 CreateMockRead(*body),
1850 MockRead(ASYNC, 0, 0) // EOF
1853 DelayedSocketData data(2, reads, arraysize(reads),
1854 writes, arraysize(writes));
1855 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
1856 DEFAULT_PRIORITY,
1857 BoundNetLog(), GetParam(), NULL);
1859 // These chunks get merged into a single frame when being sent.
1860 const int kFirstChunkSize = kUploadDataSize/2;
1861 helper.request().upload_data_stream->AppendChunk(
1862 kUploadData, kFirstChunkSize, false);
1863 helper.request().upload_data_stream->AppendChunk(
1864 kUploadData + kFirstChunkSize, kUploadDataSize - kFirstChunkSize, true);
1866 helper.RunToCompletion(&data);
1867 TransactionHelperResult out = helper.output();
1868 EXPECT_EQ(OK, out.rv);
1869 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1870 EXPECT_EQ(kUploadData, out.response_data);
1873 // Test that a chunked POST works with chunks appended after transaction starts.
1874 TEST_P(SpdyNetworkTransactionTest, DelayedChunkedPost) {
1875 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1876 scoped_ptr<SpdyFrame> chunk1(spdy_util_.ConstructSpdyBodyFrame(1, false));
1877 scoped_ptr<SpdyFrame> chunk2(spdy_util_.ConstructSpdyBodyFrame(1, false));
1878 scoped_ptr<SpdyFrame> chunk3(spdy_util_.ConstructSpdyBodyFrame(1, true));
1879 MockWrite writes[] = {
1880 CreateMockWrite(*req),
1881 CreateMockWrite(*chunk1),
1882 CreateMockWrite(*chunk2),
1883 CreateMockWrite(*chunk3),
1886 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1887 MockRead reads[] = {
1888 CreateMockRead(*resp),
1889 CreateMockRead(*chunk1),
1890 CreateMockRead(*chunk2),
1891 CreateMockRead(*chunk3),
1892 MockRead(ASYNC, 0, 0) // EOF
1895 DelayedSocketData data(4, reads, arraysize(reads),
1896 writes, arraysize(writes));
1897 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
1898 DEFAULT_PRIORITY,
1899 BoundNetLog(), GetParam(), NULL);
1901 helper.request().upload_data_stream->AppendChunk(
1902 kUploadData, kUploadDataSize, false);
1904 helper.RunPreTestSetup();
1905 helper.AddData(&data);
1906 ASSERT_TRUE(helper.StartDefaultTest());
1908 base::RunLoop().RunUntilIdle();
1909 helper.request().upload_data_stream->AppendChunk(
1910 kUploadData, kUploadDataSize, false);
1911 base::RunLoop().RunUntilIdle();
1912 helper.request().upload_data_stream->AppendChunk(
1913 kUploadData, kUploadDataSize, true);
1915 helper.FinishDefaultTest();
1916 helper.VerifyDataConsumed();
1918 std::string expected_response;
1919 expected_response += kUploadData;
1920 expected_response += kUploadData;
1921 expected_response += kUploadData;
1923 TransactionHelperResult out = helper.output();
1924 EXPECT_EQ(OK, out.rv);
1925 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1926 EXPECT_EQ(expected_response, out.response_data);
1929 // Test that a POST without any post data works.
1930 TEST_P(SpdyNetworkTransactionTest, NullPost) {
1931 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
1932 // Setup the request
1933 HttpRequestInfo request;
1934 request.method = "POST";
1935 request.url = GURL(kRequestUrl);
1936 // Create an empty UploadData.
1937 request.upload_data_stream = NULL;
1939 // When request.upload_data_stream is NULL for post, content-length is
1940 // expected to be 0.
1941 scoped_ptr<SpdyHeaderBlock> req_block(
1942 spdy_util_.ConstructPostHeaderBlock(kRequestUrl, 0));
1943 scoped_ptr<SpdyFrame> req(
1944 spdy_util_.ConstructSpdySyn(1, *req_block, LOWEST, false, true));
1946 MockWrite writes[] = {
1947 CreateMockWrite(*req),
1950 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1951 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1952 MockRead reads[] = {
1953 CreateMockRead(*resp),
1954 CreateMockRead(*body),
1955 MockRead(ASYNC, 0, 0) // EOF
1958 DelayedSocketData data(1, reads, arraysize(reads),
1959 writes, arraysize(writes));
1961 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1962 BoundNetLog(), GetParam(), NULL);
1963 helper.RunToCompletion(&data);
1964 TransactionHelperResult out = helper.output();
1965 EXPECT_EQ(OK, out.rv);
1966 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1967 EXPECT_EQ("hello!", out.response_data);
1970 // Test that a simple POST works.
1971 TEST_P(SpdyNetworkTransactionTest, EmptyPost) {
1972 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
1973 // Create an empty UploadDataStream.
1974 ScopedVector<UploadElementReader> element_readers;
1975 UploadDataStream stream(element_readers.Pass(), 0);
1977 // Setup the request
1978 HttpRequestInfo request;
1979 request.method = "POST";
1980 request.url = GURL(kRequestUrl);
1981 request.upload_data_stream = &stream;
1983 const uint64 kContentLength = 0;
1985 scoped_ptr<SpdyHeaderBlock> req_block(
1986 spdy_util_.ConstructPostHeaderBlock(kRequestUrl, kContentLength));
1987 scoped_ptr<SpdyFrame> req(
1988 spdy_util_.ConstructSpdySyn(1, *req_block, LOWEST, false, true));
1990 MockWrite writes[] = {
1991 CreateMockWrite(*req),
1994 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1995 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1996 MockRead reads[] = {
1997 CreateMockRead(*resp),
1998 CreateMockRead(*body),
1999 MockRead(ASYNC, 0, 0) // EOF
2002 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
2004 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
2005 BoundNetLog(), GetParam(), NULL);
2006 helper.RunToCompletion(&data);
2007 TransactionHelperResult out = helper.output();
2008 EXPECT_EQ(OK, out.rv);
2009 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
2010 EXPECT_EQ("hello!", out.response_data);
2013 // While we're doing a post, the server sends the reply before upload completes.
2014 TEST_P(SpdyNetworkTransactionTest, ResponseBeforePostCompletes) {
2015 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
2016 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2017 MockWrite writes[] = {
2018 CreateMockWrite(*req, 0),
2019 CreateMockWrite(*body, 3),
2021 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
2022 MockRead reads[] = {
2023 CreateMockRead(*resp, 1),
2024 CreateMockRead(*body, 2),
2025 MockRead(ASYNC, 0, 4) // EOF
2028 // Write the request headers, and read the complete response
2029 // while still waiting for chunked request data.
2030 DeterministicSocketData data(reads, arraysize(reads),
2031 writes, arraysize(writes));
2032 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
2033 DEFAULT_PRIORITY,
2034 BoundNetLog(), GetParam(), NULL);
2035 helper.SetDeterministic();
2036 helper.RunPreTestSetup();
2037 helper.AddDeterministicData(&data);
2039 ASSERT_TRUE(helper.StartDefaultTest());
2041 // Process the request headers, SYN_REPLY, and response body.
2042 // The request body is still in flight.
2043 data.RunFor(3);
2045 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
2046 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2048 // Finish sending the request body.
2049 helper.request().upload_data_stream->AppendChunk(
2050 kUploadData, kUploadDataSize, true);
2051 data.RunFor(2);
2053 std::string response_body;
2054 EXPECT_EQ(OK, ReadTransaction(helper.trans(), &response_body));
2055 EXPECT_EQ(kUploadData, response_body);
2056 helper.VerifyDataConsumed();
2059 // 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.
2062 TEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
2063 scoped_ptr<SpdyFrame> req(
2064 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2065 scoped_ptr<SpdyFrame> rst(
2066 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2067 MockWrite writes[] = {
2068 CreateMockWrite(*req.get(), 0, SYNCHRONOUS),
2069 MockWrite(SYNCHRONOUS, 0, 0, 2),
2070 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
2073 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2074 MockRead reads[] = {
2075 CreateMockRead(*resp.get(), 1, ASYNC),
2076 MockRead(ASYNC, 0, 0, 4) // EOF
2079 DeterministicSocketData data(reads, arraysize(reads),
2080 writes, arraysize(writes));
2081 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2082 BoundNetLog(), GetParam(), NULL);
2083 helper.SetDeterministic();
2084 helper.RunPreTestSetup();
2085 helper.AddDeterministicData(&data);
2086 HttpNetworkTransaction* trans = helper.trans();
2088 TestCompletionCallback callback;
2089 int rv = trans->Start(
2090 &CreateGetRequest(), callback.callback(), BoundNetLog());
2091 EXPECT_EQ(ERR_IO_PENDING, rv);
2093 data.SetStop(2);
2094 data.Run();
2095 helper.ResetTrans();
2096 data.SetStop(20);
2097 data.Run();
2099 helper.VerifyDataConsumed();
2102 // Test that the transaction doesn't crash when we don't have a reply.
2103 TEST_P(SpdyNetworkTransactionTest, ResponseWithoutSynReply) {
2104 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2105 MockRead reads[] = {
2106 CreateMockRead(*body),
2107 MockRead(ASYNC, 0, 0) // EOF
2110 DelayedSocketData data(1, reads, arraysize(reads), NULL, 0);
2111 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2112 BoundNetLog(), GetParam(), NULL);
2113 helper.RunToCompletion(&data);
2114 TransactionHelperResult out = helper.output();
2115 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
2118 // Test that the transaction doesn't crash when we get two replies on the same
2119 // stream ID. See http://crbug.com/45639.
2120 TEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
2121 scoped_ptr<SpdyFrame> req(
2122 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2123 scoped_ptr<SpdyFrame> rst(
2124 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
2125 MockWrite writes[] = {
2126 CreateMockWrite(*req),
2127 CreateMockWrite(*rst),
2130 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2131 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2132 MockRead reads[] = {
2133 CreateMockRead(*resp),
2134 CreateMockRead(*resp),
2135 CreateMockRead(*body),
2136 MockRead(ASYNC, 0, 0) // EOF
2139 DelayedSocketData data(1, reads, arraysize(reads),
2140 writes, arraysize(writes));
2142 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2143 BoundNetLog(), GetParam(), NULL);
2144 helper.RunPreTestSetup();
2145 helper.AddData(&data);
2147 HttpNetworkTransaction* trans = helper.trans();
2149 TestCompletionCallback callback;
2150 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2151 EXPECT_EQ(ERR_IO_PENDING, rv);
2152 rv = callback.WaitForResult();
2153 EXPECT_EQ(OK, rv);
2155 const HttpResponseInfo* response = trans->GetResponseInfo();
2156 ASSERT_TRUE(response != NULL);
2157 EXPECT_TRUE(response->headers.get() != NULL);
2158 EXPECT_TRUE(response->was_fetched_via_spdy);
2159 std::string response_data;
2160 rv = ReadTransaction(trans, &response_data);
2161 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
2163 helper.VerifyDataConsumed();
2166 TEST_P(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) {
2167 // Construct the request.
2168 scoped_ptr<SpdyFrame> req(
2169 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2170 scoped_ptr<SpdyFrame> rst(
2171 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
2172 MockWrite writes[] = {
2173 CreateMockWrite(*req),
2174 CreateMockWrite(*rst),
2177 const char* const headers[] = {
2178 "transfer-encoding", "chunked"
2180 scoped_ptr<SpdyFrame> resp(
2181 spdy_util_.ConstructSpdyGetSynReply(headers, 1, 1));
2182 scoped_ptr<SpdyFrame> body(
2183 spdy_util_.ConstructSpdyBodyFrame(1, true));
2184 MockRead reads[] = {
2185 CreateMockRead(*resp),
2186 CreateMockRead(*body),
2187 MockRead(ASYNC, 0, 0) // EOF
2190 DelayedSocketData data(1, reads, arraysize(reads),
2191 writes, arraysize(writes));
2192 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2193 BoundNetLog(), GetParam(), NULL);
2194 helper.RunToCompletion(&data);
2195 TransactionHelperResult out = helper.output();
2196 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
2198 helper.session()->spdy_session_pool()->CloseAllSessions();
2199 helper.VerifyDataConsumed();
2202 TEST_P(SpdyNetworkTransactionTest, ResetPushWithTransferEncoding) {
2203 // Construct the request.
2204 scoped_ptr<SpdyFrame> req(
2205 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2206 scoped_ptr<SpdyFrame> rst(
2207 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
2208 MockWrite writes[] = {
2209 CreateMockWrite(*req),
2210 CreateMockWrite(*rst),
2213 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2214 const char* const headers[] = {
2215 "transfer-encoding", "chunked"
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));
2221 MockRead reads[] = {
2222 CreateMockRead(*resp),
2223 CreateMockRead(*push),
2224 CreateMockRead(*body),
2225 MockRead(ASYNC, 0, 0) // EOF
2228 DelayedSocketData data(1, reads, arraysize(reads),
2229 writes, arraysize(writes));
2230 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2231 BoundNetLog(), GetParam(), NULL);
2232 helper.RunToCompletion(&data);
2233 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);
2238 helper.session()->spdy_session_pool()->CloseAllSessions();
2239 helper.VerifyDataConsumed();
2242 TEST_P(SpdyNetworkTransactionTest, CancelledTransaction) {
2243 // Construct the request.
2244 scoped_ptr<SpdyFrame> req(
2245 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2246 MockWrite writes[] = {
2247 CreateMockWrite(*req),
2250 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2251 MockRead reads[] = {
2252 CreateMockRead(*resp),
2253 // This following read isn't used by the test, except during the
2254 // RunUntilIdle() call at the end since the SpdySession survives the
2255 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
2256 // MockRead will do here.
2257 MockRead(ASYNC, 0, 0) // EOF
2260 StaticSocketDataProvider data(reads, arraysize(reads),
2261 writes, arraysize(writes));
2263 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2264 BoundNetLog(), GetParam(), NULL);
2265 helper.RunPreTestSetup();
2266 helper.AddData(&data);
2267 HttpNetworkTransaction* trans = helper.trans();
2269 TestCompletionCallback callback;
2270 int rv = trans->Start(
2271 &CreateGetRequest(), callback.callback(), BoundNetLog());
2272 EXPECT_EQ(ERR_IO_PENDING, rv);
2273 helper.ResetTrans(); // Cancel the transaction.
2275 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
2276 // MockClientSocketFactory) are still alive.
2277 base::RunLoop().RunUntilIdle();
2278 helper.VerifyDataNotConsumed();
2281 // Verify that the client sends a Rst Frame upon cancelling the stream.
2282 TEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
2283 scoped_ptr<SpdyFrame> req(
2284 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2285 scoped_ptr<SpdyFrame> rst(
2286 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2287 MockWrite writes[] = {
2288 CreateMockWrite(*req, 0, SYNCHRONOUS),
2289 CreateMockWrite(*rst, 2, SYNCHRONOUS),
2292 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2293 MockRead reads[] = {
2294 CreateMockRead(*resp, 1, ASYNC),
2295 MockRead(ASYNC, 0, 0, 3) // EOF
2298 DeterministicSocketData data(reads, arraysize(reads),
2299 writes, arraysize(writes));
2301 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2302 BoundNetLog(),
2303 GetParam(), NULL);
2304 helper.SetDeterministic();
2305 helper.RunPreTestSetup();
2306 helper.AddDeterministicData(&data);
2307 HttpNetworkTransaction* trans = helper.trans();
2309 TestCompletionCallback callback;
2311 int rv = trans->Start(
2312 &CreateGetRequest(), callback.callback(), BoundNetLog());
2313 EXPECT_EQ(ERR_IO_PENDING, rv);
2315 data.SetStop(2);
2316 data.Run();
2317 helper.ResetTrans();
2318 data.SetStop(20);
2319 data.Run();
2321 helper.VerifyDataConsumed();
2324 // 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
2327 TEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
2328 scoped_ptr<SpdyFrame> req(
2329 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2330 MockWrite writes[] = { CreateMockWrite(*req) };
2331 MockWrite writes2[] = { CreateMockWrite(*req) };
2333 // 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
2335 // 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', '!',
2342 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2343 MockRead reads[] = {
2344 CreateMockRead(*resp, 2),
2345 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause
2346 MockRead(ASYNC, reinterpret_cast<const char*>(kGetBodyFrame2),
2347 arraysize(kGetBodyFrame2), 4),
2348 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
2349 MockRead(ASYNC, 0, 0, 6), // EOF
2351 MockRead reads2[] = {
2352 CreateMockRead(*resp, 2),
2353 MockRead(ASYNC, 0, 0, 3), // EOF
2356 OrderedSocketData data(reads, arraysize(reads),
2357 writes, arraysize(writes));
2358 DelayedSocketData data2(1, reads2, arraysize(reads2),
2359 writes2, arraysize(writes2));
2361 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2362 BoundNetLog(), GetParam(), NULL);
2363 helper.RunPreTestSetup();
2364 helper.AddData(&data);
2365 helper.AddData(&data2);
2366 HttpNetworkTransaction* trans = helper.trans();
2368 // Start the transaction with basic parameters.
2369 TestCompletionCallback callback;
2370 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2371 EXPECT_EQ(ERR_IO_PENDING, rv);
2372 rv = callback.WaitForResult();
2374 const int kSize = 3000;
2375 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
2376 rv = trans->Read(
2377 buf.get(),
2378 kSize,
2379 base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback,
2380 helper.session()));
2381 // This forces an err_IO_pending, which sets the callback.
2382 data.CompleteRead();
2383 // This finishes the read.
2384 data.CompleteRead();
2385 helper.VerifyDataConsumed();
2388 // 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
2391 TEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
2392 scoped_ptr<SpdyFrame> req(
2393 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2394 MockWrite writes[] = { CreateMockWrite(*req) };
2396 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2397 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2398 MockRead reads[] = {
2399 CreateMockRead(*resp.get(), 2),
2400 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause
2401 CreateMockRead(*body.get(), 4),
2402 MockRead(ASYNC, 0, 0, 5), // EOF
2405 OrderedSocketData data(reads, arraysize(reads),
2406 writes, arraysize(writes));
2408 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2409 BoundNetLog(), GetParam(), NULL);
2410 helper.RunPreTestSetup();
2411 helper.AddData(&data);
2412 HttpNetworkTransaction* trans = helper.trans();
2414 // Start the transaction with basic parameters.
2415 TestCompletionCallback callback;
2416 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2417 EXPECT_EQ(ERR_IO_PENDING, rv);
2418 rv = callback.WaitForResult();
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.
2422 const int kSize = 3000;
2423 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
2424 rv = trans->Read(
2425 buf.get(),
2426 kSize,
2427 base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback,
2428 base::Unretained(&helper)));
2429 ASSERT_EQ(ERR_IO_PENDING, rv);
2430 data.CompleteRead();
2432 // Finish running rest of tasks.
2433 base::RunLoop().RunUntilIdle();
2434 helper.VerifyDataConsumed();
2437 // Send a spdy request to www.google.com that gets redirected to www.foo.com.
2438 TEST_P(SpdyNetworkTransactionTest, RedirectGetRequest) {
2439 scoped_ptr<SpdyHeaderBlock> headers(
2440 spdy_util_.ConstructGetHeaderBlock("http://www.google.com/"));
2441 (*headers)["user-agent"] = "";
2442 (*headers)["accept-encoding"] = "gzip,deflate";
2443 scoped_ptr<SpdyHeaderBlock> headers2(
2444 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2445 (*headers2)["user-agent"] = "";
2446 (*headers2)["accept-encoding"] = "gzip,deflate";
2448 // Setup writes/reads to www.google.com
2449 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));
2453 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReplyRedirect(1));
2454 MockWrite writes[] = {
2455 CreateMockWrite(*req, 1),
2457 MockRead reads[] = {
2458 CreateMockRead(*resp, 2),
2459 MockRead(ASYNC, 0, 0, 3) // EOF
2462 // Setup writes/reads to www.foo.com
2463 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2464 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
2465 MockWrite writes2[] = {
2466 CreateMockWrite(*req2, 1),
2468 MockRead reads2[] = {
2469 CreateMockRead(*resp2, 2),
2470 CreateMockRead(*body2, 3),
2471 MockRead(ASYNC, 0, 0, 4) // EOF
2473 OrderedSocketData data(reads, arraysize(reads),
2474 writes, arraysize(writes));
2475 OrderedSocketData data2(reads2, arraysize(reads2),
2476 writes2, arraysize(writes2));
2478 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2479 TestDelegate d;
2481 SpdyURLRequestContext spdy_url_request_context(
2482 GetParam().protocol,
2483 false /* force_spdy_over_ssl*/,
2484 true /* force_spdy_always */);
2485 scoped_ptr<URLRequest> r(
2486 spdy_url_request_context.CreateRequest(GURL("http://www.google.com/"),
2487 DEFAULT_PRIORITY,
2489 NULL));
2490 spdy_url_request_context.socket_factory().
2491 AddSocketDataProvider(&data);
2492 spdy_url_request_context.socket_factory().
2493 AddSocketDataProvider(&data2);
2495 d.set_quit_on_redirect(true);
2496 r->Start();
2497 base::RunLoop().Run();
2499 EXPECT_EQ(1, d.received_redirect_count());
2501 r->FollowDeferredRedirect();
2502 base::RunLoop().Run();
2503 EXPECT_EQ(1, d.response_started_count());
2504 EXPECT_FALSE(d.received_data_before_response());
2505 EXPECT_EQ(net::URLRequestStatus::SUCCESS, r->status().status());
2506 std::string contents("hello!");
2507 EXPECT_EQ(contents, d.data_received());
2509 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());
2515 // Send a spdy request to www.google.com. Get a pushed stream that redirects to
2516 // www.foo.com.
2517 TEST_P(SpdyNetworkTransactionTest, RedirectServerPush) {
2518 scoped_ptr<SpdyHeaderBlock> headers(
2519 spdy_util_.ConstructGetHeaderBlock("http://www.google.com/"));
2520 (*headers)["user-agent"] = "";
2521 (*headers)["accept-encoding"] = "gzip,deflate";
2523 // Setup writes/reads to www.google.com
2524 scoped_ptr<SpdyFrame> req(
2525 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
2526 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2527 scoped_ptr<SpdyFrame> rep(
2528 spdy_util_.ConstructSpdyPush(NULL,
2532 "http://www.google.com/foo.dat",
2533 "301 Moved Permanently",
2534 "http://www.foo.com/index.php"));
2535 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2536 scoped_ptr<SpdyFrame> rst(
2537 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
2538 MockWrite writes[] = {
2539 CreateMockWrite(*req, 1),
2540 CreateMockWrite(*rst, 6),
2542 MockRead reads[] = {
2543 CreateMockRead(*resp, 2),
2544 CreateMockRead(*rep, 3),
2545 CreateMockRead(*body, 4),
2546 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
2547 MockRead(ASYNC, 0, 0, 7) // EOF
2550 // Setup writes/reads to www.foo.com
2551 scoped_ptr<SpdyHeaderBlock> headers2(
2552 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2553 (*headers2)["user-agent"] = "";
2554 (*headers2)["accept-encoding"] = "gzip,deflate";
2555 scoped_ptr<SpdyFrame> req2(
2556 spdy_util_.ConstructSpdySyn(1, *headers2, LOWEST, false, true));
2557 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2558 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
2559 MockWrite writes2[] = {
2560 CreateMockWrite(*req2, 1),
2562 MockRead reads2[] = {
2563 CreateMockRead(*resp2, 2),
2564 CreateMockRead(*body2, 3),
2565 MockRead(ASYNC, 0, 0, 5) // EOF
2567 OrderedSocketData data(reads, arraysize(reads),
2568 writes, arraysize(writes));
2569 OrderedSocketData data2(reads2, arraysize(reads2),
2570 writes2, arraysize(writes2));
2572 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2573 TestDelegate d;
2574 TestDelegate d2;
2575 SpdyURLRequestContext spdy_url_request_context(
2576 GetParam().protocol,
2577 false /* force_spdy_over_ssl*/,
2578 true /* force_spdy_always */);
2580 scoped_ptr<URLRequest> r(
2581 spdy_url_request_context.CreateRequest(GURL("http://www.google.com/"),
2582 DEFAULT_PRIORITY,
2584 NULL));
2585 spdy_url_request_context.socket_factory().
2586 AddSocketDataProvider(&data);
2588 r->Start();
2589 base::RunLoop().Run();
2591 EXPECT_EQ(0, d.received_redirect_count());
2592 std::string contents("hello!");
2593 EXPECT_EQ(contents, d.data_received());
2595 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));
2601 spdy_url_request_context.socket_factory().
2602 AddSocketDataProvider(&data2);
2604 d2.set_quit_on_redirect(true);
2605 r2->Start();
2606 base::RunLoop().Run();
2607 EXPECT_EQ(1, d2.received_redirect_count());
2609 r2->FollowDeferredRedirect();
2610 base::RunLoop().Run();
2611 EXPECT_EQ(1, d2.response_started_count());
2612 EXPECT_FALSE(d2.received_data_before_response());
2613 EXPECT_EQ(net::URLRequestStatus::SUCCESS, r2->status().status());
2614 std::string contents2("hello!");
2615 EXPECT_EQ(contents2, d2.data_received());
2617 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());
2625 TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
2626 scoped_ptr<SpdyFrame> stream1_syn(
2627 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2628 scoped_ptr<SpdyFrame> stream1_body(
2629 spdy_util_.ConstructSpdyBodyFrame(1, true));
2630 MockWrite writes[] = {
2631 CreateMockWrite(*stream1_syn, 1),
2634 scoped_ptr<SpdyFrame>
2635 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2636 scoped_ptr<SpdyFrame>
2637 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2641 "http://www.google.com/foo.dat"));
2642 const char kPushedData[] = "pushed";
2643 scoped_ptr<SpdyFrame> stream2_body(
2644 spdy_util_.ConstructSpdyBodyFrame(
2645 2, kPushedData, strlen(kPushedData), true));
2646 MockRead reads[] = {
2647 CreateMockRead(*stream1_reply, 2),
2648 CreateMockRead(*stream2_syn, 3),
2649 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2650 CreateMockRead(*stream2_body, 5),
2651 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2654 HttpResponseInfo response;
2655 HttpResponseInfo response2;
2656 std::string expected_push_result("pushed");
2657 OrderedSocketData data(reads, arraysize(reads),
2658 writes, arraysize(writes));
2659 RunServerPushTest(&data,
2660 &response,
2661 &response2,
2662 expected_push_result);
2664 // Verify the SYN_REPLY.
2665 EXPECT_TRUE(response.headers.get() != NULL);
2666 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2668 // Verify the pushed stream.
2669 EXPECT_TRUE(response2.headers.get() != NULL);
2670 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2673 TEST_P(SpdyNetworkTransactionTest, ServerPushBeforeSynReply) {
2674 scoped_ptr<SpdyFrame> stream1_syn(
2675 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2676 scoped_ptr<SpdyFrame> stream1_body(
2677 spdy_util_.ConstructSpdyBodyFrame(1, true));
2678 MockWrite writes[] = {
2679 CreateMockWrite(*stream1_syn, 1),
2682 scoped_ptr<SpdyFrame>
2683 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2684 scoped_ptr<SpdyFrame>
2685 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2689 "http://www.google.com/foo.dat"));
2690 const char kPushedData[] = "pushed";
2691 scoped_ptr<SpdyFrame> stream2_body(
2692 spdy_util_.ConstructSpdyBodyFrame(
2693 2, kPushedData, strlen(kPushedData), true));
2694 MockRead reads[] = {
2695 CreateMockRead(*stream2_syn, 2),
2696 CreateMockRead(*stream1_reply, 3),
2697 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2698 CreateMockRead(*stream2_body, 5),
2699 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2702 HttpResponseInfo response;
2703 HttpResponseInfo response2;
2704 std::string expected_push_result("pushed");
2705 OrderedSocketData data(reads, arraysize(reads),
2706 writes, arraysize(writes));
2707 RunServerPushTest(&data,
2708 &response,
2709 &response2,
2710 expected_push_result);
2712 // Verify the SYN_REPLY.
2713 EXPECT_TRUE(response.headers.get() != NULL);
2714 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2716 // Verify the pushed stream.
2717 EXPECT_TRUE(response2.headers.get() != NULL);
2718 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2721 TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
2722 scoped_ptr<SpdyFrame> stream1_syn(
2723 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2724 MockWrite writes[] = { CreateMockWrite(*stream1_syn, 1), };
2726 scoped_ptr<SpdyFrame>
2727 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2728 scoped_ptr<SpdyFrame>
2729 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2733 "http://www.google.com/foo.dat"));
2734 const char kPushedData[] = "pushed";
2735 scoped_ptr<SpdyFrame> stream2_body(
2736 spdy_util_.ConstructSpdyBodyFrame(
2737 2, kPushedData, strlen(kPushedData), true));
2738 scoped_ptr<SpdyFrame>
2739 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2740 MockRead reads[] = {
2741 CreateMockRead(*stream1_reply, 2),
2742 CreateMockRead(*stream2_syn, 3),
2743 CreateMockRead(*stream2_body, 4),
2744 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
2745 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2748 HttpResponseInfo response;
2749 HttpResponseInfo response2;
2750 std::string expected_push_result("pushed");
2751 OrderedSocketData data(reads, arraysize(reads),
2752 writes, arraysize(writes));
2753 RunServerPushTest(&data,
2754 &response,
2755 &response2,
2756 expected_push_result);
2758 // Verify the SYN_REPLY.
2759 EXPECT_TRUE(response.headers.get() != NULL);
2760 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2762 // Verify the pushed stream.
2763 EXPECT_TRUE(response2.headers.get() != NULL);
2764 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2767 TEST_P(SpdyNetworkTransactionTest, ServerPushServerAborted) {
2768 scoped_ptr<SpdyFrame> stream1_syn(
2769 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2770 scoped_ptr<SpdyFrame> stream1_body(
2771 spdy_util_.ConstructSpdyBodyFrame(1, true));
2772 MockWrite writes[] = {
2773 CreateMockWrite(*stream1_syn, 1),
2776 scoped_ptr<SpdyFrame>
2777 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2778 scoped_ptr<SpdyFrame>
2779 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2783 "http://www.google.com/foo.dat"));
2784 scoped_ptr<SpdyFrame> stream2_rst(
2785 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
2786 MockRead reads[] = {
2787 CreateMockRead(*stream1_reply, 2),
2788 CreateMockRead(*stream2_syn, 3),
2789 CreateMockRead(*stream2_rst, 4),
2790 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
2791 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2794 OrderedSocketData data(reads, arraysize(reads),
2795 writes, arraysize(writes));
2796 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2797 BoundNetLog(), GetParam(), NULL);
2799 helper.RunPreTestSetup();
2800 helper.AddData(&data);
2802 HttpNetworkTransaction* trans = helper.trans();
2804 // Start the transaction with basic parameters.
2805 TestCompletionCallback callback;
2806 int rv = trans->Start(
2807 &CreateGetRequest(), callback.callback(), BoundNetLog());
2808 EXPECT_EQ(ERR_IO_PENDING, rv);
2809 rv = callback.WaitForResult();
2810 EXPECT_EQ(OK, rv);
2812 // Verify that we consumed all test data.
2813 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
2814 << data.read_count()
2815 << " Read index: "
2816 << data.read_index();
2817 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
2818 << data.write_count()
2819 << " Write index: "
2820 << data.write_index();
2822 // Verify the SYN_REPLY.
2823 HttpResponseInfo response = *trans->GetResponseInfo();
2824 EXPECT_TRUE(response.headers.get() != NULL);
2825 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2828 // Verify that we don't leak streams and that we properly send a reset
2829 // if the server pushes the same stream twice.
2830 TEST_P(SpdyNetworkTransactionTest, ServerPushDuplicate) {
2831 scoped_ptr<SpdyFrame> stream1_syn(
2832 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2833 scoped_ptr<SpdyFrame> stream1_body(
2834 spdy_util_.ConstructSpdyBodyFrame(1, true));
2835 scoped_ptr<SpdyFrame> stream3_rst(
2836 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR));
2837 MockWrite writes[] = {
2838 CreateMockWrite(*stream1_syn, 1),
2839 CreateMockWrite(*stream3_rst, 5),
2842 scoped_ptr<SpdyFrame>
2843 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2844 scoped_ptr<SpdyFrame>
2845 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2849 "http://www.google.com/foo.dat"));
2850 const char kPushedData[] = "pushed";
2851 scoped_ptr<SpdyFrame> stream2_body(
2852 spdy_util_.ConstructSpdyBodyFrame(
2853 2, kPushedData, strlen(kPushedData), true));
2854 scoped_ptr<SpdyFrame>
2855 stream3_syn(spdy_util_.ConstructSpdyPush(NULL,
2859 "http://www.google.com/foo.dat"));
2860 MockRead reads[] = {
2861 CreateMockRead(*stream1_reply, 2),
2862 CreateMockRead(*stream2_syn, 3),
2863 CreateMockRead(*stream3_syn, 4),
2864 CreateMockRead(*stream1_body, 6, SYNCHRONOUS),
2865 CreateMockRead(*stream2_body, 7),
2866 MockRead(ASYNC, ERR_IO_PENDING, 8), // Force a pause
2869 HttpResponseInfo response;
2870 HttpResponseInfo response2;
2871 std::string expected_push_result("pushed");
2872 OrderedSocketData data(reads, arraysize(reads),
2873 writes, arraysize(writes));
2874 RunServerPushTest(&data,
2875 &response,
2876 &response2,
2877 expected_push_result);
2879 // Verify the SYN_REPLY.
2880 EXPECT_TRUE(response.headers.get() != NULL);
2881 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2883 // Verify the pushed stream.
2884 EXPECT_TRUE(response2.headers.get() != NULL);
2885 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2888 TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
2889 scoped_ptr<SpdyFrame> stream1_syn(
2890 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2891 scoped_ptr<SpdyFrame> stream1_body(
2892 spdy_util_.ConstructSpdyBodyFrame(1, true));
2893 MockWrite writes[] = {
2894 CreateMockWrite(*stream1_syn, 1),
2897 scoped_ptr<SpdyFrame>
2898 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2899 scoped_ptr<SpdyFrame>
2900 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2904 "http://www.google.com/foo.dat"));
2905 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));
2920 MockRead reads[] = {
2921 CreateMockRead(*stream1_reply, 2),
2922 CreateMockRead(*stream2_syn, 3),
2923 CreateMockRead(*stream2_body1, 4),
2924 CreateMockRead(*stream2_body2, 5),
2925 CreateMockRead(*stream2_body3, 6),
2926 CreateMockRead(*stream2_body4, 7),
2927 CreateMockRead(*stream1_body, 8, SYNCHRONOUS),
2928 MockRead(ASYNC, ERR_IO_PENDING, 9), // Force a pause
2931 HttpResponseInfo response;
2932 HttpResponseInfo response2;
2933 std::string expected_push_result("pushed my darling hello my baby");
2934 OrderedSocketData data(reads, arraysize(reads),
2935 writes, arraysize(writes));
2936 RunServerPushTest(&data, &response, &response2, kPushedData);
2938 // Verify the SYN_REPLY.
2939 EXPECT_TRUE(response.headers.get() != NULL);
2940 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2942 // Verify the pushed stream.
2943 EXPECT_TRUE(response2.headers.get() != NULL);
2944 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2947 TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
2948 scoped_ptr<SpdyFrame> stream1_syn(
2949 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2950 scoped_ptr<SpdyFrame> stream1_body(
2951 spdy_util_.ConstructSpdyBodyFrame(1, true));
2952 MockWrite writes[] = {
2953 CreateMockWrite(*stream1_syn, 1),
2956 scoped_ptr<SpdyFrame>
2957 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2958 scoped_ptr<SpdyFrame>
2959 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2963 "http://www.google.com/foo.dat"));
2964 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));
2979 MockRead reads[] = {
2980 CreateMockRead(*stream1_reply, 2),
2981 CreateMockRead(*stream2_syn, 3),
2982 CreateMockRead(*stream2_body1, 4),
2983 CreateMockRead(*stream2_body2, 5),
2984 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2985 CreateMockRead(*stream2_body3, 7),
2986 CreateMockRead(*stream2_body4, 8),
2987 CreateMockRead(*stream1_body.get(), 9, SYNCHRONOUS),
2988 MockRead(ASYNC, ERR_IO_PENDING, 10) // Force a pause.
2991 HttpResponseInfo response;
2992 HttpResponseInfo response2;
2993 OrderedSocketData data(reads, arraysize(reads),
2994 writes, arraysize(writes));
2995 RunServerPushTest(&data, &response, &response2, kPushedData);
2997 // Verify the SYN_REPLY.
2998 EXPECT_TRUE(response.headers.get() != NULL);
2999 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3001 // Verify the pushed stream.
3002 EXPECT_TRUE(response2.headers.get() != NULL);
3003 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
3006 TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
3007 if (spdy_util_.spdy_version() == SPDY4) {
3008 // PUSH_PROMISE with stream id 0 is connection-level error.
3009 // TODO(baranovich): Test session going away.
3010 return;
3013 scoped_ptr<SpdyFrame> stream1_syn(
3014 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3015 scoped_ptr<SpdyFrame> stream1_body(
3016 spdy_util_.ConstructSpdyBodyFrame(1, true));
3017 scoped_ptr<SpdyFrame> stream2_rst(
3018 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
3019 MockWrite writes[] = {
3020 CreateMockWrite(*stream1_syn, 1),
3021 CreateMockWrite(*stream2_rst, 4),
3024 scoped_ptr<SpdyFrame>
3025 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3026 scoped_ptr<SpdyFrame>
3027 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
3031 "http://www.google.com/foo.dat"));
3032 MockRead reads[] = {
3033 CreateMockRead(*stream1_reply, 2),
3034 CreateMockRead(*stream2_syn, 3),
3035 CreateMockRead(*stream1_body, 4),
3036 MockRead(ASYNC, ERR_IO_PENDING, 5) // Force a pause
3039 OrderedSocketData data(reads, arraysize(reads),
3040 writes, arraysize(writes));
3041 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3042 BoundNetLog(), GetParam(), NULL);
3044 helper.RunPreTestSetup();
3045 helper.AddData(&data);
3047 HttpNetworkTransaction* trans = helper.trans();
3049 // Start the transaction with basic parameters.
3050 TestCompletionCallback callback;
3051 int rv = trans->Start(
3052 &CreateGetRequest(), callback.callback(), BoundNetLog());
3053 EXPECT_EQ(ERR_IO_PENDING, rv);
3054 rv = callback.WaitForResult();
3055 EXPECT_EQ(OK, rv);
3057 // Verify that we consumed all test data.
3058 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3059 << data.read_count()
3060 << " Read index: "
3061 << data.read_index();
3062 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3063 << data.write_count()
3064 << " Write index: "
3065 << data.write_index();
3067 // Verify the SYN_REPLY.
3068 HttpResponseInfo response = *trans->GetResponseInfo();
3069 EXPECT_TRUE(response.headers.get() != NULL);
3070 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3073 TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
3074 scoped_ptr<SpdyFrame> stream1_syn(
3075 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3076 scoped_ptr<SpdyFrame> stream1_body(
3077 spdy_util_.ConstructSpdyBodyFrame(1, true));
3078 scoped_ptr<SpdyFrame> stream2_rst(
3079 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM));
3080 MockWrite writes[] = {
3081 CreateMockWrite(*stream1_syn, 1),
3082 CreateMockWrite(*stream2_rst, 4),
3085 scoped_ptr<SpdyFrame>
3086 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3087 scoped_ptr<SpdyFrame>
3088 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
3092 "http://www.google.com/foo.dat"));
3093 MockRead reads[] = {
3094 CreateMockRead(*stream1_reply, 2),
3095 CreateMockRead(*stream2_syn, 3),
3096 CreateMockRead(*stream1_body, 4),
3097 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
3100 OrderedSocketData data(reads, arraysize(reads),
3101 writes, arraysize(writes));
3102 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3103 BoundNetLog(), GetParam(), NULL);
3105 helper.RunPreTestSetup();
3106 helper.AddData(&data);
3108 HttpNetworkTransaction* trans = helper.trans();
3110 // Start the transaction with basic parameters.
3111 TestCompletionCallback callback;
3112 int rv = trans->Start(
3113 &CreateGetRequest(), callback.callback(), BoundNetLog());
3114 EXPECT_EQ(ERR_IO_PENDING, rv);
3115 rv = callback.WaitForResult();
3116 EXPECT_EQ(OK, rv);
3118 // Verify that we consumed all test data.
3119 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3120 << data.read_count()
3121 << " Read index: "
3122 << data.read_index();
3123 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3124 << data.write_count()
3125 << " Write index: "
3126 << data.write_index();
3128 // Verify the SYN_REPLY.
3129 HttpResponseInfo response = *trans->GetResponseInfo();
3130 EXPECT_TRUE(response.headers.get() != NULL);
3131 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3134 TEST_P(SpdyNetworkTransactionTest, ServerPushNoURL) {
3135 scoped_ptr<SpdyFrame> stream1_syn(
3136 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3137 scoped_ptr<SpdyFrame> stream1_body(
3138 spdy_util_.ConstructSpdyBodyFrame(1, true));
3139 scoped_ptr<SpdyFrame> stream2_rst(
3140 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
3141 MockWrite writes[] = {
3142 CreateMockWrite(*stream1_syn, 1),
3143 CreateMockWrite(*stream2_rst, 4),
3146 scoped_ptr<SpdyFrame>
3147 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3148 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";
3152 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
3153 incomplete_headers.Pass(), 2, 1));
3154 MockRead reads[] = {
3155 CreateMockRead(*stream1_reply, 2),
3156 CreateMockRead(*stream2_syn, 3),
3157 CreateMockRead(*stream1_body, 4),
3158 MockRead(ASYNC, ERR_IO_PENDING, 5) // Force a pause
3161 OrderedSocketData data(reads, arraysize(reads),
3162 writes, arraysize(writes));
3163 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3164 BoundNetLog(), GetParam(), NULL);
3166 helper.RunPreTestSetup();
3167 helper.AddData(&data);
3169 HttpNetworkTransaction* trans = helper.trans();
3171 // Start the transaction with basic parameters.
3172 TestCompletionCallback callback;
3173 int rv = trans->Start(
3174 &CreateGetRequest(), callback.callback(), BoundNetLog());
3175 EXPECT_EQ(ERR_IO_PENDING, rv);
3176 rv = callback.WaitForResult();
3177 EXPECT_EQ(OK, rv);
3178 // Verify that we consumed all test data.
3179 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3180 << data.read_count()
3181 << " Read index: "
3182 << data.read_index();
3183 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3184 << data.write_count()
3185 << " Write index: "
3186 << data.write_index();
3188 // Verify the SYN_REPLY.
3189 HttpResponseInfo response = *trans->GetResponseInfo();
3190 EXPECT_TRUE(response.headers.get() != NULL);
3191 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3194 // Verify that various SynReply headers parse correctly through the
3195 // HTTP layer.
3196 TEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) {
3197 struct SynReplyHeadersTests {
3198 int num_headers;
3199 const char* extra_headers[5];
3200 SpdyHeaderBlock expected_headers;
3201 } test_cases[] = {
3202 // This uses a multi-valued cookie header.
3203 { 2,
3204 { "cookie", "val1",
3205 "cookie", "val2", // will get appended separated by NULL
3206 NULL
3209 // This is the minimalist set of headers.
3210 { 0,
3211 { NULL },
3213 // Headers with a comma separated list.
3214 { 1,
3215 { "cookie", "val1,val2",
3216 NULL
3221 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";
3227 test_cases[1].expected_headers["hello"] = "bye";
3228 test_cases[1].expected_headers["status"] = "200";
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";
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";
3241 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3242 scoped_ptr<SpdyFrame> req(
3243 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3244 MockWrite writes[] = { CreateMockWrite(*req) };
3246 scoped_ptr<SpdyFrame> resp(
3247 spdy_util_.ConstructSpdyGetSynReply(test_cases[i].extra_headers,
3248 test_cases[i].num_headers,
3249 1));
3250 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3251 MockRead reads[] = {
3252 CreateMockRead(*resp),
3253 CreateMockRead(*body),
3254 MockRead(ASYNC, 0, 0) // EOF
3257 DelayedSocketData data(1, reads, arraysize(reads),
3258 writes, arraysize(writes));
3259 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3260 BoundNetLog(), GetParam(), NULL);
3261 helper.RunToCompletion(&data);
3262 TransactionHelperResult out = helper.output();
3264 EXPECT_EQ(OK, out.rv);
3265 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3266 EXPECT_EQ("hello!", out.response_data);
3268 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3269 EXPECT_TRUE(headers.get() != NULL);
3270 void* iter = NULL;
3271 std::string name, value;
3272 SpdyHeaderBlock header_block;
3273 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3274 if (header_block[name].empty()) {
3275 header_block[name] = value;
3276 } else {
3277 header_block[name] += '\0';
3278 header_block[name] += value;
3281 EXPECT_EQ(test_cases[i].expected_headers, header_block);
3285 // Verify that various SynReply headers parse vary fields correctly
3286 // through the HTTP layer, and the response matches the request.
3287 TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) {
3288 // Modify the following data to change/add test cases:
3289 struct SynReplyTests {
3290 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.
3297 true,
3298 { 1, 4 },
3299 { { "cookie", "val1,val2",
3300 NULL
3302 { "vary", "cookie",
3303 spdy_util_.GetStatusKey(), "200",
3304 spdy_util_.GetPathKey(), "/index.php",
3305 spdy_util_.GetVersionKey(), "HTTP/1.1",
3306 NULL
3309 }, { // Multiple vary fields.
3310 true,
3311 { 2, 5 },
3312 { { "friend", "barney",
3313 "enemy", "snaggletooth",
3314 NULL
3316 { "vary", "friend",
3317 "vary", "enemy",
3318 spdy_util_.GetStatusKey(), "200",
3319 spdy_util_.GetPathKey(), "/index.php",
3320 spdy_util_.GetVersionKey(), "HTTP/1.1",
3321 NULL
3324 }, { // Test a '*' vary field.
3325 false,
3326 { 1, 4 },
3327 { { "cookie", "val1,val2",
3328 NULL
3330 { "vary", "*",
3331 spdy_util_.GetStatusKey(), "200",
3332 spdy_util_.GetPathKey(), "/index.php",
3333 spdy_util_.GetVersionKey(), "HTTP/1.1",
3334 NULL
3337 }, { // Multiple comma-separated vary fields.
3338 true,
3339 { 2, 4 },
3340 { { "friend", "barney",
3341 "enemy", "snaggletooth",
3342 NULL
3344 { "vary", "friend,enemy",
3345 spdy_util_.GetStatusKey(), "200",
3346 spdy_util_.GetPathKey(), "/index.php",
3347 spdy_util_.GetVersionKey(), "HTTP/1.1",
3348 NULL
3354 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3355 // Construct the request.
3356 scoped_ptr<SpdyFrame> frame_req(
3357 spdy_util_.ConstructSpdyGet(test_cases[i].extra_headers[0],
3358 test_cases[i].num_headers[0],
3359 false, 1, LOWEST, true));
3361 MockWrite writes[] = {
3362 CreateMockWrite(*frame_req),
3365 // Construct the reply.
3366 SpdyHeaderBlock reply_headers;
3367 AppendToHeaderBlock(test_cases[i].extra_headers[1],
3368 test_cases[i].num_headers[1],
3369 &reply_headers);
3370 scoped_ptr<SpdyFrame> frame_reply(
3371 spdy_util_.ConstructSpdyReply(1, reply_headers));
3373 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3374 MockRead reads[] = {
3375 CreateMockRead(*frame_reply),
3376 CreateMockRead(*body),
3377 MockRead(ASYNC, 0, 0) // EOF
3380 // Attach the headers to the request.
3381 int header_count = test_cases[i].num_headers[0];
3383 HttpRequestInfo request = CreateGetRequest();
3384 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);
3390 DelayedSocketData data(1, reads, arraysize(reads),
3391 writes, arraysize(writes));
3392 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
3393 BoundNetLog(), GetParam(), NULL);
3394 helper.RunToCompletion(&data);
3395 TransactionHelperResult out = helper.output();
3397 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;
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;
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");
3425 // Construct the expected header reply string.
3426 std::string expected_reply =
3427 spdy_util_.ConstructSpdyReplyString(reply_headers);
3428 EXPECT_EQ(expected_reply, lines) << i;
3432 // Verify that we don't crash on invalid SynReply responses.
3433 TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) {
3434 struct InvalidSynReplyTests {
3435 int num_headers;
3436 const char* headers[10];
3437 } test_cases[] = {
3438 // SYN_REPLY missing status header
3439 { 4,
3440 { "cookie", "val1",
3441 "cookie", "val2",
3442 spdy_util_.GetPathKey(), "/index.php",
3443 spdy_util_.GetVersionKey(), "HTTP/1.1",
3444 NULL
3447 // SYN_REPLY missing version header
3448 { 2,
3449 { "status", "200",
3450 spdy_util_.GetPathKey(), "/index.php",
3451 NULL
3454 // SYN_REPLY with no headers
3455 { 0, { NULL }, },
3458 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3459 scoped_ptr<SpdyFrame> req(
3460 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3461 scoped_ptr<SpdyFrame> rst(
3462 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
3463 MockWrite writes[] = {
3464 CreateMockWrite(*req),
3465 CreateMockWrite(*rst),
3468 // 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));
3473 MockRead reads[] = {
3474 CreateMockRead(*resp),
3475 MockRead(ASYNC, 0, 0) // EOF
3478 DelayedSocketData data(1, reads, arraysize(reads),
3479 writes, arraysize(writes));
3480 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3481 BoundNetLog(), GetParam(), NULL);
3482 helper.RunToCompletion(&data);
3483 TransactionHelperResult out = helper.output();
3484 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3488 // Verify that we don't crash on some corrupt frames.
3489 // 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.
3491 TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
3492 if (spdy_util_.spdy_version() >= SPDY4) {
3493 return;
3495 // This is the length field that's too short.
3496 scoped_ptr<SpdyFrame> syn_reply_wrong_length(
3497 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3498 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3499 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;
3504 test::SetFrameLength(syn_reply_wrong_length.get(),
3505 wrong_size,
3506 spdy_util_.spdy_version());
3508 struct SynReplyTests {
3509 const SpdyFrame* syn_reply;
3510 } test_cases[] = {
3511 { syn_reply_wrong_length.get(), },
3514 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3515 scoped_ptr<SpdyFrame> req(
3516 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3517 scoped_ptr<SpdyFrame> rst(
3518 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
3519 MockWrite writes[] = {
3520 CreateMockWrite(*req),
3521 CreateMockWrite(*rst),
3524 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3525 MockRead reads[] = {
3526 MockRead(ASYNC, test_cases[i].syn_reply->data(), wrong_size),
3527 CreateMockRead(*body),
3528 MockRead(ASYNC, 0, 0) // EOF
3531 DelayedSocketData data(1, reads, arraysize(reads),
3532 writes, arraysize(writes));
3533 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3534 BoundNetLog(), GetParam(), NULL);
3535 helper.RunToCompletion(&data);
3536 TransactionHelperResult out = helper.output();
3537 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3541 // SPDY4 treats a header decompression failure as a connection-level error.
3542 TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionErrorSpdy4) {
3543 if (spdy_util_.spdy_version() < SPDY4) {
3544 return;
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 =
3551 syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize();
3552 size_t wrong_size = right_size - 4;
3553 test::SetFrameLength(syn_reply_wrong_length.get(),
3554 wrong_size,
3555 spdy_util_.spdy_version());
3557 scoped_ptr<SpdyFrame> req(
3558 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3559 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3560 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3561 MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*goaway)};
3563 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3564 MockRead reads[] = {
3565 MockRead(ASYNC, syn_reply_wrong_length->data(),
3566 syn_reply_wrong_length->size() - 4),
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();
3575 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
3578 TEST_P(SpdyNetworkTransactionTest, GoAwayOnDecompressionFailure) {
3579 if (GetParam().protocol < kProtoSPDY4) {
3580 // Decompression failures are a stream error in SPDY3 and above.
3581 return;
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)};
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)};
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);
3602 TEST_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)};
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)};
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();
3624 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3627 // Test that we shutdown correctly on write errors.
3628 TEST_P(SpdyNetworkTransactionTest, WriteError) {
3629 scoped_ptr<SpdyFrame> req(
3630 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3631 MockWrite writes[] = {
3632 // 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),
3640 MockRead reads[] = {
3641 MockRead(ASYNC, 0, 3) // EOF
3644 DeterministicSocketData data(reads, arraysize(reads),
3645 writes, arraysize(writes));
3647 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3648 BoundNetLog(), GetParam(), NULL);
3649 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());
3657 TransactionHelperResult out = helper.output();
3658 EXPECT_EQ(ERR_FAILED, out.rv);
3661 // Test that partial writes work.
3662 TEST_P(SpdyNetworkTransactionTest, PartialWrite) {
3663 // Chop the SYN_STREAM frame into 5 chunks.
3664 scoped_ptr<SpdyFrame> req(
3665 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3666 const int kChunks = 5;
3667 scoped_ptr<MockWrite[]> writes(ChopWriteFrame(*req.get(), kChunks));
3669 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3670 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3671 MockRead reads[] = {
3672 CreateMockRead(*resp),
3673 CreateMockRead(*body),
3674 MockRead(ASYNC, 0, 0) // EOF
3677 DelayedSocketData data(kChunks, reads, arraysize(reads),
3678 writes.get(), kChunks);
3679 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3680 BoundNetLog(), GetParam(), NULL);
3681 helper.RunToCompletion(&data);
3682 TransactionHelperResult out = helper.output();
3683 EXPECT_EQ(OK, out.rv);
3684 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3685 EXPECT_EQ("hello!", out.response_data);
3688 // In this test, we enable compression, but get a uncompressed SynReply from
3689 // the server. Verify that teardown is all clean.
3690 TEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) {
3691 if (spdy_util_.spdy_version() >= SPDY4) {
3692 // HPACK doesn't use deflate compression.
3693 return;
3695 scoped_ptr<SpdyFrame> compressed(
3696 spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, LOWEST, true));
3697 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3698 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3699 MockWrite writes[] = {CreateMockWrite(*compressed), CreateMockWrite(*goaway)};
3701 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3702 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3703 MockRead reads[] = {
3704 CreateMockRead(*resp),
3707 DelayedSocketData data(1, reads, arraysize(reads),
3708 writes, arraysize(writes));
3709 SpdySessionDependencies* session_deps =
3710 CreateSpdySessionDependencies(GetParam());
3711 session_deps->enable_compression = true;
3712 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3713 BoundNetLog(), GetParam(), session_deps);
3714 helper.RunToCompletion(&data);
3715 TransactionHelperResult out = helper.output();
3716 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
3717 data.Reset();
3720 // Test that the NetLog contains good data for a simple GET request.
3721 TEST_P(SpdyNetworkTransactionTest, NetLog) {
3722 static const char* const kExtraHeaders[] = {
3723 "user-agent", "Chrome",
3725 scoped_ptr<SpdyFrame> req(
3726 spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, false, 1, LOWEST, true));
3727 MockWrite writes[] = { CreateMockWrite(*req) };
3729 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3730 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3731 MockRead reads[] = {
3732 CreateMockRead(*resp),
3733 CreateMockRead(*body),
3734 MockRead(ASYNC, 0, 0) // EOF
3737 CapturingBoundNetLog log;
3739 DelayedSocketData data(1, reads, arraysize(reads),
3740 writes, arraysize(writes));
3741 NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(),
3742 DEFAULT_PRIORITY,
3743 log.bound(), GetParam(), NULL);
3744 helper.RunToCompletion(&data);
3745 TransactionHelperResult out = helper.output();
3746 EXPECT_EQ(OK, out.rv);
3747 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3748 EXPECT_EQ("hello!", out.response_data);
3750 // Check that the NetLog was filled reasonably.
3751 // 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.
3754 net::CapturingNetLog::CapturedEntryList entries;
3755 log.GetEntries(&entries);
3757 EXPECT_LT(0u, entries.size());
3758 int pos = 0;
3759 pos = net::ExpectLogContainsSomewhere(entries, 0,
3760 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3761 net::NetLog::PHASE_BEGIN);
3762 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3763 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3764 net::NetLog::PHASE_END);
3765 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3766 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3767 net::NetLog::PHASE_BEGIN);
3768 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3769 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3770 net::NetLog::PHASE_END);
3771 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3772 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3773 net::NetLog::PHASE_BEGIN);
3774 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3775 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3776 net::NetLog::PHASE_END);
3778 // Check that we logged all the headers correctly
3779 pos = net::ExpectLogContainsSomewhere(
3780 entries, 0,
3781 net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM,
3782 net::NetLog::PHASE_NONE);
3784 base::ListValue* header_list;
3785 ASSERT_TRUE(entries[pos].params.get());
3786 ASSERT_TRUE(entries[pos].params->GetList("headers", &header_list));
3788 std::vector<std::string> expected;
3789 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");
3792 expected.push_back(std::string(spdy_util_.GetMethodKey()) + ": GET");
3793 expected.push_back("user-agent: Chrome");
3794 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");
3798 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;
3808 // 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.
3812 TEST_P(SpdyNetworkTransactionTest, BufferFull) {
3813 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3815 scoped_ptr<SpdyFrame> req(
3816 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3817 MockWrite writes[] = { CreateMockWrite(*req) };
3819 // 2 data frames in a single read.
3820 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] = {
3825 data_frame_1.get(),
3826 data_frame_2.get(),
3828 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));
3832 scoped_ptr<SpdyFrame> last_frame(
3833 framer.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN));
3835 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3836 MockRead reads[] = {
3837 CreateMockRead(*resp),
3838 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
3841 CreateMockRead(*last_frame),
3842 MockRead(ASYNC, 0, 0) // EOF
3845 DelayedSocketData data(1, reads, arraysize(reads),
3846 writes, arraysize(writes));
3848 TestCompletionCallback callback;
3850 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3851 BoundNetLog(), GetParam(), NULL);
3852 helper.RunPreTestSetup();
3853 helper.AddData(&data);
3854 HttpNetworkTransaction* trans = helper.trans();
3855 int rv = trans->Start(
3856 &CreateGetRequest(), callback.callback(), BoundNetLog());
3857 EXPECT_EQ(ERR_IO_PENDING, rv);
3859 TransactionHelperResult out = helper.output();
3860 out.rv = callback.WaitForResult();
3861 EXPECT_EQ(out.rv, OK);
3863 const HttpResponseInfo* response = trans->GetResponseInfo();
3864 EXPECT_TRUE(response->headers.get() != NULL);
3865 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.
3869 // Read Data
3870 TestCompletionCallback read_callback;
3872 std::string content;
3873 do {
3874 // Read small chunks at a time.
3875 const int kSmallReadSize = 3;
3876 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3877 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
3878 if (rv == net::ERR_IO_PENDING) {
3879 data.CompleteRead();
3880 rv = read_callback.WaitForResult();
3882 if (rv > 0) {
3883 content.append(buf->data(), rv);
3884 } else if (rv < 0) {
3885 NOTREACHED();
3887 } while (rv > 0);
3889 out.response_data.swap(content);
3891 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3892 // MockClientSocketFactory) are still alive.
3893 base::RunLoop().RunUntilIdle();
3895 // Verify that we consumed all test data.
3896 helper.VerifyDataConsumed();
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);
3903 // 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.
3906 TEST_P(SpdyNetworkTransactionTest, Buffering) {
3907 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3909 scoped_ptr<SpdyFrame> req(
3910 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3911 MockWrite writes[] = { CreateMockWrite(*req) };
3913 // 4 data frames in a single read.
3914 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] = {
3919 data_frame.get(),
3920 data_frame.get(),
3921 data_frame.get(),
3922 data_frame_fin.get()
3924 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));
3929 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3930 MockRead reads[] = {
3931 CreateMockRead(*resp),
3932 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3933 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
3934 MockRead(ASYNC, 0, 0) // EOF
3937 DelayedSocketData data(1, reads, arraysize(reads),
3938 writes, arraysize(writes));
3940 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3941 BoundNetLog(), GetParam(), NULL);
3942 helper.RunPreTestSetup();
3943 helper.AddData(&data);
3944 HttpNetworkTransaction* trans = helper.trans();
3946 TestCompletionCallback callback;
3947 int rv = trans->Start(
3948 &CreateGetRequest(), callback.callback(), BoundNetLog());
3949 EXPECT_EQ(ERR_IO_PENDING, rv);
3951 TransactionHelperResult out = helper.output();
3952 out.rv = callback.WaitForResult();
3953 EXPECT_EQ(out.rv, OK);
3955 const HttpResponseInfo* response = trans->GetResponseInfo();
3956 EXPECT_TRUE(response->headers.get() != NULL);
3957 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.
3961 // Read Data
3962 TestCompletionCallback read_callback;
3964 std::string content;
3965 int reads_completed = 0;
3966 do {
3967 // Read small chunks at a time.
3968 const int kSmallReadSize = 14;
3969 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3970 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
3971 if (rv == net::ERR_IO_PENDING) {
3972 data.CompleteRead();
3973 rv = read_callback.WaitForResult();
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;
3981 reads_completed++;
3982 } while (rv > 0);
3984 EXPECT_EQ(3, reads_completed); // Reads are: 14 bytes, 14 bytes, 0 bytes.
3986 out.response_data.swap(content);
3988 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3989 // MockClientSocketFactory) are still alive.
3990 base::RunLoop().RunUntilIdle();
3992 // Verify that we consumed all test data.
3993 helper.VerifyDataConsumed();
3995 EXPECT_EQ(OK, out.rv);
3996 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3997 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
4000 // Verify the case where we buffer data but read it after it has been buffered.
4001 TEST_P(SpdyNetworkTransactionTest, BufferedAll) {
4002 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4004 scoped_ptr<SpdyFrame> req(
4005 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4006 MockWrite writes[] = { CreateMockWrite(*req) };
4008 // 5 data frames in a single read.
4009 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4010 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));
4014 const SpdyFrame* frames[5] = {reply.get(), data_frame.get(), data_frame.get(),
4015 data_frame.get(), data_frame_fin.get()};
4016 char combined_frames[200];
4017 int combined_frames_len =
4018 CombineFrames(frames, arraysize(frames),
4019 combined_frames, arraysize(combined_frames));
4021 MockRead reads[] = {
4022 MockRead(ASYNC, combined_frames, combined_frames_len),
4023 MockRead(ASYNC, 0, 0) // EOF
4026 DelayedSocketData data(1, reads, arraysize(reads),
4027 writes, arraysize(writes));
4029 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4030 BoundNetLog(), GetParam(), NULL);
4031 helper.RunPreTestSetup();
4032 helper.AddData(&data);
4033 HttpNetworkTransaction* trans = helper.trans();
4035 TestCompletionCallback callback;
4036 int rv = trans->Start(
4037 &CreateGetRequest(), callback.callback(), BoundNetLog());
4038 EXPECT_EQ(ERR_IO_PENDING, rv);
4040 TransactionHelperResult out = helper.output();
4041 out.rv = callback.WaitForResult();
4042 EXPECT_EQ(out.rv, OK);
4044 const HttpResponseInfo* response = trans->GetResponseInfo();
4045 EXPECT_TRUE(response->headers.get() != NULL);
4046 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.
4050 // Read Data
4051 TestCompletionCallback read_callback;
4053 std::string content;
4054 int reads_completed = 0;
4055 do {
4056 // Read small chunks at a time.
4057 const int kSmallReadSize = 14;
4058 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4059 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
4060 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;
4066 reads_completed++;
4067 } while (rv > 0);
4069 EXPECT_EQ(3, reads_completed);
4071 out.response_data.swap(content);
4073 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4074 // MockClientSocketFactory) are still alive.
4075 base::RunLoop().RunUntilIdle();
4077 // Verify that we consumed all test data.
4078 helper.VerifyDataConsumed();
4080 EXPECT_EQ(OK, out.rv);
4081 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4082 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
4085 // Verify the case where we buffer data and close the connection.
4086 TEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
4087 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4089 scoped_ptr<SpdyFrame> req(
4090 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4091 MockWrite writes[] = { CreateMockWrite(*req) };
4093 // All data frames in a single read.
4094 // NOTE: We don't FIN the stream.
4095 scoped_ptr<SpdyFrame> data_frame(
4096 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4097 const SpdyFrame* data_frames[4] = {
4098 data_frame.get(),
4099 data_frame.get(),
4100 data_frame.get(),
4101 data_frame.get()
4103 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));
4107 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4108 MockRead reads[] = {
4109 CreateMockRead(*resp),
4110 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait
4111 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
4112 MockRead(ASYNC, 0, 0) // EOF
4115 DelayedSocketData data(1, reads, arraysize(reads),
4116 writes, arraysize(writes));
4118 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4119 BoundNetLog(), GetParam(), NULL);
4120 helper.RunPreTestSetup();
4121 helper.AddData(&data);
4122 HttpNetworkTransaction* trans = helper.trans();
4124 TestCompletionCallback callback;
4126 int rv = trans->Start(
4127 &CreateGetRequest(), callback.callback(), BoundNetLog());
4128 EXPECT_EQ(ERR_IO_PENDING, rv);
4130 TransactionHelperResult out = helper.output();
4131 out.rv = callback.WaitForResult();
4132 EXPECT_EQ(out.rv, OK);
4134 const HttpResponseInfo* response = trans->GetResponseInfo();
4135 EXPECT_TRUE(response->headers.get() != NULL);
4136 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.
4140 // Read Data
4141 TestCompletionCallback read_callback;
4143 std::string content;
4144 int reads_completed = 0;
4145 do {
4146 // Read small chunks at a time.
4147 const int kSmallReadSize = 14;
4148 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4149 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
4150 if (rv == net::ERR_IO_PENDING) {
4151 data.CompleteRead();
4152 rv = read_callback.WaitForResult();
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;
4161 reads_completed++;
4162 } while (rv > 0);
4164 EXPECT_EQ(0, reads_completed);
4166 out.response_data.swap(content);
4168 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4169 // MockClientSocketFactory) are still alive.
4170 base::RunLoop().RunUntilIdle();
4172 // Verify that we consumed all test data.
4173 helper.VerifyDataConsumed();
4176 // Verify the case where we buffer data and cancel the transaction.
4177 TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) {
4178 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4180 scoped_ptr<SpdyFrame> req(
4181 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4182 scoped_ptr<SpdyFrame> rst(
4183 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
4184 MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*rst)};
4186 // NOTE: We don't FIN the stream.
4187 scoped_ptr<SpdyFrame> data_frame(
4188 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4190 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4191 MockRead reads[] = {
4192 CreateMockRead(*resp),
4193 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait
4194 CreateMockRead(*data_frame),
4195 MockRead(ASYNC, 0, 0) // EOF
4198 DelayedSocketData data(1, reads, arraysize(reads),
4199 writes, arraysize(writes));
4201 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4202 BoundNetLog(), GetParam(), NULL);
4203 helper.RunPreTestSetup();
4204 helper.AddData(&data);
4205 HttpNetworkTransaction* trans = helper.trans();
4206 TestCompletionCallback callback;
4208 int rv = trans->Start(
4209 &CreateGetRequest(), callback.callback(), BoundNetLog());
4210 EXPECT_EQ(ERR_IO_PENDING, rv);
4212 TransactionHelperResult out = helper.output();
4213 out.rv = callback.WaitForResult();
4214 EXPECT_EQ(out.rv, OK);
4216 const HttpResponseInfo* response = trans->GetResponseInfo();
4217 EXPECT_TRUE(response->headers.get() != NULL);
4218 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.
4222 // Read Data
4223 TestCompletionCallback read_callback;
4225 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;
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();
4236 // Flush the MessageLoop; this will cause the buffered IO task
4237 // to run for the final time.
4238 base::RunLoop().RunUntilIdle();
4240 // Verify that we consumed all test data.
4241 helper.VerifyDataConsumed();
4244 // Test that if the server requests persistence of settings, that we save
4245 // the settings in the HttpServerProperties.
4246 TEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
4247 if (spdy_util_.spdy_version() >= SPDY4) {
4248 // SPDY4 doesn't support settings persistence.
4249 return;
4251 static const SpdyHeaderInfo kSynReplyInfo = {
4252 SYN_REPLY, // Syn Reply
4253 1, // Stream ID
4254 0, // Associated Stream ID
4255 ConvertRequestPriorityToSpdyPriority(
4256 LOWEST, spdy_util_.spdy_version()),
4257 kSpdyCredentialSlotUnused,
4258 CONTROL_FLAG_NONE, // Control Flags
4259 false, // Compressed
4260 RST_STREAM_INVALID, // Status
4261 NULL, // Data
4262 0, // Data Length
4263 DATA_FLAG_NONE // Data Flags
4266 BoundNetLog net_log;
4267 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4268 net_log, GetParam(), NULL);
4269 helper.RunPreTestSetup();
4271 // Verify that no settings exist initially.
4272 HostPortPair host_port_pair("www.google.com", helper.port());
4273 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4274 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4275 host_port_pair).empty());
4277 // Construct the request.
4278 scoped_ptr<SpdyFrame> req(
4279 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4280 MockWrite writes[] = { CreateMockWrite(*req) };
4282 // Construct the reply.
4283 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4284 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4285 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
4286 scoped_ptr<SpdyFrame> reply(
4287 spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
4289 const SpdySettingsIds kSampleId1 = SETTINGS_UPLOAD_BANDWIDTH;
4290 unsigned int kSampleValue1 = 0x0a0a0a0a;
4291 const SpdySettingsIds kSampleId2 = SETTINGS_DOWNLOAD_BANDWIDTH;
4292 unsigned int kSampleValue2 = 0x0b0b0b0b;
4293 const SpdySettingsIds kSampleId3 = SETTINGS_ROUND_TRIP_TIME;
4294 unsigned int kSampleValue3 = 0x0c0c0c0c;
4295 scoped_ptr<SpdyFrame> settings_frame;
4297 // Construct the SETTINGS frame.
4298 SettingsMap settings;
4299 // First add a persisted setting.
4300 settings[kSampleId1] =
4301 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue1);
4302 // Next add a non-persisted setting.
4303 settings[kSampleId2] =
4304 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kSampleValue2);
4305 // Next add another persisted setting.
4306 settings[kSampleId3] =
4307 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue3);
4308 settings_frame.reset(spdy_util_.ConstructSpdySettings(settings));
4311 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4312 MockRead reads[] = {
4313 CreateMockRead(*reply),
4314 CreateMockRead(*body),
4315 CreateMockRead(*settings_frame),
4316 MockRead(ASYNC, 0, 0) // EOF
4319 DelayedSocketData data(1, reads, arraysize(reads),
4320 writes, arraysize(writes));
4321 helper.AddData(&data);
4322 helper.RunDefaultTest();
4323 helper.VerifyDataConsumed();
4324 TransactionHelperResult out = helper.output();
4325 EXPECT_EQ(OK, out.rv);
4326 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4327 EXPECT_EQ("hello!", out.response_data);
4330 // Verify we had two persisted settings.
4331 const SettingsMap& settings_map =
4332 spdy_session_pool->http_server_properties()->GetSpdySettings(
4333 host_port_pair);
4334 ASSERT_EQ(2u, settings_map.size());
4336 // Verify the first persisted setting.
4337 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);
4343 // Verify the second persisted setting.
4344 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);
4352 // Test that when there are settings saved that they are sent back to the
4353 // server upon session establishment.
4354 TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) {
4355 if (spdy_util_.spdy_version() >= SPDY4) {
4356 // SPDY4 doesn't support settings persistence.
4357 return;
4359 static const SpdyHeaderInfo kSynReplyInfo = {
4360 SYN_REPLY, // Syn Reply
4361 1, // Stream ID
4362 0, // Associated Stream ID
4363 ConvertRequestPriorityToSpdyPriority(
4364 LOWEST, spdy_util_.spdy_version()),
4365 kSpdyCredentialSlotUnused,
4366 CONTROL_FLAG_NONE, // Control Flags
4367 false, // Compressed
4368 RST_STREAM_INVALID, // Status
4369 NULL, // Data
4370 0, // Data Length
4371 DATA_FLAG_NONE // Data Flags
4374 BoundNetLog net_log;
4375 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4376 net_log, GetParam(), NULL);
4377 helper.RunPreTestSetup();
4379 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4381 SpdySessionPoolPeer pool_peer(spdy_session_pool);
4382 pool_peer.SetEnableSendingInitialData(true);
4384 // Verify that no settings exist initially.
4385 HostPortPair host_port_pair("www.google.com", helper.port());
4386 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4387 host_port_pair).empty());
4389 const SpdySettingsIds kSampleId1 = SETTINGS_MAX_CONCURRENT_STREAMS;
4390 unsigned int kSampleValue1 = 0x0a0a0a0a;
4391 const SpdySettingsIds kSampleId2 = SETTINGS_INITIAL_WINDOW_SIZE;
4392 unsigned int kSampleValue2 = 0x0c0c0c0c;
4394 // 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);
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);
4408 EXPECT_EQ(2u, spdy_session_pool->http_server_properties()->GetSpdySettings(
4409 host_port_pair).size());
4411 // 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));
4418 // Construct the initial window update.
4419 scoped_ptr<SpdyFrame> initial_window_update(
4420 spdy_util_.ConstructSpdyWindowUpdate(
4421 kSessionFlowControlStreamId,
4422 kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
4424 // Construct the persisted SETTINGS frame.
4425 const SettingsMap& settings =
4426 spdy_session_pool->http_server_properties()->GetSpdySettings(
4427 host_port_pair);
4428 scoped_ptr<SpdyFrame> settings_frame(
4429 spdy_util_.ConstructSpdySettings(settings));
4431 // Construct the request.
4432 scoped_ptr<SpdyFrame> req(
4433 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4435 std::vector<MockWrite> writes;
4436 if (GetParam().protocol == kProtoSPDY4) {
4437 writes.push_back(
4438 MockWrite(ASYNC,
4439 kHttp2ConnectionHeaderPrefix,
4440 kHttp2ConnectionHeaderPrefixSize));
4442 writes.push_back(CreateMockWrite(*initial_settings_frame));
4443 if (GetParam().protocol >= kProtoSPDY31) {
4444 writes.push_back(CreateMockWrite(*initial_window_update));
4446 writes.push_back(CreateMockWrite(*settings_frame));
4447 writes.push_back(CreateMockWrite(*req));
4449 // Construct the reply.
4450 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4451 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4452 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
4453 scoped_ptr<SpdyFrame> reply(
4454 spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
4456 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4457 MockRead reads[] = {
4458 CreateMockRead(*reply),
4459 CreateMockRead(*body),
4460 MockRead(ASYNC, 0, 0) // EOF
4463 DelayedSocketData data(2, reads, arraysize(reads),
4464 vector_as_array(&writes), writes.size());
4465 helper.AddData(&data);
4466 helper.RunDefaultTest();
4467 helper.VerifyDataConsumed();
4468 TransactionHelperResult out = helper.output();
4469 EXPECT_EQ(OK, out.rv);
4470 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4471 EXPECT_EQ("hello!", out.response_data);
4474 // Verify we had two persisted settings.
4475 const SettingsMap& settings_map =
4476 spdy_session_pool->http_server_properties()->GetSpdySettings(
4477 host_port_pair);
4478 ASSERT_EQ(2u, settings_map.size());
4480 // Verify the first persisted setting.
4481 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);
4487 // Verify the second persisted setting.
4488 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);
4496 TEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
4497 scoped_ptr<SpdyFrame> req(
4498 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4499 MockWrite writes[] = { CreateMockWrite(*req) };
4501 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway());
4502 MockRead reads[] = {
4503 CreateMockRead(*go_away),
4506 DelayedSocketData data(1, reads, arraysize(reads),
4507 writes, arraysize(writes));
4508 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4509 BoundNetLog(), GetParam(), NULL);
4510 helper.AddData(&data);
4511 helper.RunToCompletion(&data);
4512 TransactionHelperResult out = helper.output();
4513 EXPECT_EQ(ERR_ABORTED, out.rv);
4516 TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) {
4517 scoped_ptr<SpdyFrame> req(
4518 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4519 MockWrite writes[] = { CreateMockWrite(*req) };
4521 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4522 MockRead reads[] = {
4523 CreateMockRead(*resp),
4524 MockRead(SYNCHRONOUS, 0, 0) // EOF
4527 DelayedSocketData data(1, reads, arraysize(reads),
4528 writes, arraysize(writes));
4529 BoundNetLog log;
4530 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4531 log, GetParam(), NULL);
4532 helper.RunPreTestSetup();
4533 helper.AddData(&data);
4534 HttpNetworkTransaction* trans = helper.trans();
4536 TestCompletionCallback callback;
4537 TransactionHelperResult out;
4538 out.rv = trans->Start(&CreateGetRequest(), callback.callback(), log);
4540 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4541 out.rv = callback.WaitForResult();
4542 EXPECT_EQ(out.rv, OK);
4544 const HttpResponseInfo* response = trans->GetResponseInfo();
4545 EXPECT_TRUE(response->headers.get() != NULL);
4546 EXPECT_TRUE(response->was_fetched_via_spdy);
4547 out.rv = ReadTransaction(trans, &out.response_data);
4548 EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv);
4550 // Verify that we consumed all test data.
4551 helper.VerifyDataConsumed();
4554 // Test to make sure we can correctly connect through a proxy.
4555 TEST_P(SpdyNetworkTransactionTest, ProxyConnect) {
4556 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4557 BoundNetLog(), GetParam(), NULL);
4558 helper.session_deps().reset(CreateSpdySessionDependencies(
4559 GetParam(),
4560 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
4561 helper.SetSession(make_scoped_refptr(
4562 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
4563 helper.RunPreTestSetup();
4564 HttpNetworkTransaction* trans = helper.trans();
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"};
4573 scoped_ptr<SpdyFrame> req(
4574 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4575 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4576 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4578 MockWrite writes_SPDYNPN[] = {
4579 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4580 CreateMockWrite(*req, 2),
4582 MockRead reads_SPDYNPN[] = {
4583 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4584 CreateMockRead(*resp, 3),
4585 CreateMockRead(*body.get(), 4),
4586 MockRead(ASYNC, 0, 0, 5),
4589 MockWrite writes_SPDYSSL[] = {
4590 MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0),
4591 CreateMockWrite(*req, 2),
4593 MockRead reads_SPDYSSL[] = {
4594 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4595 CreateMockRead(*resp, 3),
4596 CreateMockRead(*body.get(), 4),
4597 MockRead(ASYNC, 0, 0, 5),
4600 MockWrite writes_SPDYNOSSL[] = {
4601 CreateMockWrite(*req, 0),
4604 MockRead reads_SPDYNOSSL[] = {
4605 CreateMockRead(*resp, 1),
4606 CreateMockRead(*body.get(), 2),
4607 MockRead(ASYNC, 0, 0, 3),
4610 scoped_ptr<OrderedSocketData> data;
4611 switch(GetParam().ssl_type) {
4612 case SPDYNOSSL:
4613 data.reset(new OrderedSocketData(reads_SPDYNOSSL,
4614 arraysize(reads_SPDYNOSSL),
4615 writes_SPDYNOSSL,
4616 arraysize(writes_SPDYNOSSL)));
4617 break;
4618 case SPDYSSL:
4619 data.reset(new OrderedSocketData(reads_SPDYSSL,
4620 arraysize(reads_SPDYSSL),
4621 writes_SPDYSSL,
4622 arraysize(writes_SPDYSSL)));
4623 break;
4624 case SPDYNPN:
4625 data.reset(new OrderedSocketData(reads_SPDYNPN,
4626 arraysize(reads_SPDYNPN),
4627 writes_SPDYNPN,
4628 arraysize(writes_SPDYNPN)));
4629 break;
4630 default:
4631 NOTREACHED();
4634 helper.AddData(data.get());
4635 TestCompletionCallback callback;
4637 int rv = trans->Start(
4638 &CreateGetRequest(), callback.callback(), BoundNetLog());
4639 EXPECT_EQ(ERR_IO_PENDING, rv);
4641 rv = callback.WaitForResult();
4642 EXPECT_EQ(0, rv);
4644 // Verify the SYN_REPLY.
4645 HttpResponseInfo response = *trans->GetResponseInfo();
4646 EXPECT_TRUE(response.headers.get() != NULL);
4647 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
4649 std::string response_data;
4650 ASSERT_EQ(OK, ReadTransaction(trans, &response_data));
4651 EXPECT_EQ("hello!", response_data);
4652 helper.VerifyDataConsumed();
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
4658 TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
4659 // When setting up the first transaction, we store the SpdySessionPool so that
4660 // we can use the same pool in the second transaction.
4661 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4662 BoundNetLog(), GetParam(), NULL);
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".
4668 helper.session_deps().reset(CreateSpdySessionDependencies(
4669 GetParam(),
4670 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
4671 helper.SetSession(make_scoped_refptr(
4672 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
4674 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4675 helper.RunPreTestSetup();
4677 // Construct and send a simple GET request.
4678 scoped_ptr<SpdyFrame> req(
4679 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4680 MockWrite writes[] = {
4681 CreateMockWrite(*req, 1),
4684 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4685 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4686 MockRead reads[] = {
4687 CreateMockRead(*resp, 2),
4688 CreateMockRead(*body, 3),
4689 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause
4690 MockRead(ASYNC, 0, 5) // EOF
4692 OrderedSocketData data(reads, arraysize(reads),
4693 writes, arraysize(writes));
4694 helper.AddData(&data);
4695 HttpNetworkTransaction* trans = helper.trans();
4697 TestCompletionCallback callback;
4698 TransactionHelperResult out;
4699 out.rv = trans->Start(
4700 &CreateGetRequest(), callback.callback(), BoundNetLog());
4702 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4703 out.rv = callback.WaitForResult();
4704 EXPECT_EQ(out.rv, OK);
4706 const HttpResponseInfo* response = trans->GetResponseInfo();
4707 EXPECT_TRUE(response->headers.get() != NULL);
4708 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);
4715 // Check that the SpdySession is still in the SpdySessionPool.
4716 HostPortPair host_port_pair("www.google.com", helper.port());
4717 SpdySessionKey session_pool_key_direct(
4718 host_port_pair, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
4719 EXPECT_TRUE(HasSpdySession(spdy_session_pool, session_pool_key_direct));
4720 SpdySessionKey session_pool_key_proxy(
4721 host_port_pair,
4722 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP),
4723 PRIVACY_MODE_DISABLED);
4724 EXPECT_FALSE(HasSpdySession(spdy_session_pool, session_pool_key_proxy));
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"};
4734 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyGet(
4735 "http://www.google.com/foo.dat", false, 1, LOWEST));
4736 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4737 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
4739 MockWrite writes_SPDYNPN[] = {
4740 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4741 CreateMockWrite(*req2, 2),
4743 MockRead reads_SPDYNPN[] = {
4744 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4745 CreateMockRead(*resp2, 3),
4746 CreateMockRead(*body2, 4),
4747 MockRead(ASYNC, 0, 5) // EOF
4750 MockWrite writes_SPDYNOSSL[] = {
4751 CreateMockWrite(*req2, 0),
4753 MockRead reads_SPDYNOSSL[] = {
4754 CreateMockRead(*resp2, 1),
4755 CreateMockRead(*body2, 2),
4756 MockRead(ASYNC, 0, 3) // EOF
4759 MockWrite writes_SPDYSSL[] = {
4760 MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0),
4761 CreateMockWrite(*req2, 2),
4763 MockRead reads_SPDYSSL[] = {
4764 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4765 CreateMockRead(*resp2, 3),
4766 CreateMockRead(*body2, 4),
4767 MockRead(ASYNC, 0, 0, 5),
4770 scoped_ptr<OrderedSocketData> data_proxy;
4771 switch(GetParam().ssl_type) {
4772 case SPDYNPN:
4773 data_proxy.reset(new OrderedSocketData(reads_SPDYNPN,
4774 arraysize(reads_SPDYNPN),
4775 writes_SPDYNPN,
4776 arraysize(writes_SPDYNPN)));
4777 break;
4778 case SPDYNOSSL:
4779 data_proxy.reset(new OrderedSocketData(reads_SPDYNOSSL,
4780 arraysize(reads_SPDYNOSSL),
4781 writes_SPDYNOSSL,
4782 arraysize(writes_SPDYNOSSL)));
4783 break;
4784 case SPDYSSL:
4785 data_proxy.reset(new OrderedSocketData(reads_SPDYSSL,
4786 arraysize(reads_SPDYSSL),
4787 writes_SPDYSSL,
4788 arraysize(writes_SPDYSSL)));
4789 break;
4790 default:
4791 NOTREACHED();
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;
4799 scoped_ptr<SpdySessionDependencies> ssd_proxy(
4800 CreateSpdySessionDependencies(GetParam()));
4801 // Ensure that this transaction uses the same SpdySessionPool.
4802 scoped_refptr<HttpNetworkSession> session_proxy(
4803 SpdySessionDependencies::SpdyCreateSession(ssd_proxy.get()));
4804 NormalSpdyTransactionHelper helper_proxy(request_proxy, DEFAULT_PRIORITY,
4805 BoundNetLog(), GetParam(), NULL);
4806 HttpNetworkSessionPeer session_peer(session_proxy);
4807 scoped_ptr<net::ProxyService> proxy_service(
4808 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
4809 session_peer.SetProxyService(proxy_service.get());
4810 helper_proxy.session_deps().swap(ssd_proxy);
4811 helper_proxy.SetSession(session_proxy);
4812 helper_proxy.RunPreTestSetup();
4813 helper_proxy.AddData(data_proxy.get());
4815 HttpNetworkTransaction* trans_proxy = helper_proxy.trans();
4816 TestCompletionCallback callback_proxy;
4817 int rv = trans_proxy->Start(
4818 &request_proxy, callback_proxy.callback(), BoundNetLog());
4819 EXPECT_EQ(ERR_IO_PENDING, rv);
4820 rv = callback_proxy.WaitForResult();
4821 EXPECT_EQ(0, rv);
4823 HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo();
4824 EXPECT_TRUE(response_proxy.headers.get() != NULL);
4825 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy.headers->GetStatusLine());
4827 std::string response_data;
4828 ASSERT_EQ(OK, ReadTransaction(trans_proxy, &response_data));
4829 EXPECT_EQ("hello!", response_data);
4831 data.CompleteRead();
4832 helper_proxy.VerifyDataConsumed();
4835 // 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.
4839 TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
4840 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4841 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4842 MockRead reads[] = {
4843 CreateMockRead(*resp),
4844 CreateMockRead(*body),
4845 MockRead(ASYNC, ERR_IO_PENDING),
4846 MockRead(ASYNC, ERR_CONNECTION_RESET),
4849 MockRead reads2[] = {
4850 CreateMockRead(*resp),
4851 CreateMockRead(*body),
4852 MockRead(ASYNC, 0, 0) // EOF
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
4864 for (int variant = VARIANT_RST_DURING_SEND_COMPLETION;
4865 variant <= VARIANT_RST_DURING_READ_COMPLETION;
4866 ++variant) {
4867 DelayedSocketData data1(1, reads, arraysize(reads), NULL, 0);
4869 DelayedSocketData data2(1, reads2, arraysize(reads2), NULL, 0);
4871 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4872 BoundNetLog(), GetParam(), NULL);
4873 helper.AddData(&data1);
4874 helper.AddData(&data2);
4875 helper.RunPreTestSetup();
4877 for (int i = 0; i < 2; ++i) {
4878 scoped_ptr<HttpNetworkTransaction> trans(
4879 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
4881 TestCompletionCallback callback;
4882 int rv = trans->Start(
4883 &helper.request(), callback.callback(), BoundNetLog());
4884 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.
4890 base::RunLoop().RunUntilIdle();
4893 // Now schedule the ERR_CONNECTION_RESET.
4894 EXPECT_EQ(3u, data1.read_index());
4895 data1.CompleteRead();
4896 EXPECT_EQ(4u, data1.read_index());
4898 rv = callback.WaitForResult();
4899 EXPECT_EQ(OK, rv);
4901 const HttpResponseInfo* response = trans->GetResponseInfo();
4902 ASSERT_TRUE(response != NULL);
4903 EXPECT_TRUE(response->headers.get() != NULL);
4904 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);
4912 helper.VerifyDataConsumed();
4916 // Test that turning SPDY on and off works properly.
4917 TEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) {
4918 HttpStreamFactory::set_spdy_enabled(true);
4919 scoped_ptr<SpdyFrame> req(
4920 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4921 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
4923 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4924 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4925 MockRead spdy_reads[] = {
4926 CreateMockRead(*resp),
4927 CreateMockRead(*body),
4928 MockRead(ASYNC, 0, 0) // EOF
4931 DelayedSocketData data(1, spdy_reads, arraysize(spdy_reads),
4932 spdy_writes, arraysize(spdy_writes));
4933 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4934 BoundNetLog(), GetParam(), NULL);
4935 helper.RunToCompletion(&data);
4936 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);
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"),
4945 MockRead(SYNCHRONOUS, OK),
4947 DelayedSocketData data2(1, http_reads, arraysize(http_reads), NULL, 0);
4948 NormalSpdyTransactionHelper helper2(CreateGetRequest(), DEFAULT_PRIORITY,
4949 BoundNetLog(), GetParam(), NULL);
4950 helper2.SetSpdyDisabled();
4951 helper2.RunToCompletion(&data2);
4952 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);
4957 net::HttpStreamFactory::set_spdy_enabled(true);
4960 // Tests that Basic authentication works over SPDY
4961 TEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) {
4962 net::HttpStreamFactory::set_spdy_enabled(true);
4964 // The first request will be a bare GET, the second request will be a
4965 // GET with an Authorization header.
4966 scoped_ptr<SpdyFrame> req_get(
4967 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4968 const char* const kExtraAuthorizationHeaders[] = {
4969 "authorization", "Basic Zm9vOmJhcg=="
4971 scoped_ptr<SpdyFrame> req_get_authorization(
4972 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
4973 arraysize(kExtraAuthorizationHeaders) / 2,
4974 false, 3, LOWEST, true));
4975 MockWrite spdy_writes[] = {
4976 CreateMockWrite(*req_get, 1),
4977 CreateMockWrite(*req_get_authorization, 4),
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[] = {
4984 "www-authenticate",
4985 "Basic realm=\"MyRealm\""
4987 scoped_ptr<SpdyFrame> resp_authentication(
4988 spdy_util_.ConstructSpdySynReplyError(
4989 "401 Authentication Required",
4990 kExtraAuthenticationHeaders,
4991 arraysize(kExtraAuthenticationHeaders) / 2,
4992 1));
4993 scoped_ptr<SpdyFrame> body_authentication(
4994 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));
4998 MockRead spdy_reads[] = {
4999 CreateMockRead(*resp_authentication, 2),
5000 CreateMockRead(*body_authentication, 3),
5001 CreateMockRead(*resp_data, 5),
5002 CreateMockRead(*body_data, 6),
5003 MockRead(ASYNC, 0, 7),
5006 OrderedSocketData data(spdy_reads, arraysize(spdy_reads),
5007 spdy_writes, arraysize(spdy_writes));
5008 HttpRequestInfo request(CreateGetRequest());
5009 BoundNetLog net_log;
5010 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5011 net_log, GetParam(), NULL);
5013 helper.RunPreTestSetup();
5014 helper.AddData(&data);
5015 HttpNetworkTransaction* trans = helper.trans();
5016 TestCompletionCallback callback;
5017 const int rv_start = trans->Start(&request, callback.callback(), net_log);
5018 EXPECT_EQ(ERR_IO_PENDING, rv_start);
5019 const int rv_start_complete = callback.WaitForResult();
5020 EXPECT_EQ(OK, rv_start_complete);
5022 // Make sure the response has an auth challenge.
5023 const HttpResponseInfo* const response_start = trans->GetResponseInfo();
5024 ASSERT_TRUE(response_start != NULL);
5025 ASSERT_TRUE(response_start->headers.get() != NULL);
5026 EXPECT_EQ(401, response_start->headers->response_code());
5027 EXPECT_TRUE(response_start->was_fetched_via_spdy);
5028 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);
5034 // Restart with a username/password.
5035 AuthCredentials credentials(base::ASCIIToUTF16("foo"),
5036 base::ASCIIToUTF16("bar"));
5037 TestCompletionCallback callback_restart;
5038 const int rv_restart = trans->RestartWithAuth(
5039 credentials, callback_restart.callback());
5040 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);
5047 ASSERT_TRUE(response_restart->headers.get() != NULL);
5048 EXPECT_EQ(200, response_restart->headers->response_code());
5049 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
5052 TEST_P(SpdyNetworkTransactionTest, ServerPushWithHeaders) {
5053 scoped_ptr<SpdyFrame> stream1_syn(
5054 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5055 scoped_ptr<SpdyFrame> stream1_body(
5056 spdy_util_.ConstructSpdyBodyFrame(1, true));
5057 MockWrite writes[] = {
5058 CreateMockWrite(*stream1_syn, 1),
5061 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5062 spdy_util_.AddUrlToHeaderBlock(
5063 "http://www.google.com/foo.dat", initial_headers.get());
5064 scoped_ptr<SpdyFrame> stream2_syn(
5065 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
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";
5071 scoped_ptr<SpdyFrame> stream2_headers(
5072 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5073 false,
5075 LOWEST,
5076 HEADERS,
5077 CONTROL_FLAG_NONE,
5078 0));
5080 scoped_ptr<SpdyFrame>
5081 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5082 const char kPushedData[] = "pushed";
5083 scoped_ptr<SpdyFrame> stream2_body(
5084 spdy_util_.ConstructSpdyBodyFrame(
5085 2, kPushedData, strlen(kPushedData), true));
5086 MockRead reads[] = {
5087 CreateMockRead(*stream1_reply, 2),
5088 CreateMockRead(*stream2_syn, 3),
5089 CreateMockRead(*stream2_headers, 4),
5090 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
5091 CreateMockRead(*stream2_body, 5),
5092 MockRead(ASYNC, ERR_IO_PENDING, 7), // Force a pause
5095 HttpResponseInfo response;
5096 HttpResponseInfo response2;
5097 std::string expected_push_result("pushed");
5098 OrderedSocketData data(reads, arraysize(reads),
5099 writes, arraysize(writes));
5100 RunServerPushTest(&data,
5101 &response,
5102 &response2,
5103 expected_push_result);
5105 // Verify the SYN_REPLY.
5106 EXPECT_TRUE(response.headers.get() != NULL);
5107 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5109 // Verify the pushed stream.
5110 EXPECT_TRUE(response2.headers.get() != NULL);
5111 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5114 TEST_P(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
5115 // We push a stream and attempt to claim it before the headers come down.
5116 scoped_ptr<SpdyFrame> stream1_syn(
5117 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5118 scoped_ptr<SpdyFrame> stream1_body(
5119 spdy_util_.ConstructSpdyBodyFrame(1, true));
5120 MockWrite writes[] = {
5121 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5124 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5125 spdy_util_.AddUrlToHeaderBlock(
5126 "http://www.google.com/foo.dat", initial_headers.get());
5127 scoped_ptr<SpdyFrame> stream2_syn(
5128 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
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";
5134 scoped_ptr<SpdyFrame> stream2_headers(
5135 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5136 false,
5138 LOWEST,
5139 HEADERS,
5140 CONTROL_FLAG_NONE,
5141 0));
5143 scoped_ptr<SpdyFrame>
5144 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5145 const char kPushedData[] = "pushed";
5146 scoped_ptr<SpdyFrame> stream2_body(
5147 spdy_util_.ConstructSpdyBodyFrame(
5148 2, kPushedData, strlen(kPushedData), true));
5149 MockRead reads[] = {
5150 CreateMockRead(*stream1_reply, 1),
5151 CreateMockRead(*stream2_syn, 2),
5152 CreateMockRead(*stream1_body, 3),
5153 CreateMockRead(*stream2_headers, 4),
5154 CreateMockRead(*stream2_body, 5),
5155 MockRead(ASYNC, 0, 6), // EOF
5158 HttpResponseInfo response;
5159 HttpResponseInfo response2;
5160 std::string expected_push_result("pushed");
5161 DeterministicSocketData data(reads, arraysize(reads),
5162 writes, arraysize(writes));
5164 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5165 BoundNetLog(), GetParam(), NULL);
5166 helper.SetDeterministic();
5167 helper.AddDeterministicData(&data);
5168 helper.RunPreTestSetup();
5170 HttpNetworkTransaction* trans = helper.trans();
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.
5175 data.SetStop(3);
5177 // Start the transaction.
5178 TestCompletionCallback callback;
5179 int rv = trans->Start(
5180 &CreateGetRequest(), callback.callback(), BoundNetLog());
5181 EXPECT_EQ(ERR_IO_PENDING, rv);
5182 data.Run();
5183 rv = callback.WaitForResult();
5184 EXPECT_EQ(0, rv);
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(
5189 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5190 rv = trans2->Start(
5191 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5192 EXPECT_EQ(ERR_IO_PENDING, rv);
5193 data.RunFor(3);
5194 base::RunLoop().RunUntilIdle();
5196 // Read the server push body.
5197 std::string result2;
5198 ReadResult(trans2.get(), &data, &result2);
5199 // Read the response body.
5200 std::string result;
5201 ReadResult(trans, &data, &result);
5203 // 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;
5210 // Verify the SYN_REPLY.
5211 // Copy the response info, because trans goes away.
5212 response = *trans->GetResponseInfo();
5213 response2 = *trans2->GetResponseInfo();
5215 VerifyStreamsClosed(helper);
5217 // Verify the SYN_REPLY.
5218 EXPECT_TRUE(response.headers.get() != NULL);
5219 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5221 // Verify the pushed stream.
5222 EXPECT_TRUE(response2.headers.get() != NULL);
5223 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5225 // Read the final EOF (which will close the session)
5226 data.RunFor(1);
5228 // Verify that we consumed all test data.
5229 EXPECT_TRUE(data.at_read_eof());
5230 EXPECT_TRUE(data.at_write_eof());
5233 // TODO(baranovich): HTTP 2 does not allow multiple HEADERS frames
5234 TEST_P(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) {
5235 // We push a stream and attempt to claim it before the headers come down.
5236 scoped_ptr<SpdyFrame> stream1_syn(
5237 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5238 scoped_ptr<SpdyFrame> stream1_body(
5239 spdy_util_.ConstructSpdyBodyFrame(1, true));
5240 MockWrite writes[] = {
5241 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5244 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5245 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";
5249 spdy_util_.AddUrlToHeaderBlock(
5250 "http://www.google.com/foo.dat", initial_headers.get());
5251 scoped_ptr<SpdyFrame> stream2_syn(
5252 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
5254 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5255 (*middle_headers)["hello"] = "bye";
5256 scoped_ptr<SpdyFrame> stream2_headers1(
5257 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(),
5258 false,
5260 LOWEST,
5261 HEADERS,
5262 CONTROL_FLAG_NONE,
5263 0));
5265 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5266 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5267 if (spdy_util_.spdy_version() < SPDY4) {
5268 // SPDY4/HTTP2 eliminates use of the :version header.
5269 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5271 scoped_ptr<SpdyFrame> stream2_headers2(
5272 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5273 false,
5275 LOWEST,
5276 HEADERS,
5277 CONTROL_FLAG_NONE,
5278 0));
5280 scoped_ptr<SpdyFrame>
5281 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5282 const char kPushedData[] = "pushed";
5283 scoped_ptr<SpdyFrame> stream2_body(
5284 spdy_util_.ConstructSpdyBodyFrame(
5285 2, kPushedData, strlen(kPushedData), true));
5286 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),
5292 CreateMockRead(*stream2_body, 6),
5293 MockRead(ASYNC, 0, 7), // EOF
5296 HttpResponseInfo response;
5297 HttpResponseInfo response2;
5298 std::string expected_push_result("pushed");
5299 DeterministicSocketData data(reads, arraysize(reads),
5300 writes, arraysize(writes));
5302 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5303 BoundNetLog(), GetParam(), NULL);
5304 helper.SetDeterministic();
5305 helper.AddDeterministicData(&data);
5306 helper.RunPreTestSetup();
5308 HttpNetworkTransaction* trans = helper.trans();
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.
5313 data.SetStop(4);
5315 // Start the transaction.
5316 TestCompletionCallback callback;
5317 int rv = trans->Start(
5318 &CreateGetRequest(), callback.callback(), BoundNetLog());
5319 EXPECT_EQ(ERR_IO_PENDING, rv);
5320 data.Run();
5321 rv = callback.WaitForResult();
5322 EXPECT_EQ(0, rv);
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(
5327 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5328 rv = trans2->Start(
5329 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5330 EXPECT_EQ(ERR_IO_PENDING, rv);
5331 data.RunFor(3);
5332 base::RunLoop().RunUntilIdle();
5334 // Read the server push body.
5335 std::string result2;
5336 ReadResult(trans2.get(), &data, &result2);
5337 // Read the response body.
5338 std::string result;
5339 ReadResult(trans, &data, &result);
5341 // Verify that the received push data is same as the expected push data.
5342 EXPECT_EQ(expected_push_result, result2);
5344 // Verify the SYN_REPLY.
5345 // Copy the response info, because trans goes away.
5346 response = *trans->GetResponseInfo();
5347 response2 = *trans2->GetResponseInfo();
5349 VerifyStreamsClosed(helper);
5351 // Verify the SYN_REPLY.
5352 EXPECT_TRUE(response.headers.get() != NULL);
5353 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5355 // Verify the pushed stream.
5356 EXPECT_TRUE(response2.headers.get() != NULL);
5357 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5359 // Verify we got all the headers from all header blocks.
5360 if (spdy_util_.spdy_version() < SPDY4)
5361 EXPECT_TRUE(response2.headers->HasHeaderValue("alpha", "beta"));
5362 EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye"));
5363 EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200"));
5365 // Read the final EOF (which will close the session)
5366 data.RunFor(1);
5368 // Verify that we consumed all test data.
5369 EXPECT_TRUE(data.at_read_eof());
5370 EXPECT_TRUE(data.at_write_eof());
5373 TEST_P(SpdyNetworkTransactionTest, ServerPushWithNoStatusHeaderFrames) {
5374 // We push a stream and attempt to claim it before the headers come down.
5375 scoped_ptr<SpdyFrame> stream1_syn(
5376 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5377 scoped_ptr<SpdyFrame> stream1_body(
5378 spdy_util_.ConstructSpdyBodyFrame(1, true));
5379 MockWrite writes[] = {
5380 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5383 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5384 spdy_util_.AddUrlToHeaderBlock(
5385 "http://www.google.com/foo.dat", initial_headers.get());
5386 scoped_ptr<SpdyFrame> stream2_syn(
5387 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
5389 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5390 (*middle_headers)["hello"] = "bye";
5391 scoped_ptr<SpdyFrame> stream2_headers1(
5392 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(),
5393 false,
5395 LOWEST,
5396 HEADERS,
5397 CONTROL_FLAG_NONE,
5398 0));
5400 scoped_ptr<SpdyFrame>
5401 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5402 const char kPushedData[] = "pushed";
5403 scoped_ptr<SpdyFrame> stream2_body(
5404 spdy_util_.ConstructSpdyBodyFrame(
5405 2, kPushedData, strlen(kPushedData), true));
5406 MockRead reads[] = {
5407 CreateMockRead(*stream1_reply, 1),
5408 CreateMockRead(*stream2_syn, 2),
5409 CreateMockRead(*stream1_body, 3),
5410 CreateMockRead(*stream2_headers1, 4),
5411 CreateMockRead(*stream2_body, 5),
5412 MockRead(ASYNC, 0, 6), // EOF
5415 DeterministicSocketData data(reads, arraysize(reads),
5416 writes, arraysize(writes));
5418 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5419 BoundNetLog(), GetParam(), NULL);
5420 helper.SetDeterministic();
5421 helper.AddDeterministicData(&data);
5422 helper.RunPreTestSetup();
5424 HttpNetworkTransaction* trans = helper.trans();
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);
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);
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(
5443 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5444 rv = trans2->Start(
5445 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5446 EXPECT_EQ(ERR_IO_PENDING, rv);
5447 data.RunFor(2);
5448 base::RunLoop().RunUntilIdle();
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);
5458 // Verify that we haven't received any push data.
5459 EXPECT_EQ("", result2);
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);
5466 VerifyStreamsClosed(helper);
5468 // Verify the SYN_REPLY.
5469 EXPECT_TRUE(response.headers.get() != NULL);
5470 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5472 // Read the final EOF (which will close the session).
5473 data.RunFor(1);
5475 // Verify that we consumed all test data.
5476 EXPECT_TRUE(data.at_read_eof());
5477 EXPECT_TRUE(data.at_write_eof());
5480 TEST_P(SpdyNetworkTransactionTest, SynReplyWithHeaders) {
5481 scoped_ptr<SpdyFrame> req(
5482 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5483 scoped_ptr<SpdyFrame> rst(
5484 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
5485 MockWrite writes[] = {
5486 CreateMockWrite(*req), CreateMockWrite(*rst),
5489 scoped_ptr<SpdyFrame> stream1_reply(
5490 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5492 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5493 (*late_headers)["hello"] = "bye";
5494 scoped_ptr<SpdyFrame> stream1_headers(
5495 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5496 false,
5498 LOWEST,
5499 HEADERS,
5500 CONTROL_FLAG_NONE,
5501 0));
5502 scoped_ptr<SpdyFrame> stream1_body(
5503 spdy_util_.ConstructSpdyBodyFrame(1, true));
5504 MockRead reads[] = {
5505 CreateMockRead(*stream1_reply),
5506 CreateMockRead(*stream1_headers),
5507 CreateMockRead(*stream1_body),
5508 MockRead(ASYNC, 0, 0) // EOF
5511 DelayedSocketData data(1, reads, arraysize(reads),
5512 writes, arraysize(writes));
5513 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5514 BoundNetLog(), GetParam(), NULL);
5515 helper.RunToCompletion(&data);
5516 TransactionHelperResult out = helper.output();
5517 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
5520 TEST_P(SpdyNetworkTransactionTest, SynReplyWithLateHeaders) {
5521 scoped_ptr<SpdyFrame> req(
5522 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5523 scoped_ptr<SpdyFrame> rst(
5524 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
5525 MockWrite writes[] = {
5526 CreateMockWrite(*req),
5527 CreateMockWrite(*rst),
5530 scoped_ptr<SpdyFrame> stream1_reply(
5531 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5533 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5534 (*late_headers)["hello"] = "bye";
5535 scoped_ptr<SpdyFrame> stream1_headers(
5536 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5537 false,
5539 LOWEST,
5540 HEADERS,
5541 CONTROL_FLAG_NONE,
5542 0));
5543 scoped_ptr<SpdyFrame> stream1_body(
5544 spdy_util_.ConstructSpdyBodyFrame(1, false));
5545 scoped_ptr<SpdyFrame> stream1_body2(
5546 spdy_util_.ConstructSpdyBodyFrame(1, true));
5547 MockRead reads[] = {
5548 CreateMockRead(*stream1_reply),
5549 CreateMockRead(*stream1_body),
5550 CreateMockRead(*stream1_headers),
5551 CreateMockRead(*stream1_body2),
5552 MockRead(ASYNC, 0, 0) // EOF
5555 DelayedSocketData data(1, reads, arraysize(reads),
5556 writes, arraysize(writes));
5557 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5558 BoundNetLog(), GetParam(), NULL);
5559 helper.RunToCompletion(&data);
5560 TransactionHelperResult out = helper.output();
5561 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
5564 TEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
5565 // 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".
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
5576 "http://www.google.com/foo.html",
5577 "https://www.google.com/foo.js", // Bad protocol
5579 "http://www.google.com/foo.html",
5580 "ftp://www.google.com/foo.js", // Invalid Protocol
5582 "http://www.google.com/foo.html",
5583 "http://blat.www.google.com/foo.js", // Cross subdomain
5585 "http://www.google.com/foo.html",
5586 "http://www.foo.com/foo.js", // Cross domain
5589 for (size_t index = 0; index < arraysize(kTestCases); index += 2) {
5590 const char* url_to_fetch = kTestCases[index];
5591 const char* url_to_push = kTestCases[index + 1];
5593 scoped_ptr<SpdyFrame> stream1_syn(
5594 spdy_util_.ConstructSpdyGet(url_to_fetch, false, 1, LOWEST));
5595 scoped_ptr<SpdyFrame> stream1_body(
5596 spdy_util_.ConstructSpdyBodyFrame(1, true));
5597 scoped_ptr<SpdyFrame> push_rst(
5598 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
5599 MockWrite writes[] = {
5600 CreateMockWrite(*stream1_syn, 1),
5601 CreateMockWrite(*push_rst, 4),
5604 scoped_ptr<SpdyFrame>
5605 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5606 scoped_ptr<SpdyFrame>
5607 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
5611 url_to_push));
5612 const char kPushedData[] = "pushed";
5613 scoped_ptr<SpdyFrame> stream2_body(
5614 spdy_util_.ConstructSpdyBodyFrame(
5615 2, kPushedData, strlen(kPushedData), true));
5616 scoped_ptr<SpdyFrame> rst(
5617 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
5619 MockRead reads[] = {
5620 CreateMockRead(*stream1_reply, 2),
5621 CreateMockRead(*stream2_syn, 3),
5622 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
5623 CreateMockRead(*stream2_body, 6),
5624 MockRead(ASYNC, ERR_IO_PENDING, 7), // Force a pause
5627 HttpResponseInfo response;
5628 OrderedSocketData data(reads, arraysize(reads),
5629 writes, arraysize(writes));
5631 HttpRequestInfo request;
5632 request.method = "GET";
5633 request.url = GURL(url_to_fetch);
5634 request.load_flags = 0;
5636 // Enable cross-origin push. Since we are not using a proxy, this should
5637 // not actually enable cross-origin SPDY push.
5638 scoped_ptr<SpdySessionDependencies> session_deps(
5639 CreateSpdySessionDependencies(GetParam()));
5640 session_deps->trusted_spdy_proxy = "123.45.67.89:8080";
5641 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5642 BoundNetLog(), GetParam(),
5643 session_deps.release());
5644 helper.RunPreTestSetup();
5645 helper.AddData(&data);
5647 HttpNetworkTransaction* trans = helper.trans();
5649 // Start the transaction with basic parameters.
5650 TestCompletionCallback callback;
5652 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5653 EXPECT_EQ(ERR_IO_PENDING, rv);
5654 rv = callback.WaitForResult();
5656 // Read the response body.
5657 std::string result;
5658 ReadResult(trans, &data, &result);
5660 // Verify that we consumed all test data.
5661 EXPECT_TRUE(data.at_read_eof());
5662 EXPECT_TRUE(data.at_write_eof());
5664 // Verify the SYN_REPLY.
5665 // Copy the response info, because trans goes away.
5666 response = *trans->GetResponseInfo();
5668 VerifyStreamsClosed(helper);
5670 // Verify the SYN_REPLY.
5671 EXPECT_TRUE(response.headers.get() != NULL);
5672 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5676 TEST_P(SpdyNetworkTransactionTest, RetryAfterRefused) {
5677 // Construct the request.
5678 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));
5682 MockWrite writes[] = {
5683 CreateMockWrite(*req, 1),
5684 CreateMockWrite(*req2, 3),
5687 scoped_ptr<SpdyFrame> refused(
5688 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
5689 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5690 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(3, true));
5691 MockRead reads[] = {
5692 CreateMockRead(*refused, 2),
5693 CreateMockRead(*resp, 4),
5694 CreateMockRead(*body, 5),
5695 MockRead(ASYNC, 0, 6) // EOF
5698 OrderedSocketData data(reads, arraysize(reads),
5699 writes, arraysize(writes));
5700 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5701 BoundNetLog(), GetParam(), NULL);
5703 helper.RunPreTestSetup();
5704 helper.AddData(&data);
5706 HttpNetworkTransaction* trans = helper.trans();
5708 // Start the transaction with basic parameters.
5709 TestCompletionCallback callback;
5710 int rv = trans->Start(
5711 &CreateGetRequest(), callback.callback(), BoundNetLog());
5712 EXPECT_EQ(ERR_IO_PENDING, rv);
5713 rv = callback.WaitForResult();
5714 EXPECT_EQ(OK, rv);
5716 // Verify that we consumed all test data.
5717 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
5718 << data.read_count()
5719 << " Read index: "
5720 << data.read_index();
5721 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
5722 << data.write_count()
5723 << " Write index: "
5724 << data.write_index();
5726 // Verify the SYN_REPLY.
5727 HttpResponseInfo response = *trans->GetResponseInfo();
5728 EXPECT_TRUE(response.headers.get() != NULL);
5729 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5732 TEST_P(SpdyNetworkTransactionTest, OutOfOrderSynStream) {
5733 // 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
5736 // start before the second, causing the second to be numbered differently
5737 // than the order they were created.
5738 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));
5744 MockWrite writes[] = {
5745 CreateMockWrite(*req1, 0),
5746 CreateMockWrite(*req2, 3),
5747 CreateMockWrite(*req3, 4),
5750 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));
5756 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
5766 DeterministicSocketData data(reads, arraysize(reads),
5767 writes, arraysize(writes));
5768 NormalSpdyTransactionHelper helper(CreateGetRequest(), LOWEST,
5769 BoundNetLog(), GetParam(), NULL);
5770 helper.SetDeterministic();
5771 helper.RunPreTestSetup();
5772 helper.AddDeterministicData(&data);
5774 // Start the first transaction to set up the SpdySession
5775 HttpNetworkTransaction* trans = helper.trans();
5776 TestCompletionCallback callback;
5777 HttpRequestInfo info1 = CreateGetRequest();
5778 int rv = trans->Start(&info1, callback.callback(), BoundNetLog());
5779 EXPECT_EQ(ERR_IO_PENDING, rv);
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.
5784 base::RunLoop().RunUntilIdle();
5786 // Now, start both new transactions
5787 HttpRequestInfo info2 = CreateGetRequest();
5788 TestCompletionCallback callback2;
5789 scoped_ptr<HttpNetworkTransaction> trans2(
5790 new HttpNetworkTransaction(MEDIUM, helper.session().get()));
5791 rv = trans2->Start(&info2, callback2.callback(), BoundNetLog());
5792 EXPECT_EQ(ERR_IO_PENDING, rv);
5793 base::RunLoop().RunUntilIdle();
5795 HttpRequestInfo info3 = CreateGetRequest();
5796 TestCompletionCallback callback3;
5797 scoped_ptr<HttpNetworkTransaction> trans3(
5798 new HttpNetworkTransaction(HIGHEST, helper.session().get()));
5799 rv = trans3->Start(&info3, callback3.callback(), BoundNetLog());
5800 EXPECT_EQ(ERR_IO_PENDING, rv);
5801 base::RunLoop().RunUntilIdle();
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.
5806 data.RunFor(2);
5807 EXPECT_EQ(OK, callback.WaitForResult());
5809 // And now we can allow everything else to run to completion.
5810 data.SetStop(10);
5811 data.Run();
5812 EXPECT_EQ(OK, callback2.WaitForResult());
5813 EXPECT_EQ(OK, callback3.WaitForResult());
5815 helper.VerifyDataConsumed();
5818 // The tests below are only for SPDY/3 and above.
5820 // Test that sent data frames and received WINDOW_UPDATE frames change
5821 // the send_window_size_ correctly.
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.
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.
5841 TEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) {
5842 if (GetParam().protocol < kProtoSPDY3)
5843 return;
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));
5857 MockWrite writes[] = {
5858 CreateMockWrite(*req, 0),
5859 CreateMockWrite(*body, 1),
5860 CreateMockWrite(*body_end, 2),
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
5883 DeterministicSocketData data(reads, arraysize(reads),
5884 writes, arraysize(writes));
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()));
5891 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
5893 // Setup the request
5894 HttpRequestInfo request;
5895 request.method = "POST";
5896 request.url = GURL(kDefaultURL);
5897 request.upload_data_stream = &upload_data_stream;
5899 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5900 BoundNetLog(), GetParam(), NULL);
5901 helper.SetDeterministic();
5902 helper.AddDeterministicData(&data);
5903 helper.RunPreTestSetup();
5905 HttpNetworkTransaction* trans = helper.trans();
5907 TestCompletionCallback callback;
5908 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5910 EXPECT_EQ(ERR_IO_PENDING, rv);
5912 data.RunFor(11);
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());
5922 data.RunFor(1);
5924 rv = callback.WaitForResult();
5925 EXPECT_EQ(OK, rv);
5927 helper.VerifyDataConsumed();
5930 // Test that received data frames and sent WINDOW_UPDATE frames change
5931 // the recv_window_size_ correctly.
5932 TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) {
5933 if (GetParam().protocol < kProtoSPDY3)
5934 return;
5936 // Amount of body required to trigger a sent window update.
5937 const size_t kTargetSize = kSpdyStreamInitialWindowSize / 2 + 1;
5939 scoped_ptr<SpdyFrame> req(
5940 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5941 scoped_ptr<SpdyFrame> session_window_update(
5942 spdy_util_.ConstructSpdyWindowUpdate(0, kTargetSize));
5943 scoped_ptr<SpdyFrame> window_update(
5944 spdy_util_.ConstructSpdyWindowUpdate(1, kTargetSize));
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));
5952 std::vector<MockRead> reads;
5953 scoped_ptr<SpdyFrame> resp(
5954 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5955 reads.push_back(CreateMockRead(*resp));
5957 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;
5966 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, 0)); // Yield.
5968 DelayedSocketData data(1, vector_as_array(&reads), reads.size(),
5969 vector_as_array(&writes), writes.size());
5971 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5972 BoundNetLog(), GetParam(), NULL);
5973 helper.AddData(&data);
5974 helper.RunPreTestSetup();
5975 HttpNetworkTransaction* trans = helper.trans();
5977 TestCompletionCallback callback;
5978 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5980 EXPECT_EQ(ERR_IO_PENDING, rv);
5981 rv = callback.WaitForResult();
5982 EXPECT_EQ(OK, rv);
5984 SpdyHttpStream* stream =
5985 static_cast<SpdyHttpStream*>(trans->stream_.get());
5986 ASSERT_TRUE(stream != NULL);
5987 ASSERT_TRUE(stream->stream() != NULL);
5989 // 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());
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);
5999 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
6000 // size increased to default.
6001 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')));
6008 // Allow scheduled WINDOW_UPDATE frames to write.
6009 base::RunLoop().RunUntilIdle();
6010 helper.VerifyDataConsumed();
6013 // Test that WINDOW_UPDATE frame causing overflow is handled correctly.
6014 TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
6015 if (GetParam().protocol < kProtoSPDY3)
6016 return;
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;
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));
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),
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
6048 DeterministicSocketData data(reads, arraysize(reads),
6049 writes, arraysize(writes));
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()));
6056 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
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;
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();
6071 TestCompletionCallback callback;
6072 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6073 ASSERT_EQ(ERR_IO_PENDING, rv);
6075 data.RunFor(5);
6076 ASSERT_TRUE(callback.have_result());
6077 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, callback.WaitForResult());
6078 helper.VerifyDataConsumed();
6081 // Test that after hitting a send window size of 0, the write process
6082 // stalls and upon receiving WINDOW_UPDATE frame write resumes.
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.
6096 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) {
6097 if (GetParam().protocol < kProtoSPDY3)
6098 return;
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;
6106 // Calculate last frame's size; 0 size data frame is legal.
6107 size_t last_frame_size =
6108 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
6110 // Construct content for a data frame of maximum size.
6111 std::string content(kMaxSpdyFrameChunkSize, 'a');
6113 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6114 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
6115 LOWEST, NULL, 0));
6117 // Full frames.
6118 scoped_ptr<SpdyFrame> body1(
6119 spdy_util_.ConstructSpdyBodyFrame(
6120 1, content.c_str(), content.size(), false));
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));
6127 // Data frame to be sent once WINDOW_UPDATE frame is received.
6128 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
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);
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
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;
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);
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()));
6172 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
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();
6183 HttpNetworkTransaction* trans = helper.trans();
6185 TestCompletionCallback callback;
6186 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6187 EXPECT_EQ(ERR_IO_PENDING, rv);
6189 base::RunLoop().RunUntilIdle(); // Write as much as we can.
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());
6203 data.ForceNextRead(); // Read in WINDOW_UPDATE frame.
6204 rv = callback.WaitForResult();
6205 helper.VerifyDataConsumed();
6208 // Test we correctly handle the case where the SETTINGS frame results in
6209 // unstalling the send window.
6210 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
6211 if (GetParam().protocol < kProtoSPDY3)
6212 return;
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;
6219 // Calculate last frame's size; 0 size data frame is legal.
6220 size_t last_frame_size =
6221 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
6223 // Construct content for a data frame of maximum size.
6224 std::string content(kMaxSpdyFrameChunkSize, 'a');
6226 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6227 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
6228 LOWEST, NULL, 0));
6230 // Full frames.
6231 scoped_ptr<SpdyFrame> body1(
6232 spdy_util_.ConstructSpdyBodyFrame(
6233 1, content.c_str(), content.size(), false));
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));
6240 // Data frame to be sent once SETTINGS frame is received.
6241 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
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++));
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));
6261 reads.push_back(CreateMockRead(*settings_frame_large, i++));
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++));
6268 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
6269 writes.push_back(CreateMockWrite(*settings_ack, i++));
6271 writes.push_back(CreateMockWrite(*body3, i++));
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
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());
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()));
6289 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
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);
6301 HttpNetworkTransaction* trans = helper.trans();
6303 TestCompletionCallback callback;
6304 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6305 EXPECT_EQ(ERR_IO_PENDING, rv);
6307 data.RunFor(num_writes - 1); // Write as much as we can.
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());
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());
6322 data.RunFor(7); // Read in SETTINGS frame to unstall.
6323 rv = callback.WaitForResult();
6324 helper.VerifyDataConsumed();
6325 // If stream is NULL, that means it was unstalled and closed.
6326 EXPECT_TRUE(stream->stream() == NULL);
6329 // Test we correctly handle the case where the SETTINGS frame results in a
6330 // negative send window size.
6331 TEST_P(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
6332 if (GetParam().protocol < kProtoSPDY3)
6333 return;
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;
6340 // Calculate last frame's size; 0 size data frame is legal.
6341 size_t last_frame_size =
6342 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
6344 // Construct content for a data frame of maximum size.
6345 std::string content(kMaxSpdyFrameChunkSize, 'a');
6347 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6348 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
6349 LOWEST, NULL, 0));
6351 // Full frames.
6352 scoped_ptr<SpdyFrame> body1(
6353 spdy_util_.ConstructSpdyBodyFrame(
6354 1, content.c_str(), content.size(), false));
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));
6361 // Data frame to be sent once SETTINGS frame is received.
6362 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
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++));
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));
6388 reads.push_back(CreateMockRead(*settings_frame_small, i++));
6390 if (GetParam().protocol >= kProtoSPDY3)
6391 reads.push_back(CreateMockRead(*session_window_update_init_size, i++));
6393 reads.push_back(CreateMockRead(*window_update_init_size, i++));
6395 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
6396 writes.push_back(CreateMockWrite(*settings_ack, i++));
6398 writes.push_back(CreateMockWrite(*body3, i++));
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
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());
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()));
6416 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
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);
6428 HttpNetworkTransaction* trans = helper.trans();
6430 TestCompletionCallback callback;
6431 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6432 EXPECT_EQ(ERR_IO_PENDING, rv);
6434 data.RunFor(num_writes - 1); // Write as much as we can.
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());
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());
6449 // Read in WINDOW_UPDATE or SETTINGS frame.
6450 data.RunFor((GetParam().protocol >= kProtoSPDY31) ? 9 : 8);
6451 rv = callback.WaitForResult();
6452 helper.VerifyDataConsumed();
6455 class SpdyNetworkTransactionNoTLSUsageCheckTest
6456 : public SpdyNetworkTransactionTest {
6457 protected:
6458 void RunNoTLSUsageCheckTest(scoped_ptr<SSLSocketDataProvider> ssl_provider) {
6459 // Construct the request.
6460 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyGet(
6461 "https://www.google.com/", false, 1, LOWEST));
6462 MockWrite writes[] = {CreateMockWrite(*req)};
6464 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6465 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6466 MockRead reads[] = {
6467 CreateMockRead(*resp), CreateMockRead(*body),
6468 MockRead(ASYNC, 0, 0) // EOF
6471 DelayedSocketData data(
6472 1, reads, arraysize(reads), writes, arraysize(writes));
6473 HttpRequestInfo request;
6474 request.method = "GET";
6475 request.url = GURL("https://www.google.com/");
6476 NormalSpdyTransactionHelper helper(
6477 request, DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6478 helper.RunToCompletionWithSSLData(&data, ssl_provider.Pass());
6479 TransactionHelperResult out = helper.output();
6480 EXPECT_EQ(OK, out.rv);
6481 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
6482 EXPECT_EQ("hello!", out.response_data);
6486 //-----------------------------------------------------------------------------
6487 // All tests are run with three different connection types: SPDY after NPN
6488 // negotiation, SPDY without SSL, and SPDY with SSL.
6490 // TODO(akalin): Use ::testing::Combine() when we are able to use
6491 // <tr1/tuple>.
6492 INSTANTIATE_TEST_CASE_P(
6493 Spdy,
6494 SpdyNetworkTransactionNoTLSUsageCheckTest,
6495 ::testing::Values(SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2,
6496 SPDYNPN),
6497 SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYNPN),
6498 SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNPN)));
6500 TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest, TLSVersionTooOld) {
6501 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6502 new SSLSocketDataProvider(ASYNC, OK));
6503 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6504 &ssl_provider->connection_status);
6506 RunNoTLSUsageCheckTest(ssl_provider.Pass());
6509 TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest, TLSCipherSuiteSucky) {
6510 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6511 new SSLSocketDataProvider(ASYNC, OK));
6512 // Set to TLS_RSA_WITH_NULL_MD5
6513 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider->connection_status);
6515 RunNoTLSUsageCheckTest(ssl_provider.Pass());
6518 class SpdyNetworkTransactionTLSUsageCheckTest
6519 : public SpdyNetworkTransactionTest {
6520 protected:
6521 void RunTLSUsageCheckTest(scoped_ptr<SSLSocketDataProvider> ssl_provider) {
6522 scoped_ptr<SpdyFrame> goaway(
6523 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_INADEQUATE_SECURITY, ""));
6524 MockWrite writes[] = {CreateMockWrite(*goaway)};
6526 DelayedSocketData data(1, NULL, 0, writes, arraysize(writes));
6527 HttpRequestInfo request;
6528 request.method = "GET";
6529 request.url = GURL("https://www.google.com/");
6530 NormalSpdyTransactionHelper helper(
6531 request, DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6532 helper.RunToCompletionWithSSLData(&data, ssl_provider.Pass());
6533 TransactionHelperResult out = helper.output();
6534 EXPECT_EQ(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY, out.rv);
6538 INSTANTIATE_TEST_CASE_P(
6539 Spdy,
6540 SpdyNetworkTransactionTLSUsageCheckTest,
6541 ::testing::Values(SpdyNetworkTransactionTestParams(kProtoSPDY4, SPDYNPN)));
6543 TEST_P(SpdyNetworkTransactionTLSUsageCheckTest, TLSVersionTooOld) {
6544 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6545 new SSLSocketDataProvider(ASYNC, OK));
6546 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6547 &ssl_provider->connection_status);
6549 RunTLSUsageCheckTest(ssl_provider.Pass());
6552 TEST_P(SpdyNetworkTransactionTLSUsageCheckTest, TLSCipherSuiteSucky) {
6553 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6554 new SSLSocketDataProvider(ASYNC, OK));
6555 // Set to TLS_RSA_WITH_NULL_MD5
6556 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider->connection_status);
6558 RunTLSUsageCheckTest(ssl_provider.Pass());
6561 } // namespace net