Raise SIGKILL if cast_service doesn't Finalize() within timeout.
[chromium-blink-merge.git] / net / spdy / spdy_network_transaction_unittest.cc
blobb1dd944b3fad7907b637ea6c3c19b5b6304e3613
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/files/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/chunked_upload_data_stream.h"
19 #include "net/base/elements_upload_data_stream.h"
20 #include "net/base/net_log_unittest.h"
21 #include "net/base/request_priority.h"
22 #include "net/base/upload_bytes_element_reader.h"
23 #include "net/base/upload_file_element_reader.h"
24 #include "net/http/http_network_session_peer.h"
25 #include "net/http/http_network_transaction.h"
26 #include "net/http/http_server_properties.h"
27 #include "net/http/http_transaction_test_util.h"
28 #include "net/socket/client_socket_pool_base.h"
29 #include "net/socket/next_proto.h"
30 #include "net/spdy/buffered_spdy_framer.h"
31 #include "net/spdy/spdy_http_stream.h"
32 #include "net/spdy/spdy_http_utils.h"
33 #include "net/spdy/spdy_session.h"
34 #include "net/spdy/spdy_session_pool.h"
35 #include "net/spdy/spdy_test_util_common.h"
36 #include "net/spdy/spdy_test_utils.h"
37 #include "net/ssl/ssl_connection_status_flags.h"
38 #include "net/url_request/url_request_test_util.h"
39 #include "testing/gmock/include/gmock/gmock.h"
40 #include "testing/platform_test.h"
42 //-----------------------------------------------------------------------------
44 namespace net {
46 namespace {
48 using testing::Each;
49 using testing::Eq;
51 const char kRequestUrl[] = "http://www.google.com/";
53 enum SpdyNetworkTransactionTestSSLType {
54 SPDYNPN,
55 SPDYNOSSL,
56 SPDYSSL,
59 struct SpdyNetworkTransactionTestParams {
60 SpdyNetworkTransactionTestParams()
61 : protocol(kProtoSPDY31),
62 ssl_type(SPDYNPN) {}
64 SpdyNetworkTransactionTestParams(
65 NextProto protocol,
66 SpdyNetworkTransactionTestSSLType ssl_type)
67 : protocol(protocol),
68 ssl_type(ssl_type) {}
70 NextProto protocol;
71 SpdyNetworkTransactionTestSSLType ssl_type;
74 void UpdateSpdySessionDependencies(
75 SpdyNetworkTransactionTestParams test_params,
76 SpdySessionDependencies* session_deps) {
77 switch (test_params.ssl_type) {
78 case SPDYNPN:
79 session_deps->http_server_properties.SetAlternativeService(
80 HostPortPair("www.google.com", 80),
81 AlternativeService(
82 AlternateProtocolFromNextProto(test_params.protocol),
83 "www.google.com", 443),
84 1);
85 session_deps->use_alternate_protocols = true;
86 session_deps->next_protos = SpdyNextProtos();
87 break;
88 case SPDYNOSSL:
89 session_deps->force_spdy_over_ssl = false;
90 session_deps->force_spdy_always = true;
91 break;
92 case SPDYSSL:
93 session_deps->force_spdy_over_ssl = true;
94 session_deps->force_spdy_always = true;
95 break;
96 default:
97 NOTREACHED();
101 SpdySessionDependencies* CreateSpdySessionDependencies(
102 SpdyNetworkTransactionTestParams test_params) {
103 SpdySessionDependencies* session_deps =
104 new SpdySessionDependencies(test_params.protocol);
105 UpdateSpdySessionDependencies(test_params, session_deps);
106 return session_deps;
109 SpdySessionDependencies* CreateSpdySessionDependencies(
110 SpdyNetworkTransactionTestParams test_params,
111 ProxyService* proxy_service) {
112 SpdySessionDependencies* session_deps =
113 new SpdySessionDependencies(test_params.protocol, proxy_service);
114 UpdateSpdySessionDependencies(test_params, session_deps);
115 return session_deps;
118 } // namespace
120 class SpdyNetworkTransactionTest
121 : public ::testing::TestWithParam<SpdyNetworkTransactionTestParams> {
122 protected:
123 SpdyNetworkTransactionTest() : spdy_util_(GetParam().protocol) {
126 virtual ~SpdyNetworkTransactionTest() {
127 // UploadDataStream may post a deletion tasks back to the message loop on
128 // destruction.
129 upload_data_stream_.reset();
130 base::RunLoop().RunUntilIdle();
133 void SetUp() override {
134 google_get_request_initialized_ = false;
135 google_post_request_initialized_ = false;
136 google_chunked_post_request_initialized_ = false;
137 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
140 struct TransactionHelperResult {
141 int rv;
142 std::string status_line;
143 std::string response_data;
144 HttpResponseInfo response_info;
147 // A helper class that handles all the initial npn/ssl setup.
148 class NormalSpdyTransactionHelper {
149 public:
150 NormalSpdyTransactionHelper(const HttpRequestInfo& request,
151 RequestPriority priority,
152 const BoundNetLog& log,
153 SpdyNetworkTransactionTestParams test_params,
154 SpdySessionDependencies* session_deps)
155 : request_(request),
156 priority_(priority),
157 session_deps_(session_deps == NULL ?
158 CreateSpdySessionDependencies(test_params) :
159 session_deps),
160 session_(SpdySessionDependencies::SpdyCreateSession(
161 session_deps_.get())),
162 log_(log),
163 test_params_(test_params),
164 deterministic_(false),
165 spdy_enabled_(true) {
166 switch (test_params_.ssl_type) {
167 case SPDYNOSSL:
168 case SPDYSSL:
169 port_ = 80;
170 break;
171 case SPDYNPN:
172 port_ = 443;
173 break;
174 default:
175 NOTREACHED();
179 ~NormalSpdyTransactionHelper() {
180 // Any test which doesn't close the socket by sending it an EOF will
181 // have a valid session left open, which leaks the entire session pool.
182 // This is just fine - in fact, some of our tests intentionally do this
183 // so that we can check consistency of the SpdySessionPool as the test
184 // finishes. If we had put an EOF on the socket, the SpdySession would
185 // have closed and we wouldn't be able to check the consistency.
187 // Forcefully close existing sessions here.
188 session()->spdy_session_pool()->CloseAllSessions();
191 void SetDeterministic() {
192 session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
193 session_deps_.get());
194 deterministic_ = true;
197 void SetSpdyDisabled() {
198 spdy_enabled_ = false;
199 port_ = 80;
202 void RunPreTestSetup() {
203 if (!session_deps_.get())
204 session_deps_.reset(CreateSpdySessionDependencies(test_params_));
205 if (!session_.get()) {
206 session_ = SpdySessionDependencies::SpdyCreateSession(
207 session_deps_.get());
210 // We're now ready to use SSL-npn SPDY.
211 trans_.reset(new HttpNetworkTransaction(priority_, session_.get()));
214 // Start the transaction, read some data, finish.
215 void RunDefaultTest() {
216 if (!StartDefaultTest())
217 return;
218 FinishDefaultTest();
221 bool StartDefaultTest() {
222 output_.rv = trans_->Start(&request_, callback_.callback(), log_);
224 // We expect an IO Pending or some sort of error.
225 EXPECT_LT(output_.rv, 0);
226 return output_.rv == ERR_IO_PENDING;
229 void FinishDefaultTest() {
230 output_.rv = callback_.WaitForResult();
231 if (output_.rv != OK) {
232 session_->spdy_session_pool()->CloseCurrentSessions(ERR_ABORTED);
233 return;
236 // Verify responses.
237 const HttpResponseInfo* response = trans_->GetResponseInfo();
238 ASSERT_TRUE(response != NULL);
239 ASSERT_TRUE(response->headers.get() != NULL);
240 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
241 EXPECT_EQ(spdy_enabled_, response->was_fetched_via_spdy);
242 if (HttpStreamFactory::spdy_enabled()) {
243 EXPECT_EQ(
244 HttpResponseInfo::ConnectionInfoFromNextProto(
245 test_params_.protocol),
246 response->connection_info);
247 } else {
248 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1,
249 response->connection_info);
251 if (test_params_.ssl_type == SPDYNPN && spdy_enabled_) {
252 EXPECT_TRUE(response->was_npn_negotiated);
253 } else {
254 EXPECT_TRUE(!response->was_npn_negotiated);
256 // If SPDY is not enabled, a HTTP request should not be diverted
257 // over a SSL session.
258 if (!spdy_enabled_) {
259 EXPECT_EQ(request_.url.SchemeIs("https"),
260 response->was_npn_negotiated);
262 EXPECT_EQ("127.0.0.1", response->socket_address.host());
263 EXPECT_EQ(port_, response->socket_address.port());
264 output_.status_line = response->headers->GetStatusLine();
265 output_.response_info = *response; // Make a copy so we can verify.
266 output_.rv = ReadTransaction(trans_.get(), &output_.response_data);
269 void FinishDefaultTestWithoutVerification() {
270 output_.rv = callback_.WaitForResult();
271 if (output_.rv != OK)
272 session_->spdy_session_pool()->CloseCurrentSessions(ERR_ABORTED);
275 // Most tests will want to call this function. In particular, the MockReads
276 // should end with an empty read, and that read needs to be processed to
277 // ensure proper deletion of the spdy_session_pool.
278 void VerifyDataConsumed() {
279 for (DataVector::iterator it = data_vector_.begin();
280 it != data_vector_.end(); ++it) {
281 EXPECT_TRUE((*it)->at_read_eof()) << "Read count: "
282 << (*it)->read_count()
283 << " Read index: "
284 << (*it)->read_index();
285 EXPECT_TRUE((*it)->at_write_eof()) << "Write count: "
286 << (*it)->write_count()
287 << " Write index: "
288 << (*it)->write_index();
292 // Occasionally a test will expect to error out before certain reads are
293 // processed. In that case we want to explicitly ensure that the reads were
294 // not processed.
295 void VerifyDataNotConsumed() {
296 for (DataVector::iterator it = data_vector_.begin();
297 it != data_vector_.end(); ++it) {
298 EXPECT_TRUE(!(*it)->at_read_eof()) << "Read count: "
299 << (*it)->read_count()
300 << " Read index: "
301 << (*it)->read_index();
302 EXPECT_TRUE(!(*it)->at_write_eof()) << "Write count: "
303 << (*it)->write_count()
304 << " Write index: "
305 << (*it)->write_index();
309 void RunToCompletion(StaticSocketDataProvider* data) {
310 RunPreTestSetup();
311 AddData(data);
312 RunDefaultTest();
313 VerifyDataConsumed();
316 void RunToCompletionWithSSLData(
317 StaticSocketDataProvider* data,
318 scoped_ptr<SSLSocketDataProvider> ssl_provider) {
319 RunPreTestSetup();
320 AddDataWithSSLSocketDataProvider(data, ssl_provider.Pass());
321 RunDefaultTest();
322 VerifyDataConsumed();
325 void AddData(StaticSocketDataProvider* data) {
326 scoped_ptr<SSLSocketDataProvider> ssl_provider(
327 new SSLSocketDataProvider(ASYNC, OK));
328 AddDataWithSSLSocketDataProvider(data, ssl_provider.Pass());
331 void AddDataWithSSLSocketDataProvider(
332 StaticSocketDataProvider* data,
333 scoped_ptr<SSLSocketDataProvider> ssl_provider) {
334 DCHECK(!deterministic_);
335 data_vector_.push_back(data);
336 if (test_params_.ssl_type == SPDYNPN)
337 ssl_provider->SetNextProto(test_params_.protocol);
339 if (test_params_.ssl_type == SPDYNPN ||
340 test_params_.ssl_type == SPDYSSL) {
341 session_deps_->socket_factory->AddSSLSocketDataProvider(
342 ssl_provider.get());
344 ssl_vector_.push_back(ssl_provider.release());
346 session_deps_->socket_factory->AddSocketDataProvider(data);
347 if (test_params_.ssl_type == SPDYNPN) {
348 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
349 StaticSocketDataProvider* hanging_non_alternate_protocol_socket =
350 new StaticSocketDataProvider(NULL, 0, NULL, 0);
351 hanging_non_alternate_protocol_socket->set_connect_data(
352 never_finishing_connect);
353 session_deps_->socket_factory->AddSocketDataProvider(
354 hanging_non_alternate_protocol_socket);
355 alternate_vector_.push_back(hanging_non_alternate_protocol_socket);
359 void AddDeterministicData(DeterministicSocketData* data) {
360 DCHECK(deterministic_);
361 data_vector_.push_back(data);
362 SSLSocketDataProvider* ssl_provider =
363 new SSLSocketDataProvider(ASYNC, OK);
364 if (test_params_.ssl_type == SPDYNPN)
365 ssl_provider->SetNextProto(test_params_.protocol);
367 ssl_vector_.push_back(ssl_provider);
368 if (test_params_.ssl_type == SPDYNPN ||
369 test_params_.ssl_type == SPDYSSL) {
370 session_deps_->deterministic_socket_factory->
371 AddSSLSocketDataProvider(ssl_provider);
373 session_deps_->deterministic_socket_factory->AddSocketDataProvider(data);
374 if (test_params_.ssl_type == SPDYNPN) {
375 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
376 DeterministicSocketData* hanging_non_alternate_protocol_socket =
377 new DeterministicSocketData(NULL, 0, NULL, 0);
378 hanging_non_alternate_protocol_socket->set_connect_data(
379 never_finishing_connect);
380 session_deps_->deterministic_socket_factory->AddSocketDataProvider(
381 hanging_non_alternate_protocol_socket);
382 alternate_deterministic_vector_.push_back(
383 hanging_non_alternate_protocol_socket);
387 void SetSession(const scoped_refptr<HttpNetworkSession>& session) {
388 session_ = session;
390 HttpNetworkTransaction* trans() { return trans_.get(); }
391 void ResetTrans() { trans_.reset(); }
392 TransactionHelperResult& output() { return output_; }
393 const HttpRequestInfo& request() const { return request_; }
394 const scoped_refptr<HttpNetworkSession>& session() const {
395 return session_;
397 scoped_ptr<SpdySessionDependencies>& session_deps() {
398 return session_deps_;
400 int port() const { return port_; }
401 SpdyNetworkTransactionTestParams test_params() const {
402 return test_params_;
405 private:
406 typedef std::vector<StaticSocketDataProvider*> DataVector;
407 typedef ScopedVector<SSLSocketDataProvider> SSLVector;
408 typedef ScopedVector<StaticSocketDataProvider> AlternateVector;
409 typedef ScopedVector<DeterministicSocketData> AlternateDeterministicVector;
410 HttpRequestInfo request_;
411 RequestPriority priority_;
412 scoped_ptr<SpdySessionDependencies> session_deps_;
413 scoped_refptr<HttpNetworkSession> session_;
414 TransactionHelperResult output_;
415 scoped_ptr<StaticSocketDataProvider> first_transaction_;
416 SSLVector ssl_vector_;
417 TestCompletionCallback callback_;
418 scoped_ptr<HttpNetworkTransaction> trans_;
419 scoped_ptr<HttpNetworkTransaction> trans_http_;
420 DataVector data_vector_;
421 AlternateVector alternate_vector_;
422 AlternateDeterministicVector alternate_deterministic_vector_;
423 const BoundNetLog log_;
424 SpdyNetworkTransactionTestParams test_params_;
425 int port_;
426 bool deterministic_;
427 bool spdy_enabled_;
430 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
431 int expected_status);
433 void ConnectStatusHelper(const MockRead& status);
435 const HttpRequestInfo& CreateGetPushRequest() {
436 google_get_push_request_.method = "GET";
437 google_get_push_request_.url = GURL("http://www.google.com/foo.dat");
438 google_get_push_request_.load_flags = 0;
439 return google_get_push_request_;
442 const HttpRequestInfo& CreateGetRequest() {
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_initialized_ = true;
449 return google_get_request_;
452 const HttpRequestInfo& CreateGetRequestWithUserAgent() {
453 if (!google_get_request_initialized_) {
454 google_get_request_.method = "GET";
455 google_get_request_.url = GURL(kDefaultURL);
456 google_get_request_.load_flags = 0;
457 google_get_request_.extra_headers.SetHeader("User-Agent", "Chrome");
458 google_get_request_initialized_ = true;
460 return google_get_request_;
463 const HttpRequestInfo& CreatePostRequest() {
464 if (!google_post_request_initialized_) {
465 ScopedVector<UploadElementReader> element_readers;
466 element_readers.push_back(
467 new UploadBytesElementReader(kUploadData, kUploadDataSize));
468 upload_data_stream_.reset(
469 new ElementsUploadDataStream(element_readers.Pass(), 0));
471 google_post_request_.method = "POST";
472 google_post_request_.url = GURL(kDefaultURL);
473 google_post_request_.upload_data_stream = upload_data_stream_.get();
474 google_post_request_initialized_ = true;
476 return google_post_request_;
479 const HttpRequestInfo& CreateFilePostRequest() {
480 if (!google_post_request_initialized_) {
481 base::FilePath file_path;
482 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
483 CHECK_EQ(static_cast<int>(kUploadDataSize),
484 base::WriteFile(file_path, kUploadData, kUploadDataSize));
486 ScopedVector<UploadElementReader> element_readers;
487 element_readers.push_back(
488 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
489 file_path,
491 kUploadDataSize,
492 base::Time()));
493 upload_data_stream_.reset(
494 new ElementsUploadDataStream(element_readers.Pass(), 0));
496 google_post_request_.method = "POST";
497 google_post_request_.url = GURL(kDefaultURL);
498 google_post_request_.upload_data_stream = upload_data_stream_.get();
499 google_post_request_initialized_ = true;
501 return google_post_request_;
504 const HttpRequestInfo& CreateUnreadableFilePostRequest() {
505 if (google_post_request_initialized_)
506 return google_post_request_;
508 base::FilePath file_path;
509 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
510 CHECK_EQ(static_cast<int>(kUploadDataSize),
511 base::WriteFile(file_path, kUploadData, kUploadDataSize));
512 CHECK(base::MakeFileUnreadable(file_path));
514 ScopedVector<UploadElementReader> element_readers;
515 element_readers.push_back(
516 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
517 file_path,
519 kUploadDataSize,
520 base::Time()));
521 upload_data_stream_.reset(
522 new ElementsUploadDataStream(element_readers.Pass(), 0));
524 google_post_request_.method = "POST";
525 google_post_request_.url = GURL(kDefaultURL);
526 google_post_request_.upload_data_stream = upload_data_stream_.get();
527 google_post_request_initialized_ = true;
528 return google_post_request_;
531 const HttpRequestInfo& CreateComplexPostRequest() {
532 if (!google_post_request_initialized_) {
533 const int kFileRangeOffset = 1;
534 const int kFileRangeLength = 3;
535 CHECK_LT(kFileRangeOffset + kFileRangeLength, kUploadDataSize);
537 base::FilePath file_path;
538 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
539 CHECK_EQ(static_cast<int>(kUploadDataSize),
540 base::WriteFile(file_path, kUploadData, kUploadDataSize));
542 ScopedVector<UploadElementReader> element_readers;
543 element_readers.push_back(
544 new UploadBytesElementReader(kUploadData, kFileRangeOffset));
545 element_readers.push_back(
546 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
547 file_path,
548 kFileRangeOffset,
549 kFileRangeLength,
550 base::Time()));
551 element_readers.push_back(new UploadBytesElementReader(
552 kUploadData + kFileRangeOffset + kFileRangeLength,
553 kUploadDataSize - (kFileRangeOffset + kFileRangeLength)));
554 upload_data_stream_.reset(
555 new ElementsUploadDataStream(element_readers.Pass(), 0));
557 google_post_request_.method = "POST";
558 google_post_request_.url = GURL(kDefaultURL);
559 google_post_request_.upload_data_stream = upload_data_stream_.get();
560 google_post_request_initialized_ = true;
562 return google_post_request_;
565 const HttpRequestInfo& CreateChunkedPostRequest() {
566 if (!google_chunked_post_request_initialized_) {
567 upload_chunked_data_stream_.reset(new ChunkedUploadDataStream(0));
568 google_chunked_post_request_.method = "POST";
569 google_chunked_post_request_.url = GURL(kDefaultURL);
570 google_chunked_post_request_.upload_data_stream =
571 upload_chunked_data_stream_.get();
572 google_chunked_post_request_initialized_ = true;
574 return google_chunked_post_request_;
577 // Read the result of a particular transaction, knowing that we've got
578 // multiple transactions in the read pipeline; so as we read, we may have
579 // to skip over data destined for other transactions while we consume
580 // the data for |trans|.
581 int ReadResult(HttpNetworkTransaction* trans,
582 StaticSocketDataProvider* data,
583 std::string* result) {
584 const int kSize = 3000;
586 int bytes_read = 0;
587 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(kSize));
588 TestCompletionCallback callback;
589 while (true) {
590 int rv = trans->Read(buf.get(), kSize, callback.callback());
591 if (rv == ERR_IO_PENDING) {
592 // Multiple transactions may be in the data set. Keep pulling off
593 // reads until we complete our callback.
594 while (!callback.have_result()) {
595 data->CompleteRead();
596 base::RunLoop().RunUntilIdle();
598 rv = callback.WaitForResult();
599 } else if (rv <= 0) {
600 break;
602 result->append(buf->data(), rv);
603 bytes_read += rv;
605 return bytes_read;
608 void VerifyStreamsClosed(const NormalSpdyTransactionHelper& helper) {
609 // This lengthy block is reaching into the pool to dig out the active
610 // session. Once we have the session, we verify that the streams are
611 // all closed and not leaked at this point.
612 const GURL& url = helper.request().url;
613 int port = helper.test_params().ssl_type == SPDYNPN ? 443 : 80;
614 HostPortPair host_port_pair(url.host(), port);
615 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
616 PRIVACY_MODE_DISABLED);
617 BoundNetLog log;
618 const scoped_refptr<HttpNetworkSession>& session = helper.session();
619 base::WeakPtr<SpdySession> spdy_session =
620 session->spdy_session_pool()->FindAvailableSession(key, log);
621 ASSERT_TRUE(spdy_session != NULL);
622 EXPECT_EQ(0u, spdy_session->num_active_streams());
623 EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams());
626 void RunServerPushTest(OrderedSocketData* data,
627 HttpResponseInfo* response,
628 HttpResponseInfo* push_response,
629 const std::string& expected) {
630 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
631 BoundNetLog(), GetParam(), NULL);
632 helper.RunPreTestSetup();
633 helper.AddData(data);
635 HttpNetworkTransaction* trans = helper.trans();
637 // Start the transaction with basic parameters.
638 TestCompletionCallback callback;
639 int rv = trans->Start(
640 &CreateGetRequest(), callback.callback(), BoundNetLog());
641 EXPECT_EQ(ERR_IO_PENDING, rv);
642 rv = callback.WaitForResult();
644 // Request the pushed path.
645 scoped_ptr<HttpNetworkTransaction> trans2(
646 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
647 rv = trans2->Start(
648 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
649 EXPECT_EQ(ERR_IO_PENDING, rv);
650 base::RunLoop().RunUntilIdle();
652 // The data for the pushed path may be coming in more than 1 frame. Compile
653 // the results into a single string.
655 // Read the server push body.
656 std::string result2;
657 ReadResult(trans2.get(), data, &result2);
658 // Read the response body.
659 std::string result;
660 ReadResult(trans, data, &result);
662 // Verify that we consumed all test data.
663 EXPECT_TRUE(data->at_read_eof());
664 EXPECT_TRUE(data->at_write_eof());
666 // Verify that the received push data is same as the expected push data.
667 EXPECT_EQ(result2.compare(expected), 0) << "Received data: "
668 << result2
669 << "||||| Expected data: "
670 << expected;
672 // Verify the SYN_REPLY.
673 // Copy the response info, because trans goes away.
674 *response = *trans->GetResponseInfo();
675 *push_response = *trans2->GetResponseInfo();
677 VerifyStreamsClosed(helper);
680 static void DeleteSessionCallback(NormalSpdyTransactionHelper* helper,
681 int result) {
682 helper->ResetTrans();
685 static void StartTransactionCallback(
686 const scoped_refptr<HttpNetworkSession>& session,
687 int result) {
688 scoped_ptr<HttpNetworkTransaction> trans(
689 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
690 TestCompletionCallback callback;
691 HttpRequestInfo request;
692 request.method = "GET";
693 request.url = GURL("http://www.google.com/");
694 request.load_flags = 0;
695 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
696 EXPECT_EQ(ERR_IO_PENDING, rv);
697 callback.WaitForResult();
700 ChunkedUploadDataStream* upload_chunked_data_stream() const {
701 return upload_chunked_data_stream_.get();
704 SpdyTestUtil spdy_util_;
706 private:
707 scoped_ptr<ChunkedUploadDataStream> upload_chunked_data_stream_;
708 scoped_ptr<UploadDataStream> upload_data_stream_;
709 bool google_get_request_initialized_;
710 bool google_post_request_initialized_;
711 bool google_chunked_post_request_initialized_;
712 HttpRequestInfo google_get_request_;
713 HttpRequestInfo google_post_request_;
714 HttpRequestInfo google_chunked_post_request_;
715 HttpRequestInfo google_get_push_request_;
716 base::ScopedTempDir temp_dir_;
719 //-----------------------------------------------------------------------------
720 // All tests are run with three different connection types: SPDY after NPN
721 // negotiation, SPDY without SSL, and SPDY with SSL.
723 // TODO(akalin): Use ::testing::Combine() when we are able to use
724 // <tr1/tuple>.
725 INSTANTIATE_TEST_CASE_P(
726 Spdy,
727 SpdyNetworkTransactionTest,
728 ::testing::Values(
729 SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNOSSL),
730 SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYSSL),
731 SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNPN),
732 SpdyNetworkTransactionTestParams(kProtoSPDY4_14, SPDYNOSSL),
733 SpdyNetworkTransactionTestParams(kProtoSPDY4_14, SPDYSSL),
734 SpdyNetworkTransactionTestParams(kProtoSPDY4_14, SPDYNPN),
735 SpdyNetworkTransactionTestParams(kProtoSPDY4, SPDYNOSSL),
736 SpdyNetworkTransactionTestParams(kProtoSPDY4, SPDYSSL),
737 SpdyNetworkTransactionTestParams(kProtoSPDY4, SPDYNPN)));
739 // Verify HttpNetworkTransaction constructor.
740 TEST_P(SpdyNetworkTransactionTest, Constructor) {
741 scoped_ptr<SpdySessionDependencies> session_deps(
742 CreateSpdySessionDependencies(GetParam()));
743 scoped_refptr<HttpNetworkSession> session(
744 SpdySessionDependencies::SpdyCreateSession(session_deps.get()));
745 scoped_ptr<HttpTransaction> trans(
746 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
749 TEST_P(SpdyNetworkTransactionTest, Get) {
750 // Construct the request.
751 scoped_ptr<SpdyFrame> req(
752 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
753 MockWrite writes[] = { CreateMockWrite(*req) };
755 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
756 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
757 MockRead reads[] = {
758 CreateMockRead(*resp),
759 CreateMockRead(*body),
760 MockRead(ASYNC, 0, 0) // EOF
763 DelayedSocketData data(1, reads, arraysize(reads),
764 writes, arraysize(writes));
765 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
766 BoundNetLog(), GetParam(), NULL);
767 helper.RunToCompletion(&data);
768 TransactionHelperResult out = helper.output();
769 EXPECT_EQ(OK, out.rv);
770 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
771 EXPECT_EQ("hello!", out.response_data);
774 TEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) {
775 for (RequestPriority p = MINIMUM_PRIORITY; p <= MAXIMUM_PRIORITY;
776 p = RequestPriority(p + 1)) {
777 // Construct the request.
778 scoped_ptr<SpdyFrame> req(
779 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, p, true));
780 MockWrite writes[] = { CreateMockWrite(*req) };
782 SpdyPriority spdy_prio = 0;
783 EXPECT_TRUE(GetSpdyPriority(spdy_util_.spdy_version(), *req, &spdy_prio));
784 // this repeats the RequestPriority-->SpdyPriority mapping from
785 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
786 // sure it's being done right.
787 if (spdy_util_.spdy_version() < SPDY3) {
788 switch (p) {
789 case HIGHEST:
790 EXPECT_EQ(0, spdy_prio);
791 break;
792 case MEDIUM:
793 EXPECT_EQ(1, spdy_prio);
794 break;
795 case LOW:
796 case LOWEST:
797 EXPECT_EQ(2, spdy_prio);
798 break;
799 case IDLE:
800 EXPECT_EQ(3, spdy_prio);
801 break;
802 default:
803 FAIL();
805 } else {
806 switch(p) {
807 case HIGHEST:
808 EXPECT_EQ(0, spdy_prio);
809 break;
810 case MEDIUM:
811 EXPECT_EQ(1, spdy_prio);
812 break;
813 case LOW:
814 EXPECT_EQ(2, spdy_prio);
815 break;
816 case LOWEST:
817 EXPECT_EQ(3, spdy_prio);
818 break;
819 case IDLE:
820 EXPECT_EQ(4, spdy_prio);
821 break;
822 default:
823 FAIL();
827 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
828 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
829 MockRead reads[] = {
830 CreateMockRead(*resp),
831 CreateMockRead(*body),
832 MockRead(ASYNC, 0, 0) // EOF
835 DelayedSocketData data(1, reads, arraysize(reads),
836 writes, arraysize(writes));
837 HttpRequestInfo http_req = CreateGetRequest();
839 NormalSpdyTransactionHelper helper(http_req, p, BoundNetLog(),
840 GetParam(), NULL);
841 helper.RunToCompletion(&data);
842 TransactionHelperResult out = helper.output();
843 EXPECT_EQ(OK, out.rv);
844 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
845 EXPECT_EQ("hello!", out.response_data);
849 // Start three gets simultaniously; making sure that multiplexed
850 // streams work properly.
852 // This can't use the TransactionHelper method, since it only
853 // handles a single transaction, and finishes them as soon
854 // as it launches them.
856 // TODO(gavinp): create a working generalized TransactionHelper that
857 // can allow multiple streams in flight.
859 TEST_P(SpdyNetworkTransactionTest, ThreeGets) {
860 scoped_ptr<SpdyFrame> req(
861 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
862 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
863 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
864 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
866 scoped_ptr<SpdyFrame> req2(
867 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
868 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
869 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
870 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
872 scoped_ptr<SpdyFrame> req3(
873 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
874 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
875 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
876 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
878 MockWrite writes[] = {
879 CreateMockWrite(*req),
880 CreateMockWrite(*req2),
881 CreateMockWrite(*req3),
883 MockRead reads[] = {
884 CreateMockRead(*resp, 1),
885 CreateMockRead(*body),
886 CreateMockRead(*resp2, 4),
887 CreateMockRead(*body2),
888 CreateMockRead(*resp3, 7),
889 CreateMockRead(*body3),
891 CreateMockRead(*fbody),
892 CreateMockRead(*fbody2),
893 CreateMockRead(*fbody3),
895 MockRead(ASYNC, 0, 0), // EOF
897 OrderedSocketData data(reads, arraysize(reads),
898 writes, arraysize(writes));
899 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
901 BoundNetLog log;
902 TransactionHelperResult out;
903 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
904 BoundNetLog(), GetParam(), NULL);
905 helper.RunPreTestSetup();
906 helper.AddData(&data);
907 // We require placeholder data because three get requests are sent out, so
908 // there needs to be three sets of SSL connection data.
909 helper.AddData(&data_placeholder);
910 helper.AddData(&data_placeholder);
911 scoped_ptr<HttpNetworkTransaction> trans1(
912 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
913 scoped_ptr<HttpNetworkTransaction> trans2(
914 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
915 scoped_ptr<HttpNetworkTransaction> trans3(
916 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
918 TestCompletionCallback callback1;
919 TestCompletionCallback callback2;
920 TestCompletionCallback callback3;
922 HttpRequestInfo httpreq1 = CreateGetRequest();
923 HttpRequestInfo httpreq2 = CreateGetRequest();
924 HttpRequestInfo httpreq3 = CreateGetRequest();
926 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
927 ASSERT_EQ(ERR_IO_PENDING, out.rv);
928 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
929 ASSERT_EQ(ERR_IO_PENDING, out.rv);
930 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
931 ASSERT_EQ(ERR_IO_PENDING, out.rv);
933 out.rv = callback1.WaitForResult();
934 ASSERT_EQ(OK, out.rv);
935 out.rv = callback3.WaitForResult();
936 ASSERT_EQ(OK, out.rv);
938 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
939 EXPECT_TRUE(response1->headers.get() != NULL);
940 EXPECT_TRUE(response1->was_fetched_via_spdy);
941 out.status_line = response1->headers->GetStatusLine();
942 out.response_info = *response1;
944 trans2->GetResponseInfo();
946 out.rv = ReadTransaction(trans1.get(), &out.response_data);
947 helper.VerifyDataConsumed();
948 EXPECT_EQ(OK, out.rv);
950 EXPECT_EQ(OK, out.rv);
951 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
952 EXPECT_EQ("hello!hello!", out.response_data);
955 TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
956 scoped_ptr<SpdyFrame> req(
957 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
958 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
959 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
960 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
962 scoped_ptr<SpdyFrame> req2(
963 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
964 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
965 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
966 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
968 MockWrite writes[] = {
969 CreateMockWrite(*req),
970 CreateMockWrite(*req2),
972 MockRead reads[] = {
973 CreateMockRead(*resp, 1),
974 CreateMockRead(*body),
975 CreateMockRead(*resp2, 4),
976 CreateMockRead(*body2),
977 CreateMockRead(*fbody),
978 CreateMockRead(*fbody2),
979 MockRead(ASYNC, 0, 0), // EOF
981 OrderedSocketData data(reads, arraysize(reads),
982 writes, arraysize(writes));
984 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
986 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
987 data_placeholder.set_connect_data(never_finishing_connect);
989 BoundNetLog log;
990 TransactionHelperResult out;
991 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
992 BoundNetLog(), GetParam(), NULL);
993 helper.RunPreTestSetup();
994 helper.AddData(&data);
995 // We require placeholder data because two get requests are sent out, so
996 // there needs to be two sets of SSL connection data.
997 helper.AddData(&data_placeholder);
998 scoped_ptr<HttpNetworkTransaction> trans1(
999 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1000 scoped_ptr<HttpNetworkTransaction> trans2(
1001 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1003 TestCompletionCallback callback1;
1004 TestCompletionCallback callback2;
1006 HttpRequestInfo httpreq1 = CreateGetRequest();
1007 HttpRequestInfo httpreq2 = CreateGetRequest();
1009 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1010 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1011 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1012 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1014 out.rv = callback1.WaitForResult();
1015 ASSERT_EQ(OK, out.rv);
1016 out.rv = callback2.WaitForResult();
1017 ASSERT_EQ(OK, out.rv);
1019 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1020 EXPECT_TRUE(response1->headers.get() != NULL);
1021 EXPECT_TRUE(response1->was_fetched_via_spdy);
1022 out.status_line = response1->headers->GetStatusLine();
1023 out.response_info = *response1;
1024 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1025 EXPECT_EQ(OK, out.rv);
1026 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1027 EXPECT_EQ("hello!hello!", out.response_data);
1029 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1030 EXPECT_TRUE(response2->headers.get() != NULL);
1031 EXPECT_TRUE(response2->was_fetched_via_spdy);
1032 out.status_line = response2->headers->GetStatusLine();
1033 out.response_info = *response2;
1034 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1035 EXPECT_EQ(OK, out.rv);
1036 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1037 EXPECT_EQ("hello!hello!", out.response_data);
1039 helper.VerifyDataConsumed();
1042 TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
1043 scoped_ptr<SpdyFrame> req(
1044 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1045 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1046 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1047 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
1049 scoped_ptr<SpdyFrame> req2(
1050 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1051 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1052 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1053 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1055 MockWrite writes[] = {
1056 CreateMockWrite(*req),
1057 CreateMockWrite(*req2),
1059 MockRead reads[] = {
1060 CreateMockRead(*resp, 1),
1061 CreateMockRead(*body),
1062 CreateMockRead(*resp2, 4),
1063 CreateMockRead(*body2),
1064 CreateMockRead(*fbody),
1065 CreateMockRead(*fbody2),
1066 MockRead(ASYNC, 0, 0), // EOF
1068 OrderedSocketData preconnect_data(reads, arraysize(reads),
1069 writes, arraysize(writes));
1071 MockConnect never_finishing_connect(ASYNC, ERR_IO_PENDING);
1073 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1074 data_placeholder.set_connect_data(never_finishing_connect);
1076 BoundNetLog log;
1077 TransactionHelperResult out;
1078 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1079 BoundNetLog(), GetParam(), NULL);
1080 helper.RunPreTestSetup();
1081 helper.AddData(&preconnect_data);
1082 // We require placeholder data because 3 connections are attempted (first is
1083 // the preconnect, 2nd and 3rd are the never finished connections.
1084 helper.AddData(&data_placeholder);
1085 helper.AddData(&data_placeholder);
1087 scoped_ptr<HttpNetworkTransaction> trans1(
1088 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1089 scoped_ptr<HttpNetworkTransaction> trans2(
1090 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1092 TestCompletionCallback callback1;
1093 TestCompletionCallback callback2;
1095 HttpRequestInfo httpreq = CreateGetRequest();
1097 // Preconnect the first.
1098 SSLConfig preconnect_ssl_config;
1099 helper.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config);
1100 HttpStreamFactory* http_stream_factory =
1101 helper.session()->http_stream_factory();
1102 helper.session()->GetNextProtos(&preconnect_ssl_config.next_protos);
1104 http_stream_factory->PreconnectStreams(
1105 1, httpreq, DEFAULT_PRIORITY,
1106 preconnect_ssl_config, preconnect_ssl_config);
1108 out.rv = trans1->Start(&httpreq, callback1.callback(), log);
1109 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1110 out.rv = trans2->Start(&httpreq, callback2.callback(), log);
1111 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1113 out.rv = callback1.WaitForResult();
1114 ASSERT_EQ(OK, out.rv);
1115 out.rv = callback2.WaitForResult();
1116 ASSERT_EQ(OK, out.rv);
1118 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1119 EXPECT_TRUE(response1->headers.get() != NULL);
1120 EXPECT_TRUE(response1->was_fetched_via_spdy);
1121 out.status_line = response1->headers->GetStatusLine();
1122 out.response_info = *response1;
1123 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1124 EXPECT_EQ(OK, out.rv);
1125 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1126 EXPECT_EQ("hello!hello!", out.response_data);
1128 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1129 EXPECT_TRUE(response2->headers.get() != NULL);
1130 EXPECT_TRUE(response2->was_fetched_via_spdy);
1131 out.status_line = response2->headers->GetStatusLine();
1132 out.response_info = *response2;
1133 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1134 EXPECT_EQ(OK, out.rv);
1135 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1136 EXPECT_EQ("hello!hello!", out.response_data);
1138 helper.VerifyDataConsumed();
1141 // Similar to ThreeGets above, however this test adds a SETTINGS
1142 // frame. The SETTINGS frame is read during the IO loop waiting on
1143 // the first transaction completion, and sets a maximum concurrent
1144 // stream limit of 1. This means that our IO loop exists after the
1145 // second transaction completes, so we can assert on read_index().
1146 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
1147 // Construct the request.
1148 scoped_ptr<SpdyFrame> req(
1149 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1150 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1151 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1152 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
1154 scoped_ptr<SpdyFrame> req2(
1155 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1156 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1157 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1158 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1160 scoped_ptr<SpdyFrame> req3(
1161 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
1162 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
1163 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
1164 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
1166 SettingsMap settings;
1167 const uint32 max_concurrent_streams = 1;
1168 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1169 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1170 scoped_ptr<SpdyFrame> settings_frame(
1171 spdy_util_.ConstructSpdySettings(settings));
1172 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1174 MockWrite writes[] = {
1175 CreateMockWrite(*req),
1176 CreateMockWrite(*settings_ack, 2),
1177 CreateMockWrite(*req2),
1178 CreateMockWrite(*req3),
1181 MockRead reads[] = {
1182 CreateMockRead(*settings_frame, 1),
1183 CreateMockRead(*resp),
1184 CreateMockRead(*body),
1185 CreateMockRead(*fbody),
1186 CreateMockRead(*resp2, 8),
1187 CreateMockRead(*body2),
1188 CreateMockRead(*fbody2),
1189 CreateMockRead(*resp3, 13),
1190 CreateMockRead(*body3),
1191 CreateMockRead(*fbody3),
1193 MockRead(ASYNC, 0, 0), // EOF
1196 OrderedSocketData data(reads, arraysize(reads),
1197 writes, arraysize(writes));
1198 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1200 BoundNetLog log;
1201 TransactionHelperResult out;
1203 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1204 BoundNetLog(), GetParam(), NULL);
1205 helper.RunPreTestSetup();
1206 helper.AddData(&data);
1207 // We require placeholder data because three get requests are sent out, so
1208 // there needs to be three sets of SSL connection data.
1209 helper.AddData(&data_placeholder);
1210 helper.AddData(&data_placeholder);
1211 scoped_ptr<HttpNetworkTransaction> trans1(
1212 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1213 scoped_ptr<HttpNetworkTransaction> trans2(
1214 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1215 scoped_ptr<HttpNetworkTransaction> trans3(
1216 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1218 TestCompletionCallback callback1;
1219 TestCompletionCallback callback2;
1220 TestCompletionCallback callback3;
1222 HttpRequestInfo httpreq1 = CreateGetRequest();
1223 HttpRequestInfo httpreq2 = CreateGetRequest();
1224 HttpRequestInfo httpreq3 = CreateGetRequest();
1226 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1227 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1228 // Run transaction 1 through quickly to force a read of our SETTINGS
1229 // frame.
1230 out.rv = callback1.WaitForResult();
1231 ASSERT_EQ(OK, out.rv);
1233 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1234 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1235 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1236 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1237 out.rv = callback2.WaitForResult();
1238 ASSERT_EQ(OK, out.rv);
1239 EXPECT_EQ(7U, data.read_index()); // i.e. the third trans was queued
1241 out.rv = callback3.WaitForResult();
1242 ASSERT_EQ(OK, out.rv);
1244 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1245 ASSERT_TRUE(response1 != NULL);
1246 EXPECT_TRUE(response1->headers.get() != NULL);
1247 EXPECT_TRUE(response1->was_fetched_via_spdy);
1248 out.status_line = response1->headers->GetStatusLine();
1249 out.response_info = *response1;
1250 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1251 EXPECT_EQ(OK, out.rv);
1252 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1253 EXPECT_EQ("hello!hello!", out.response_data);
1255 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1256 out.status_line = response2->headers->GetStatusLine();
1257 out.response_info = *response2;
1258 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1259 EXPECT_EQ(OK, out.rv);
1260 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1261 EXPECT_EQ("hello!hello!", out.response_data);
1263 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1264 out.status_line = response3->headers->GetStatusLine();
1265 out.response_info = *response3;
1266 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1267 EXPECT_EQ(OK, out.rv);
1268 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1269 EXPECT_EQ("hello!hello!", out.response_data);
1271 helper.VerifyDataConsumed();
1273 EXPECT_EQ(OK, out.rv);
1276 // Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1277 // a fourth transaction. The third and fourth transactions have
1278 // different data ("hello!" vs "hello!hello!") and because of the
1279 // user specified priority, we expect to see them inverted in
1280 // the response from the server.
1281 TEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
1282 // Construct the request.
1283 scoped_ptr<SpdyFrame> req(
1284 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1285 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1286 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1287 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
1289 scoped_ptr<SpdyFrame> req2(
1290 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1291 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1292 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1293 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1295 scoped_ptr<SpdyFrame> req4(
1296 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, HIGHEST, true));
1297 scoped_ptr<SpdyFrame> resp4(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
1298 scoped_ptr<SpdyFrame> fbody4(spdy_util_.ConstructSpdyBodyFrame(5, true));
1300 scoped_ptr<SpdyFrame> req3(
1301 spdy_util_.ConstructSpdyGet(NULL, 0, false, 7, LOWEST, true));
1302 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 7));
1303 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(7, false));
1304 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(7, true));
1306 SettingsMap settings;
1307 const uint32 max_concurrent_streams = 1;
1308 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1309 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1310 scoped_ptr<SpdyFrame> settings_frame(
1311 spdy_util_.ConstructSpdySettings(settings));
1312 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1314 MockWrite writes[] = { CreateMockWrite(*req),
1315 CreateMockWrite(*settings_ack, 2),
1316 CreateMockWrite(*req2),
1317 CreateMockWrite(*req4),
1318 CreateMockWrite(*req3),
1320 MockRead reads[] = {
1321 CreateMockRead(*settings_frame, 1),
1322 CreateMockRead(*resp),
1323 CreateMockRead(*body),
1324 CreateMockRead(*fbody),
1325 CreateMockRead(*resp2, 8),
1326 CreateMockRead(*body2),
1327 CreateMockRead(*fbody2),
1328 CreateMockRead(*resp4, 14),
1329 CreateMockRead(*fbody4),
1330 CreateMockRead(*resp3, 17),
1331 CreateMockRead(*body3),
1332 CreateMockRead(*fbody3),
1334 MockRead(ASYNC, 0, 0), // EOF
1337 OrderedSocketData data(reads, arraysize(reads),
1338 writes, arraysize(writes));
1339 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1341 BoundNetLog log;
1342 TransactionHelperResult out;
1343 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1344 BoundNetLog(), GetParam(), NULL);
1345 helper.RunPreTestSetup();
1346 helper.AddData(&data);
1347 // We require placeholder data because four get requests are sent out, so
1348 // there needs to be four sets of SSL connection data.
1349 helper.AddData(&data_placeholder);
1350 helper.AddData(&data_placeholder);
1351 helper.AddData(&data_placeholder);
1352 scoped_ptr<HttpNetworkTransaction> trans1(
1353 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1354 scoped_ptr<HttpNetworkTransaction> trans2(
1355 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1356 scoped_ptr<HttpNetworkTransaction> trans3(
1357 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1358 scoped_ptr<HttpNetworkTransaction> trans4(
1359 new HttpNetworkTransaction(HIGHEST, helper.session().get()));
1361 TestCompletionCallback callback1;
1362 TestCompletionCallback callback2;
1363 TestCompletionCallback callback3;
1364 TestCompletionCallback callback4;
1366 HttpRequestInfo httpreq1 = CreateGetRequest();
1367 HttpRequestInfo httpreq2 = CreateGetRequest();
1368 HttpRequestInfo httpreq3 = CreateGetRequest();
1369 HttpRequestInfo httpreq4 = CreateGetRequest();
1371 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1372 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1373 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1374 out.rv = callback1.WaitForResult();
1375 ASSERT_EQ(OK, out.rv);
1377 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1378 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1379 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1380 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1381 out.rv = trans4->Start(&httpreq4, callback4.callback(), log);
1382 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1384 out.rv = callback2.WaitForResult();
1385 ASSERT_EQ(OK, out.rv);
1386 EXPECT_EQ(data.read_index(), 7U); // i.e. the third & fourth trans queued
1388 out.rv = callback3.WaitForResult();
1389 ASSERT_EQ(OK, out.rv);
1391 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1392 EXPECT_TRUE(response1->headers.get() != NULL);
1393 EXPECT_TRUE(response1->was_fetched_via_spdy);
1394 out.status_line = response1->headers->GetStatusLine();
1395 out.response_info = *response1;
1396 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1397 EXPECT_EQ(OK, out.rv);
1398 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1399 EXPECT_EQ("hello!hello!", out.response_data);
1401 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1402 out.status_line = response2->headers->GetStatusLine();
1403 out.response_info = *response2;
1404 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1405 EXPECT_EQ(OK, out.rv);
1406 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1407 EXPECT_EQ("hello!hello!", out.response_data);
1409 // notice: response3 gets two hellos, response4 gets one
1410 // hello, so we know dequeuing priority was respected.
1411 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1412 out.status_line = response3->headers->GetStatusLine();
1413 out.response_info = *response3;
1414 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1415 EXPECT_EQ(OK, out.rv);
1416 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1417 EXPECT_EQ("hello!hello!", out.response_data);
1419 out.rv = callback4.WaitForResult();
1420 EXPECT_EQ(OK, out.rv);
1421 const HttpResponseInfo* response4 = trans4->GetResponseInfo();
1422 out.status_line = response4->headers->GetStatusLine();
1423 out.response_info = *response4;
1424 out.rv = ReadTransaction(trans4.get(), &out.response_data);
1425 EXPECT_EQ(OK, out.rv);
1426 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1427 EXPECT_EQ("hello!", out.response_data);
1428 helper.VerifyDataConsumed();
1429 EXPECT_EQ(OK, out.rv);
1432 // Similar to ThreeGetsMaxConcurrrent above, however, this test
1433 // deletes a session in the middle of the transaction to insure
1434 // that we properly remove pendingcreatestream objects from
1435 // the spdy_session
1436 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
1437 // Construct the request.
1438 scoped_ptr<SpdyFrame> req(
1439 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1440 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1441 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1442 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
1444 scoped_ptr<SpdyFrame> req2(
1445 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1446 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1447 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1448 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1450 SettingsMap settings;
1451 const uint32 max_concurrent_streams = 1;
1452 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1453 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1454 scoped_ptr<SpdyFrame> settings_frame(
1455 spdy_util_.ConstructSpdySettings(settings));
1456 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1458 MockWrite writes[] = {
1459 CreateMockWrite(*req),
1460 CreateMockWrite(*settings_ack, 2),
1461 CreateMockWrite(*req2),
1463 MockRead reads[] = {
1464 CreateMockRead(*settings_frame, 1),
1465 CreateMockRead(*resp),
1466 CreateMockRead(*body),
1467 CreateMockRead(*fbody),
1468 CreateMockRead(*resp2, 8),
1469 CreateMockRead(*body2),
1470 CreateMockRead(*fbody2),
1471 MockRead(ASYNC, 0, 0), // EOF
1474 OrderedSocketData data(reads, arraysize(reads),
1475 writes, arraysize(writes));
1476 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1478 BoundNetLog log;
1479 TransactionHelperResult out;
1480 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1481 BoundNetLog(), GetParam(), NULL);
1482 helper.RunPreTestSetup();
1483 helper.AddData(&data);
1484 // We require placeholder data because three get requests are sent out, so
1485 // there needs to be three sets of SSL connection data.
1486 helper.AddData(&data_placeholder);
1487 helper.AddData(&data_placeholder);
1488 scoped_ptr<HttpNetworkTransaction> trans1(
1489 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1490 scoped_ptr<HttpNetworkTransaction> trans2(
1491 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1492 scoped_ptr<HttpNetworkTransaction> trans3(
1493 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1495 TestCompletionCallback callback1;
1496 TestCompletionCallback callback2;
1497 TestCompletionCallback callback3;
1499 HttpRequestInfo httpreq1 = CreateGetRequest();
1500 HttpRequestInfo httpreq2 = CreateGetRequest();
1501 HttpRequestInfo httpreq3 = CreateGetRequest();
1503 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1504 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1505 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1506 out.rv = callback1.WaitForResult();
1507 ASSERT_EQ(OK, out.rv);
1509 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1510 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1511 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1512 delete trans3.release();
1513 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1514 out.rv = callback2.WaitForResult();
1515 ASSERT_EQ(OK, out.rv);
1517 EXPECT_EQ(8U, data.read_index());
1519 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1520 ASSERT_TRUE(response1 != NULL);
1521 EXPECT_TRUE(response1->headers.get() != NULL);
1522 EXPECT_TRUE(response1->was_fetched_via_spdy);
1523 out.status_line = response1->headers->GetStatusLine();
1524 out.response_info = *response1;
1525 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1526 EXPECT_EQ(OK, out.rv);
1527 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1528 EXPECT_EQ("hello!hello!", out.response_data);
1530 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1531 ASSERT_TRUE(response2 != NULL);
1532 out.status_line = response2->headers->GetStatusLine();
1533 out.response_info = *response2;
1534 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1535 EXPECT_EQ(OK, out.rv);
1536 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1537 EXPECT_EQ("hello!hello!", out.response_data);
1538 helper.VerifyDataConsumed();
1539 EXPECT_EQ(OK, out.rv);
1542 namespace {
1544 // The KillerCallback will delete the transaction on error as part of the
1545 // callback.
1546 class KillerCallback : public TestCompletionCallbackBase {
1547 public:
1548 explicit KillerCallback(HttpNetworkTransaction* transaction)
1549 : transaction_(transaction),
1550 callback_(base::Bind(&KillerCallback::OnComplete,
1551 base::Unretained(this))) {
1554 ~KillerCallback() override {}
1556 const CompletionCallback& callback() const { return callback_; }
1558 private:
1559 void OnComplete(int result) {
1560 if (result < 0)
1561 delete transaction_;
1563 SetResult(result);
1566 HttpNetworkTransaction* transaction_;
1567 CompletionCallback callback_;
1570 } // namespace
1572 // Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1573 // closes the socket while we have a pending transaction waiting for
1574 // a pending stream creation. http://crbug.com/52901
1575 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
1576 // Construct the request.
1577 scoped_ptr<SpdyFrame> req(
1578 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1579 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1580 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1581 scoped_ptr<SpdyFrame> fin_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1583 scoped_ptr<SpdyFrame> req2(
1584 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1585 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1587 SettingsMap settings;
1588 const uint32 max_concurrent_streams = 1;
1589 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1590 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1591 scoped_ptr<SpdyFrame> settings_frame(
1592 spdy_util_.ConstructSpdySettings(settings));
1593 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1595 MockWrite writes[] = {
1596 CreateMockWrite(*req),
1597 CreateMockWrite(*settings_ack, 2),
1598 CreateMockWrite(*req2),
1600 MockRead reads[] = {
1601 CreateMockRead(*settings_frame, 1),
1602 CreateMockRead(*resp),
1603 CreateMockRead(*body),
1604 CreateMockRead(*fin_body),
1605 CreateMockRead(*resp2, 8),
1606 MockRead(ASYNC, ERR_CONNECTION_RESET, 0), // Abort!
1609 OrderedSocketData data(reads, arraysize(reads),
1610 writes, arraysize(writes));
1611 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1613 BoundNetLog log;
1614 TransactionHelperResult out;
1615 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1616 BoundNetLog(), GetParam(), NULL);
1617 helper.RunPreTestSetup();
1618 helper.AddData(&data);
1619 // We require placeholder data because three get requests are sent out, so
1620 // there needs to be three sets of SSL connection data.
1621 helper.AddData(&data_placeholder);
1622 helper.AddData(&data_placeholder);
1623 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session().get());
1624 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session().get());
1625 HttpNetworkTransaction* trans3(
1626 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1628 TestCompletionCallback callback1;
1629 TestCompletionCallback callback2;
1630 KillerCallback callback3(trans3);
1632 HttpRequestInfo httpreq1 = CreateGetRequest();
1633 HttpRequestInfo httpreq2 = CreateGetRequest();
1634 HttpRequestInfo httpreq3 = CreateGetRequest();
1636 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
1637 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1638 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1639 out.rv = callback1.WaitForResult();
1640 ASSERT_EQ(OK, out.rv);
1642 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
1643 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1644 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1645 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1646 out.rv = callback3.WaitForResult();
1647 ASSERT_EQ(ERR_ABORTED, out.rv);
1649 EXPECT_EQ(6U, data.read_index());
1651 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
1652 ASSERT_TRUE(response1 != NULL);
1653 EXPECT_TRUE(response1->headers.get() != NULL);
1654 EXPECT_TRUE(response1->was_fetched_via_spdy);
1655 out.status_line = response1->headers->GetStatusLine();
1656 out.response_info = *response1;
1657 out.rv = ReadTransaction(&trans1, &out.response_data);
1658 EXPECT_EQ(OK, out.rv);
1660 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
1661 ASSERT_TRUE(response2 != NULL);
1662 out.status_line = response2->headers->GetStatusLine();
1663 out.response_info = *response2;
1664 out.rv = ReadTransaction(&trans2, &out.response_data);
1665 EXPECT_EQ(ERR_CONNECTION_RESET, out.rv);
1667 helper.VerifyDataConsumed();
1670 // Test that a simple PUT request works.
1671 TEST_P(SpdyNetworkTransactionTest, Put) {
1672 // Setup the request
1673 HttpRequestInfo request;
1674 request.method = "PUT";
1675 request.url = GURL("http://www.google.com/");
1677 scoped_ptr<SpdyHeaderBlock> put_headers(
1678 spdy_util_.ConstructPutHeaderBlock("http://www.google.com", 0));
1679 scoped_ptr<SpdyFrame> req(
1680 spdy_util_.ConstructSpdySyn(1, *put_headers, LOWEST, false, true));
1681 MockWrite writes[] = {
1682 CreateMockWrite(*req),
1685 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1686 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1687 MockRead reads[] = {
1688 CreateMockRead(*resp),
1689 CreateMockRead(*body),
1690 MockRead(ASYNC, 0, 0) // EOF
1693 DelayedSocketData data(1, reads, arraysize(reads),
1694 writes, arraysize(writes));
1695 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1696 BoundNetLog(), GetParam(), NULL);
1697 helper.RunToCompletion(&data);
1698 TransactionHelperResult out = helper.output();
1700 EXPECT_EQ(OK, out.rv);
1701 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1704 // Test that a simple HEAD request works.
1705 TEST_P(SpdyNetworkTransactionTest, Head) {
1706 // Setup the request
1707 HttpRequestInfo request;
1708 request.method = "HEAD";
1709 request.url = GURL("http://www.google.com/");
1711 scoped_ptr<SpdyHeaderBlock> head_headers(
1712 spdy_util_.ConstructHeadHeaderBlock("http://www.google.com", 0));
1713 scoped_ptr<SpdyFrame> req(
1714 spdy_util_.ConstructSpdySyn(1, *head_headers, LOWEST, false, true));
1715 MockWrite writes[] = {
1716 CreateMockWrite(*req),
1719 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1720 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1721 MockRead reads[] = {
1722 CreateMockRead(*resp),
1723 CreateMockRead(*body),
1724 MockRead(ASYNC, 0, 0) // EOF
1727 DelayedSocketData data(1, reads, arraysize(reads),
1728 writes, arraysize(writes));
1729 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1730 BoundNetLog(), GetParam(), NULL);
1731 helper.RunToCompletion(&data);
1732 TransactionHelperResult out = helper.output();
1734 EXPECT_EQ(OK, out.rv);
1735 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1738 // Test that a simple POST works.
1739 TEST_P(SpdyNetworkTransactionTest, Post) {
1740 scoped_ptr<SpdyFrame> req(
1741 spdy_util_.ConstructSpdyPost(
1742 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
1743 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1744 MockWrite writes[] = {
1745 CreateMockWrite(*req),
1746 CreateMockWrite(*body), // POST upload frame
1749 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1750 MockRead reads[] = {
1751 CreateMockRead(*resp),
1752 CreateMockRead(*body),
1753 MockRead(ASYNC, 0, 0) // EOF
1756 DelayedSocketData data(2, reads, arraysize(reads),
1757 writes, arraysize(writes));
1758 NormalSpdyTransactionHelper helper(CreatePostRequest(), DEFAULT_PRIORITY,
1759 BoundNetLog(), GetParam(), NULL);
1760 helper.RunToCompletion(&data);
1761 TransactionHelperResult out = helper.output();
1762 EXPECT_EQ(OK, out.rv);
1763 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1764 EXPECT_EQ("hello!", out.response_data);
1767 // Test that a POST with a file works.
1768 TEST_P(SpdyNetworkTransactionTest, FilePost) {
1769 scoped_ptr<SpdyFrame> req(
1770 spdy_util_.ConstructSpdyPost(
1771 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
1772 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1773 MockWrite writes[] = {
1774 CreateMockWrite(*req),
1775 CreateMockWrite(*body), // POST upload frame
1778 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1779 MockRead reads[] = {
1780 CreateMockRead(*resp),
1781 CreateMockRead(*body),
1782 MockRead(ASYNC, 0, 0) // EOF
1785 DelayedSocketData data(2, reads, arraysize(reads),
1786 writes, arraysize(writes));
1787 NormalSpdyTransactionHelper helper(CreateFilePostRequest(), DEFAULT_PRIORITY,
1788 BoundNetLog(), GetParam(), NULL);
1789 helper.RunToCompletion(&data);
1790 TransactionHelperResult out = helper.output();
1791 EXPECT_EQ(OK, out.rv);
1792 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1793 EXPECT_EQ("hello!", out.response_data);
1796 // Test that a POST with a unreadable file fails.
1797 TEST_P(SpdyNetworkTransactionTest, UnreadableFilePost) {
1798 MockWrite writes[] = {
1799 MockWrite(ASYNC, 0, 0) // EOF
1801 MockRead reads[] = {
1802 MockRead(ASYNC, 0, 0) // EOF
1805 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
1806 NormalSpdyTransactionHelper helper(CreateUnreadableFilePostRequest(),
1807 DEFAULT_PRIORITY,
1808 BoundNetLog(), GetParam(), NULL);
1809 helper.RunPreTestSetup();
1810 helper.AddData(&data);
1811 helper.RunDefaultTest();
1813 base::RunLoop().RunUntilIdle();
1814 helper.VerifyDataNotConsumed();
1815 EXPECT_EQ(ERR_ACCESS_DENIED, helper.output().rv);
1818 // Test that a complex POST works.
1819 TEST_P(SpdyNetworkTransactionTest, ComplexPost) {
1820 scoped_ptr<SpdyFrame> req(
1821 spdy_util_.ConstructSpdyPost(
1822 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
1823 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1824 MockWrite writes[] = {
1825 CreateMockWrite(*req),
1826 CreateMockWrite(*body), // POST upload frame
1829 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1830 MockRead reads[] = {
1831 CreateMockRead(*resp),
1832 CreateMockRead(*body),
1833 MockRead(ASYNC, 0, 0) // EOF
1836 DelayedSocketData data(2, reads, arraysize(reads),
1837 writes, arraysize(writes));
1838 NormalSpdyTransactionHelper helper(CreateComplexPostRequest(),
1839 DEFAULT_PRIORITY,
1840 BoundNetLog(), GetParam(), NULL);
1841 helper.RunToCompletion(&data);
1842 TransactionHelperResult out = helper.output();
1843 EXPECT_EQ(OK, out.rv);
1844 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1845 EXPECT_EQ("hello!", out.response_data);
1848 // Test that a chunked POST works.
1849 TEST_P(SpdyNetworkTransactionTest, ChunkedPost) {
1850 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1851 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1852 MockWrite writes[] = {
1853 CreateMockWrite(*req),
1854 CreateMockWrite(*body),
1857 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1858 MockRead reads[] = {
1859 CreateMockRead(*resp),
1860 CreateMockRead(*body),
1861 MockRead(ASYNC, 0, 0) // EOF
1864 DelayedSocketData data(2, reads, arraysize(reads),
1865 writes, arraysize(writes));
1866 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
1867 DEFAULT_PRIORITY,
1868 BoundNetLog(), GetParam(), NULL);
1870 // These chunks get merged into a single frame when being sent.
1871 const int kFirstChunkSize = kUploadDataSize/2;
1872 upload_chunked_data_stream()->AppendData(kUploadData, kFirstChunkSize, false);
1873 upload_chunked_data_stream()->AppendData(
1874 kUploadData + kFirstChunkSize, kUploadDataSize - kFirstChunkSize, true);
1876 helper.RunToCompletion(&data);
1877 TransactionHelperResult out = helper.output();
1878 EXPECT_EQ(OK, out.rv);
1879 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1880 EXPECT_EQ(kUploadData, out.response_data);
1883 // Test that a chunked POST works with chunks appended after transaction starts.
1884 TEST_P(SpdyNetworkTransactionTest, DelayedChunkedPost) {
1885 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1886 scoped_ptr<SpdyFrame> chunk1(spdy_util_.ConstructSpdyBodyFrame(1, false));
1887 scoped_ptr<SpdyFrame> chunk2(spdy_util_.ConstructSpdyBodyFrame(1, false));
1888 scoped_ptr<SpdyFrame> chunk3(spdy_util_.ConstructSpdyBodyFrame(1, true));
1889 MockWrite writes[] = {
1890 CreateMockWrite(*req),
1891 CreateMockWrite(*chunk1),
1892 CreateMockWrite(*chunk2),
1893 CreateMockWrite(*chunk3),
1896 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1897 MockRead reads[] = {
1898 CreateMockRead(*resp),
1899 CreateMockRead(*chunk1),
1900 CreateMockRead(*chunk2),
1901 CreateMockRead(*chunk3),
1902 MockRead(ASYNC, 0, 0) // EOF
1905 DelayedSocketData data(4, reads, arraysize(reads),
1906 writes, arraysize(writes));
1907 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
1908 DEFAULT_PRIORITY,
1909 BoundNetLog(), GetParam(), NULL);
1911 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
1913 helper.RunPreTestSetup();
1914 helper.AddData(&data);
1915 ASSERT_TRUE(helper.StartDefaultTest());
1917 base::RunLoop().RunUntilIdle();
1918 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
1919 base::RunLoop().RunUntilIdle();
1920 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true);
1922 helper.FinishDefaultTest();
1923 helper.VerifyDataConsumed();
1925 std::string expected_response;
1926 expected_response += kUploadData;
1927 expected_response += kUploadData;
1928 expected_response += kUploadData;
1930 TransactionHelperResult out = helper.output();
1931 EXPECT_EQ(OK, out.rv);
1932 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1933 EXPECT_EQ(expected_response, out.response_data);
1936 // Test that a POST without any post data works.
1937 TEST_P(SpdyNetworkTransactionTest, NullPost) {
1938 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
1939 // Setup the request
1940 HttpRequestInfo request;
1941 request.method = "POST";
1942 request.url = GURL(kRequestUrl);
1943 // Create an empty UploadData.
1944 request.upload_data_stream = NULL;
1946 // When request.upload_data_stream is NULL for post, content-length is
1947 // expected to be 0.
1948 scoped_ptr<SpdyHeaderBlock> req_block(
1949 spdy_util_.ConstructPostHeaderBlock(kRequestUrl, 0));
1950 scoped_ptr<SpdyFrame> req(
1951 spdy_util_.ConstructSpdySyn(1, *req_block, LOWEST, false, true));
1953 MockWrite writes[] = {
1954 CreateMockWrite(*req),
1957 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1958 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1959 MockRead reads[] = {
1960 CreateMockRead(*resp),
1961 CreateMockRead(*body),
1962 MockRead(ASYNC, 0, 0) // EOF
1965 DelayedSocketData data(1, reads, arraysize(reads),
1966 writes, arraysize(writes));
1968 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1969 BoundNetLog(), GetParam(), NULL);
1970 helper.RunToCompletion(&data);
1971 TransactionHelperResult out = helper.output();
1972 EXPECT_EQ(OK, out.rv);
1973 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1974 EXPECT_EQ("hello!", out.response_data);
1977 // Test that a simple POST works.
1978 TEST_P(SpdyNetworkTransactionTest, EmptyPost) {
1979 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
1980 // Create an empty UploadDataStream.
1981 ScopedVector<UploadElementReader> element_readers;
1982 ElementsUploadDataStream stream(element_readers.Pass(), 0);
1984 // Setup the request
1985 HttpRequestInfo request;
1986 request.method = "POST";
1987 request.url = GURL(kRequestUrl);
1988 request.upload_data_stream = &stream;
1990 const uint64 kContentLength = 0;
1992 scoped_ptr<SpdyHeaderBlock> req_block(
1993 spdy_util_.ConstructPostHeaderBlock(kRequestUrl, kContentLength));
1994 scoped_ptr<SpdyFrame> req(
1995 spdy_util_.ConstructSpdySyn(1, *req_block, LOWEST, false, true));
1997 MockWrite writes[] = {
1998 CreateMockWrite(*req),
2001 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
2002 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2003 MockRead reads[] = {
2004 CreateMockRead(*resp),
2005 CreateMockRead(*body),
2006 MockRead(ASYNC, 0, 0) // EOF
2009 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
2011 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
2012 BoundNetLog(), GetParam(), NULL);
2013 helper.RunToCompletion(&data);
2014 TransactionHelperResult out = helper.output();
2015 EXPECT_EQ(OK, out.rv);
2016 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
2017 EXPECT_EQ("hello!", out.response_data);
2020 // While we're doing a post, the server sends the reply before upload completes.
2021 TEST_P(SpdyNetworkTransactionTest, ResponseBeforePostCompletes) {
2022 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
2023 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2024 MockWrite writes[] = {
2025 CreateMockWrite(*req, 0),
2026 CreateMockWrite(*body, 3),
2028 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
2029 MockRead reads[] = {
2030 CreateMockRead(*resp, 1),
2031 CreateMockRead(*body, 2),
2032 MockRead(ASYNC, 0, 4) // EOF
2035 // Write the request headers, and read the complete response
2036 // while still waiting for chunked request data.
2037 DeterministicSocketData data(reads, arraysize(reads),
2038 writes, arraysize(writes));
2039 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
2040 DEFAULT_PRIORITY,
2041 BoundNetLog(), GetParam(), NULL);
2042 helper.SetDeterministic();
2043 helper.RunPreTestSetup();
2044 helper.AddDeterministicData(&data);
2046 ASSERT_TRUE(helper.StartDefaultTest());
2048 // Process the request headers, SYN_REPLY, and response body.
2049 // The request body is still in flight.
2050 data.RunFor(3);
2052 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
2053 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2055 // Finish sending the request body.
2056 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true);
2057 data.RunFor(2);
2059 std::string response_body;
2060 EXPECT_EQ(OK, ReadTransaction(helper.trans(), &response_body));
2061 EXPECT_EQ(kUploadData, response_body);
2062 helper.VerifyDataConsumed();
2065 // The client upon cancellation tries to send a RST_STREAM frame. The mock
2066 // socket causes the TCP write to return zero. This test checks that the client
2067 // tries to queue up the RST_STREAM frame again.
2068 TEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
2069 scoped_ptr<SpdyFrame> req(
2070 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2071 scoped_ptr<SpdyFrame> rst(
2072 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2073 MockWrite writes[] = {
2074 CreateMockWrite(*req.get(), 0, SYNCHRONOUS),
2075 MockWrite(SYNCHRONOUS, 0, 0, 2),
2076 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
2079 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2080 MockRead reads[] = {
2081 CreateMockRead(*resp.get(), 1, ASYNC),
2082 MockRead(ASYNC, 0, 0, 4) // EOF
2085 DeterministicSocketData data(reads, arraysize(reads),
2086 writes, arraysize(writes));
2087 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2088 BoundNetLog(), GetParam(), NULL);
2089 helper.SetDeterministic();
2090 helper.RunPreTestSetup();
2091 helper.AddDeterministicData(&data);
2092 HttpNetworkTransaction* trans = helper.trans();
2094 TestCompletionCallback callback;
2095 int rv = trans->Start(
2096 &CreateGetRequest(), callback.callback(), BoundNetLog());
2097 EXPECT_EQ(ERR_IO_PENDING, rv);
2099 data.SetStop(2);
2100 data.Run();
2101 helper.ResetTrans();
2102 data.SetStop(20);
2103 data.Run();
2105 helper.VerifyDataConsumed();
2108 // Test that the transaction doesn't crash when we don't have a reply.
2109 TEST_P(SpdyNetworkTransactionTest, ResponseWithoutSynReply) {
2110 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2111 MockRead reads[] = {
2112 CreateMockRead(*body),
2113 MockRead(ASYNC, 0, 0) // EOF
2116 DelayedSocketData data(1, reads, arraysize(reads), NULL, 0);
2117 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2118 BoundNetLog(), GetParam(), NULL);
2119 helper.RunToCompletion(&data);
2120 TransactionHelperResult out = helper.output();
2121 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
2124 // Test that the transaction doesn't crash when we get two replies on the same
2125 // stream ID. See http://crbug.com/45639.
2126 TEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
2127 scoped_ptr<SpdyFrame> req(
2128 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2129 scoped_ptr<SpdyFrame> rst(
2130 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
2131 MockWrite writes[] = {
2132 CreateMockWrite(*req),
2133 CreateMockWrite(*rst),
2136 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2137 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2138 MockRead reads[] = {
2139 CreateMockRead(*resp),
2140 CreateMockRead(*resp),
2141 CreateMockRead(*body),
2142 MockRead(ASYNC, 0, 0) // EOF
2145 DelayedSocketData data(1, reads, arraysize(reads),
2146 writes, arraysize(writes));
2148 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2149 BoundNetLog(), GetParam(), NULL);
2150 helper.RunPreTestSetup();
2151 helper.AddData(&data);
2153 HttpNetworkTransaction* trans = helper.trans();
2155 TestCompletionCallback callback;
2156 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2157 EXPECT_EQ(ERR_IO_PENDING, rv);
2158 rv = callback.WaitForResult();
2159 EXPECT_EQ(OK, rv);
2161 const HttpResponseInfo* response = trans->GetResponseInfo();
2162 ASSERT_TRUE(response != NULL);
2163 EXPECT_TRUE(response->headers.get() != NULL);
2164 EXPECT_TRUE(response->was_fetched_via_spdy);
2165 std::string response_data;
2166 rv = ReadTransaction(trans, &response_data);
2167 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
2169 helper.VerifyDataConsumed();
2172 TEST_P(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) {
2173 // Construct the request.
2174 scoped_ptr<SpdyFrame> req(
2175 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2176 scoped_ptr<SpdyFrame> rst(
2177 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
2178 MockWrite writes[] = {
2179 CreateMockWrite(*req),
2180 CreateMockWrite(*rst),
2183 const char* const headers[] = {
2184 "transfer-encoding", "chunked"
2186 scoped_ptr<SpdyFrame> resp(
2187 spdy_util_.ConstructSpdyGetSynReply(headers, 1, 1));
2188 scoped_ptr<SpdyFrame> body(
2189 spdy_util_.ConstructSpdyBodyFrame(1, true));
2190 MockRead reads[] = {
2191 CreateMockRead(*resp),
2192 CreateMockRead(*body),
2193 MockRead(ASYNC, 0, 0) // EOF
2196 DelayedSocketData data(1, reads, arraysize(reads),
2197 writes, arraysize(writes));
2198 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2199 BoundNetLog(), GetParam(), NULL);
2200 helper.RunToCompletion(&data);
2201 TransactionHelperResult out = helper.output();
2202 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
2204 helper.session()->spdy_session_pool()->CloseAllSessions();
2205 helper.VerifyDataConsumed();
2208 TEST_P(SpdyNetworkTransactionTest, ResetPushWithTransferEncoding) {
2209 // Construct the request.
2210 scoped_ptr<SpdyFrame> req(
2211 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2212 scoped_ptr<SpdyFrame> rst(
2213 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
2214 MockWrite writes[] = {
2215 CreateMockWrite(*req),
2216 CreateMockWrite(*rst),
2219 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2220 const char* const headers[] = {
2221 "transfer-encoding", "chunked"
2223 scoped_ptr<SpdyFrame> push(
2224 spdy_util_.ConstructSpdyPush(headers, arraysize(headers) / 2,
2225 2, 1, "http://www.google.com/1"));
2226 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2227 MockRead reads[] = {
2228 CreateMockRead(*resp),
2229 CreateMockRead(*push),
2230 CreateMockRead(*body),
2231 MockRead(ASYNC, 0, 0) // EOF
2234 DelayedSocketData data(1, reads, arraysize(reads),
2235 writes, arraysize(writes));
2236 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2237 BoundNetLog(), GetParam(), NULL);
2238 helper.RunToCompletion(&data);
2239 TransactionHelperResult out = helper.output();
2240 EXPECT_EQ(OK, out.rv);
2241 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
2242 EXPECT_EQ("hello!", out.response_data);
2244 helper.session()->spdy_session_pool()->CloseAllSessions();
2245 helper.VerifyDataConsumed();
2248 TEST_P(SpdyNetworkTransactionTest, CancelledTransaction) {
2249 // Construct the request.
2250 scoped_ptr<SpdyFrame> req(
2251 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2252 MockWrite writes[] = {
2253 CreateMockWrite(*req),
2256 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2257 MockRead reads[] = {
2258 CreateMockRead(*resp),
2259 // This following read isn't used by the test, except during the
2260 // RunUntilIdle() call at the end since the SpdySession survives the
2261 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
2262 // MockRead will do here.
2263 MockRead(ASYNC, 0, 0) // EOF
2266 StaticSocketDataProvider data(reads, arraysize(reads),
2267 writes, arraysize(writes));
2269 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2270 BoundNetLog(), GetParam(), NULL);
2271 helper.RunPreTestSetup();
2272 helper.AddData(&data);
2273 HttpNetworkTransaction* trans = helper.trans();
2275 TestCompletionCallback callback;
2276 int rv = trans->Start(
2277 &CreateGetRequest(), callback.callback(), BoundNetLog());
2278 EXPECT_EQ(ERR_IO_PENDING, rv);
2279 helper.ResetTrans(); // Cancel the transaction.
2281 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
2282 // MockClientSocketFactory) are still alive.
2283 base::RunLoop().RunUntilIdle();
2284 helper.VerifyDataNotConsumed();
2287 // Verify that the client sends a Rst Frame upon cancelling the stream.
2288 TEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
2289 scoped_ptr<SpdyFrame> req(
2290 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2291 scoped_ptr<SpdyFrame> rst(
2292 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2293 MockWrite writes[] = {
2294 CreateMockWrite(*req, 0, SYNCHRONOUS),
2295 CreateMockWrite(*rst, 2, SYNCHRONOUS),
2298 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2299 MockRead reads[] = {
2300 CreateMockRead(*resp, 1, ASYNC),
2301 MockRead(ASYNC, 0, 0, 3) // EOF
2304 DeterministicSocketData data(reads, arraysize(reads),
2305 writes, arraysize(writes));
2307 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2308 BoundNetLog(),
2309 GetParam(), NULL);
2310 helper.SetDeterministic();
2311 helper.RunPreTestSetup();
2312 helper.AddDeterministicData(&data);
2313 HttpNetworkTransaction* trans = helper.trans();
2315 TestCompletionCallback callback;
2317 int rv = trans->Start(
2318 &CreateGetRequest(), callback.callback(), BoundNetLog());
2319 EXPECT_EQ(ERR_IO_PENDING, rv);
2321 data.SetStop(2);
2322 data.Run();
2323 helper.ResetTrans();
2324 data.SetStop(20);
2325 data.Run();
2327 helper.VerifyDataConsumed();
2330 // Verify that the client can correctly deal with the user callback attempting
2331 // to start another transaction on a session that is closing down. See
2332 // http://crbug.com/47455
2333 TEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
2334 scoped_ptr<SpdyFrame> req(
2335 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2336 MockWrite writes[] = { CreateMockWrite(*req) };
2337 MockWrite writes2[] = { CreateMockWrite(*req) };
2339 // The indicated length of this frame is longer than its actual length. When
2340 // the session receives an empty frame after this one, it shuts down the
2341 // session, and calls the read callback with the incomplete data.
2342 const uint8 kGetBodyFrame2[] = {
2343 0x00, 0x00, 0x00, 0x01,
2344 0x01, 0x00, 0x00, 0x07,
2345 'h', 'e', 'l', 'l', 'o', '!',
2348 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2349 MockRead reads[] = {
2350 CreateMockRead(*resp, 2),
2351 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause
2352 MockRead(ASYNC, reinterpret_cast<const char*>(kGetBodyFrame2),
2353 arraysize(kGetBodyFrame2), 4),
2354 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
2355 MockRead(ASYNC, 0, 0, 6), // EOF
2357 MockRead reads2[] = {
2358 CreateMockRead(*resp, 2),
2359 MockRead(ASYNC, 0, 0, 3), // EOF
2362 OrderedSocketData data(reads, arraysize(reads),
2363 writes, arraysize(writes));
2364 DelayedSocketData data2(1, reads2, arraysize(reads2),
2365 writes2, arraysize(writes2));
2367 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2368 BoundNetLog(), GetParam(), NULL);
2369 helper.RunPreTestSetup();
2370 helper.AddData(&data);
2371 helper.AddData(&data2);
2372 HttpNetworkTransaction* trans = helper.trans();
2374 // Start the transaction with basic parameters.
2375 TestCompletionCallback callback;
2376 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2377 EXPECT_EQ(ERR_IO_PENDING, rv);
2378 rv = callback.WaitForResult();
2380 const int kSize = 3000;
2381 scoped_refptr<IOBuffer> buf(new IOBuffer(kSize));
2382 rv = trans->Read(
2383 buf.get(),
2384 kSize,
2385 base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback,
2386 helper.session()));
2387 // This forces an err_IO_pending, which sets the callback.
2388 data.CompleteRead();
2389 // This finishes the read.
2390 data.CompleteRead();
2391 helper.VerifyDataConsumed();
2394 // Verify that the client can correctly deal with the user callback deleting the
2395 // transaction. Failures will usually be valgrind errors. See
2396 // http://crbug.com/46925
2397 TEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
2398 scoped_ptr<SpdyFrame> req(
2399 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2400 MockWrite writes[] = { CreateMockWrite(*req) };
2402 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2403 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2404 MockRead reads[] = {
2405 CreateMockRead(*resp.get(), 2),
2406 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause
2407 CreateMockRead(*body.get(), 4),
2408 MockRead(ASYNC, 0, 0, 5), // EOF
2411 OrderedSocketData data(reads, arraysize(reads),
2412 writes, arraysize(writes));
2414 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2415 BoundNetLog(), GetParam(), NULL);
2416 helper.RunPreTestSetup();
2417 helper.AddData(&data);
2418 HttpNetworkTransaction* trans = helper.trans();
2420 // Start the transaction with basic parameters.
2421 TestCompletionCallback callback;
2422 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2423 EXPECT_EQ(ERR_IO_PENDING, rv);
2424 rv = callback.WaitForResult();
2426 // Setup a user callback which will delete the session, and clear out the
2427 // memory holding the stream object. Note that the callback deletes trans.
2428 const int kSize = 3000;
2429 scoped_refptr<IOBuffer> buf(new IOBuffer(kSize));
2430 rv = trans->Read(
2431 buf.get(),
2432 kSize,
2433 base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback,
2434 base::Unretained(&helper)));
2435 ASSERT_EQ(ERR_IO_PENDING, rv);
2436 data.CompleteRead();
2438 // Finish running rest of tasks.
2439 base::RunLoop().RunUntilIdle();
2440 helper.VerifyDataConsumed();
2443 // Send a spdy request to www.google.com that gets redirected to www.foo.com.
2444 TEST_P(SpdyNetworkTransactionTest, RedirectGetRequest) {
2445 scoped_ptr<SpdyHeaderBlock> headers(
2446 spdy_util_.ConstructGetHeaderBlock("http://www.google.com/"));
2447 (*headers)["user-agent"] = "";
2448 (*headers)["accept-encoding"] = "gzip, deflate";
2449 scoped_ptr<SpdyHeaderBlock> headers2(
2450 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2451 (*headers2)["user-agent"] = "";
2452 (*headers2)["accept-encoding"] = "gzip, deflate";
2454 // Setup writes/reads to www.google.com
2455 scoped_ptr<SpdyFrame> req(
2456 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
2457 scoped_ptr<SpdyFrame> req2(
2458 spdy_util_.ConstructSpdySyn(1, *headers2, LOWEST, false, true));
2459 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReplyRedirect(1));
2460 MockWrite writes[] = {
2461 CreateMockWrite(*req, 1),
2463 MockRead reads[] = {
2464 CreateMockRead(*resp, 2),
2465 MockRead(ASYNC, 0, 0, 3) // EOF
2468 // Setup writes/reads to www.foo.com
2469 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2470 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
2471 MockWrite writes2[] = {
2472 CreateMockWrite(*req2, 1),
2474 MockRead reads2[] = {
2475 CreateMockRead(*resp2, 2),
2476 CreateMockRead(*body2, 3),
2477 MockRead(ASYNC, 0, 0, 4) // EOF
2479 OrderedSocketData data(reads, arraysize(reads),
2480 writes, arraysize(writes));
2481 OrderedSocketData data2(reads2, arraysize(reads2),
2482 writes2, arraysize(writes2));
2484 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2485 TestDelegate d;
2487 SpdyURLRequestContext spdy_url_request_context(
2488 GetParam().protocol,
2489 false /* force_spdy_over_ssl*/,
2490 true /* force_spdy_always */);
2491 scoped_ptr<URLRequest> r(spdy_url_request_context.CreateRequest(
2492 GURL("http://www.google.com/"), DEFAULT_PRIORITY, &d));
2493 spdy_url_request_context.socket_factory().
2494 AddSocketDataProvider(&data);
2495 spdy_url_request_context.socket_factory().
2496 AddSocketDataProvider(&data2);
2498 d.set_quit_on_redirect(true);
2499 r->Start();
2500 base::RunLoop().Run();
2502 EXPECT_EQ(1, d.received_redirect_count());
2504 r->FollowDeferredRedirect();
2505 base::RunLoop().Run();
2506 EXPECT_EQ(1, d.response_started_count());
2507 EXPECT_FALSE(d.received_data_before_response());
2508 EXPECT_EQ(URLRequestStatus::SUCCESS, r->status().status());
2509 std::string contents("hello!");
2510 EXPECT_EQ(contents, d.data_received());
2512 EXPECT_TRUE(data.at_read_eof());
2513 EXPECT_TRUE(data.at_write_eof());
2514 EXPECT_TRUE(data2.at_read_eof());
2515 EXPECT_TRUE(data2.at_write_eof());
2518 // Send a spdy request to www.google.com. Get a pushed stream that redirects to
2519 // www.foo.com.
2520 TEST_P(SpdyNetworkTransactionTest, RedirectServerPush) {
2521 scoped_ptr<SpdyHeaderBlock> headers(
2522 spdy_util_.ConstructGetHeaderBlock("http://www.google.com/"));
2523 (*headers)["user-agent"] = "";
2524 (*headers)["accept-encoding"] = "gzip, deflate";
2526 // Setup writes/reads to www.google.com
2527 scoped_ptr<SpdyFrame> req(
2528 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
2529 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2530 scoped_ptr<SpdyFrame> rep(
2531 spdy_util_.ConstructSpdyPush(NULL,
2535 "http://www.google.com/foo.dat",
2536 "301 Moved Permanently",
2537 "http://www.foo.com/index.php"));
2538 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2539 scoped_ptr<SpdyFrame> rst(
2540 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
2541 MockWrite writes[] = {
2542 CreateMockWrite(*req, 1),
2543 CreateMockWrite(*rst, 6),
2545 MockRead reads[] = {
2546 CreateMockRead(*resp, 2),
2547 CreateMockRead(*rep, 3),
2548 CreateMockRead(*body, 4),
2549 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
2550 MockRead(ASYNC, 0, 0, 7) // EOF
2553 // Setup writes/reads to www.foo.com
2554 scoped_ptr<SpdyHeaderBlock> headers2(
2555 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2556 (*headers2)["user-agent"] = "";
2557 (*headers2)["accept-encoding"] = "gzip, deflate";
2558 scoped_ptr<SpdyFrame> req2(
2559 spdy_util_.ConstructSpdySyn(1, *headers2, LOWEST, false, true));
2560 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2561 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
2562 MockWrite writes2[] = {
2563 CreateMockWrite(*req2, 1),
2565 MockRead reads2[] = {
2566 CreateMockRead(*resp2, 2),
2567 CreateMockRead(*body2, 3),
2568 MockRead(ASYNC, 0, 0, 5) // EOF
2570 OrderedSocketData data(reads, arraysize(reads),
2571 writes, arraysize(writes));
2572 OrderedSocketData data2(reads2, arraysize(reads2),
2573 writes2, arraysize(writes2));
2575 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2576 TestDelegate d;
2577 TestDelegate d2;
2578 SpdyURLRequestContext spdy_url_request_context(
2579 GetParam().protocol,
2580 false /* force_spdy_over_ssl*/,
2581 true /* force_spdy_always */);
2583 scoped_ptr<URLRequest> r(spdy_url_request_context.CreateRequest(
2584 GURL("http://www.google.com/"), DEFAULT_PRIORITY, &d));
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(spdy_url_request_context.CreateRequest(
2596 GURL("http://www.google.com/foo.dat"), DEFAULT_PRIORITY, &d2));
2597 spdy_url_request_context.socket_factory().
2598 AddSocketDataProvider(&data2);
2600 d2.set_quit_on_redirect(true);
2601 r2->Start();
2602 base::RunLoop().Run();
2603 EXPECT_EQ(1, d2.received_redirect_count());
2605 r2->FollowDeferredRedirect();
2606 base::RunLoop().Run();
2607 EXPECT_EQ(1, d2.response_started_count());
2608 EXPECT_FALSE(d2.received_data_before_response());
2609 EXPECT_EQ(URLRequestStatus::SUCCESS, r2->status().status());
2610 std::string contents2("hello!");
2611 EXPECT_EQ(contents2, d2.data_received());
2613 data.CompleteRead();
2614 data2.CompleteRead();
2615 EXPECT_TRUE(data.at_read_eof());
2616 EXPECT_TRUE(data.at_write_eof());
2617 EXPECT_TRUE(data2.at_read_eof());
2618 EXPECT_TRUE(data2.at_write_eof());
2621 TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
2622 scoped_ptr<SpdyFrame> stream1_syn(
2623 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2624 scoped_ptr<SpdyFrame> stream1_body(
2625 spdy_util_.ConstructSpdyBodyFrame(1, true));
2626 MockWrite writes[] = {
2627 CreateMockWrite(*stream1_syn, 1),
2630 scoped_ptr<SpdyFrame>
2631 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2632 scoped_ptr<SpdyFrame>
2633 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2637 "http://www.google.com/foo.dat"));
2638 const char kPushedData[] = "pushed";
2639 scoped_ptr<SpdyFrame> stream2_body(
2640 spdy_util_.ConstructSpdyBodyFrame(
2641 2, kPushedData, strlen(kPushedData), true));
2642 MockRead reads[] = {
2643 CreateMockRead(*stream1_reply, 2),
2644 CreateMockRead(*stream2_syn, 3),
2645 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2646 CreateMockRead(*stream2_body, 5),
2647 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2650 HttpResponseInfo response;
2651 HttpResponseInfo response2;
2652 std::string expected_push_result("pushed");
2653 OrderedSocketData data(reads, arraysize(reads),
2654 writes, arraysize(writes));
2655 RunServerPushTest(&data,
2656 &response,
2657 &response2,
2658 expected_push_result);
2660 // Verify the SYN_REPLY.
2661 EXPECT_TRUE(response.headers.get() != NULL);
2662 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2664 // Verify the pushed stream.
2665 EXPECT_TRUE(response2.headers.get() != NULL);
2666 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2669 TEST_P(SpdyNetworkTransactionTest, ServerPushBeforeSynReply) {
2670 scoped_ptr<SpdyFrame> stream1_syn(
2671 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2672 scoped_ptr<SpdyFrame> stream1_body(
2673 spdy_util_.ConstructSpdyBodyFrame(1, true));
2674 MockWrite writes[] = {
2675 CreateMockWrite(*stream1_syn, 1),
2678 scoped_ptr<SpdyFrame>
2679 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2680 scoped_ptr<SpdyFrame>
2681 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2685 "http://www.google.com/foo.dat"));
2686 const char kPushedData[] = "pushed";
2687 scoped_ptr<SpdyFrame> stream2_body(
2688 spdy_util_.ConstructSpdyBodyFrame(
2689 2, kPushedData, strlen(kPushedData), true));
2690 MockRead reads[] = {
2691 CreateMockRead(*stream2_syn, 2),
2692 CreateMockRead(*stream1_reply, 3),
2693 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2694 CreateMockRead(*stream2_body, 5),
2695 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2698 HttpResponseInfo response;
2699 HttpResponseInfo response2;
2700 std::string expected_push_result("pushed");
2701 OrderedSocketData data(reads, arraysize(reads),
2702 writes, arraysize(writes));
2703 RunServerPushTest(&data,
2704 &response,
2705 &response2,
2706 expected_push_result);
2708 // Verify the SYN_REPLY.
2709 EXPECT_TRUE(response.headers.get() != NULL);
2710 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2712 // Verify the pushed stream.
2713 EXPECT_TRUE(response2.headers.get() != NULL);
2714 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2717 TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
2718 scoped_ptr<SpdyFrame> stream1_syn(
2719 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2720 MockWrite writes[] = { CreateMockWrite(*stream1_syn, 1), };
2722 scoped_ptr<SpdyFrame>
2723 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2724 scoped_ptr<SpdyFrame>
2725 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2729 "http://www.google.com/foo.dat"));
2730 const char kPushedData[] = "pushed";
2731 scoped_ptr<SpdyFrame> stream2_body(
2732 spdy_util_.ConstructSpdyBodyFrame(
2733 2, kPushedData, strlen(kPushedData), true));
2734 scoped_ptr<SpdyFrame>
2735 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2736 MockRead reads[] = {
2737 CreateMockRead(*stream1_reply, 2),
2738 CreateMockRead(*stream2_syn, 3),
2739 CreateMockRead(*stream2_body, 4),
2740 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
2741 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2744 HttpResponseInfo response;
2745 HttpResponseInfo response2;
2746 std::string expected_push_result("pushed");
2747 OrderedSocketData data(reads, arraysize(reads),
2748 writes, arraysize(writes));
2749 RunServerPushTest(&data,
2750 &response,
2751 &response2,
2752 expected_push_result);
2754 // Verify the SYN_REPLY.
2755 EXPECT_TRUE(response.headers.get() != NULL);
2756 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2758 // Verify the pushed stream.
2759 EXPECT_TRUE(response2.headers.get() != NULL);
2760 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2763 TEST_P(SpdyNetworkTransactionTest, ServerPushServerAborted) {
2764 scoped_ptr<SpdyFrame> stream1_syn(
2765 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2766 scoped_ptr<SpdyFrame> stream1_body(
2767 spdy_util_.ConstructSpdyBodyFrame(1, true));
2768 MockWrite writes[] = {
2769 CreateMockWrite(*stream1_syn, 1),
2772 scoped_ptr<SpdyFrame>
2773 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2774 scoped_ptr<SpdyFrame>
2775 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2779 "http://www.google.com/foo.dat"));
2780 scoped_ptr<SpdyFrame> stream2_rst(
2781 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
2782 MockRead reads[] = {
2783 CreateMockRead(*stream1_reply, 2),
2784 CreateMockRead(*stream2_syn, 3),
2785 CreateMockRead(*stream2_rst, 4),
2786 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
2787 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2790 OrderedSocketData data(reads, arraysize(reads),
2791 writes, arraysize(writes));
2792 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2793 BoundNetLog(), GetParam(), NULL);
2795 helper.RunPreTestSetup();
2796 helper.AddData(&data);
2798 HttpNetworkTransaction* trans = helper.trans();
2800 // Start the transaction with basic parameters.
2801 TestCompletionCallback callback;
2802 int rv = trans->Start(
2803 &CreateGetRequest(), callback.callback(), BoundNetLog());
2804 EXPECT_EQ(ERR_IO_PENDING, rv);
2805 rv = callback.WaitForResult();
2806 EXPECT_EQ(OK, rv);
2808 // Verify that we consumed all test data.
2809 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
2810 << data.read_count()
2811 << " Read index: "
2812 << data.read_index();
2813 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
2814 << data.write_count()
2815 << " Write index: "
2816 << data.write_index();
2818 // Verify the SYN_REPLY.
2819 HttpResponseInfo response = *trans->GetResponseInfo();
2820 EXPECT_TRUE(response.headers.get() != NULL);
2821 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2824 // Verify that we don't leak streams and that we properly send a reset
2825 // if the server pushes the same stream twice.
2826 TEST_P(SpdyNetworkTransactionTest, ServerPushDuplicate) {
2827 scoped_ptr<SpdyFrame> stream1_syn(
2828 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2829 scoped_ptr<SpdyFrame> stream1_body(
2830 spdy_util_.ConstructSpdyBodyFrame(1, true));
2831 scoped_ptr<SpdyFrame> stream3_rst(
2832 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR));
2833 MockWrite writes[] = {
2834 CreateMockWrite(*stream1_syn, 1),
2835 CreateMockWrite(*stream3_rst, 5),
2838 scoped_ptr<SpdyFrame>
2839 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2840 scoped_ptr<SpdyFrame>
2841 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2845 "http://www.google.com/foo.dat"));
2846 const char kPushedData[] = "pushed";
2847 scoped_ptr<SpdyFrame> stream2_body(
2848 spdy_util_.ConstructSpdyBodyFrame(
2849 2, kPushedData, strlen(kPushedData), true));
2850 scoped_ptr<SpdyFrame>
2851 stream3_syn(spdy_util_.ConstructSpdyPush(NULL,
2855 "http://www.google.com/foo.dat"));
2856 MockRead reads[] = {
2857 CreateMockRead(*stream1_reply, 2),
2858 CreateMockRead(*stream2_syn, 3),
2859 CreateMockRead(*stream3_syn, 4),
2860 CreateMockRead(*stream1_body, 6, SYNCHRONOUS),
2861 CreateMockRead(*stream2_body, 7),
2862 MockRead(ASYNC, ERR_IO_PENDING, 8), // Force a pause
2865 HttpResponseInfo response;
2866 HttpResponseInfo response2;
2867 std::string expected_push_result("pushed");
2868 OrderedSocketData data(reads, arraysize(reads),
2869 writes, arraysize(writes));
2870 RunServerPushTest(&data,
2871 &response,
2872 &response2,
2873 expected_push_result);
2875 // Verify the SYN_REPLY.
2876 EXPECT_TRUE(response.headers.get() != NULL);
2877 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2879 // Verify the pushed stream.
2880 EXPECT_TRUE(response2.headers.get() != NULL);
2881 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2884 TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
2885 scoped_ptr<SpdyFrame> stream1_syn(
2886 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2887 scoped_ptr<SpdyFrame> stream1_body(
2888 spdy_util_.ConstructSpdyBodyFrame(1, true));
2889 MockWrite writes[] = {
2890 CreateMockWrite(*stream1_syn, 1),
2893 scoped_ptr<SpdyFrame>
2894 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2895 scoped_ptr<SpdyFrame>
2896 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2900 "http://www.google.com/foo.dat"));
2901 static const char kPushedData[] = "pushed my darling hello my baby";
2902 scoped_ptr<SpdyFrame> stream2_body_base(
2903 spdy_util_.ConstructSpdyBodyFrame(
2904 2, kPushedData, strlen(kPushedData), true));
2905 const size_t kChunkSize = strlen(kPushedData) / 4;
2906 scoped_ptr<SpdyFrame> stream2_body1(
2907 new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
2908 scoped_ptr<SpdyFrame> stream2_body2(
2909 new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
2910 scoped_ptr<SpdyFrame> stream2_body3(
2911 new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
2912 kChunkSize, false));
2913 scoped_ptr<SpdyFrame> stream2_body4(
2914 new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
2915 stream2_body_base->size() - 3 * kChunkSize, false));
2916 MockRead reads[] = {
2917 CreateMockRead(*stream1_reply, 2),
2918 CreateMockRead(*stream2_syn, 3),
2919 CreateMockRead(*stream2_body1, 4),
2920 CreateMockRead(*stream2_body2, 5),
2921 CreateMockRead(*stream2_body3, 6),
2922 CreateMockRead(*stream2_body4, 7),
2923 CreateMockRead(*stream1_body, 8, SYNCHRONOUS),
2924 MockRead(ASYNC, ERR_IO_PENDING, 9), // Force a pause
2927 HttpResponseInfo response;
2928 HttpResponseInfo response2;
2929 std::string expected_push_result("pushed my darling hello my baby");
2930 OrderedSocketData data(reads, arraysize(reads),
2931 writes, arraysize(writes));
2932 RunServerPushTest(&data, &response, &response2, kPushedData);
2934 // Verify the SYN_REPLY.
2935 EXPECT_TRUE(response.headers.get() != NULL);
2936 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2938 // Verify the pushed stream.
2939 EXPECT_TRUE(response2.headers.get() != NULL);
2940 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2943 TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
2944 scoped_ptr<SpdyFrame> stream1_syn(
2945 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2946 scoped_ptr<SpdyFrame> stream1_body(
2947 spdy_util_.ConstructSpdyBodyFrame(1, true));
2948 MockWrite writes[] = {
2949 CreateMockWrite(*stream1_syn, 1),
2952 scoped_ptr<SpdyFrame>
2953 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2954 scoped_ptr<SpdyFrame>
2955 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2959 "http://www.google.com/foo.dat"));
2960 static const char kPushedData[] = "pushed my darling hello my baby";
2961 scoped_ptr<SpdyFrame> stream2_body_base(
2962 spdy_util_.ConstructSpdyBodyFrame(
2963 2, kPushedData, strlen(kPushedData), true));
2964 const size_t kChunkSize = strlen(kPushedData) / 4;
2965 scoped_ptr<SpdyFrame> stream2_body1(
2966 new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
2967 scoped_ptr<SpdyFrame> stream2_body2(
2968 new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
2969 scoped_ptr<SpdyFrame> stream2_body3(
2970 new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
2971 kChunkSize, false));
2972 scoped_ptr<SpdyFrame> stream2_body4(
2973 new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
2974 stream2_body_base->size() - 3 * kChunkSize, false));
2975 MockRead reads[] = {
2976 CreateMockRead(*stream1_reply, 2),
2977 CreateMockRead(*stream2_syn, 3),
2978 CreateMockRead(*stream2_body1, 4),
2979 CreateMockRead(*stream2_body2, 5),
2980 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2981 CreateMockRead(*stream2_body3, 7),
2982 CreateMockRead(*stream2_body4, 8),
2983 CreateMockRead(*stream1_body.get(), 9, SYNCHRONOUS),
2984 MockRead(ASYNC, ERR_IO_PENDING, 10) // Force a pause.
2987 HttpResponseInfo response;
2988 HttpResponseInfo response2;
2989 OrderedSocketData data(reads, arraysize(reads),
2990 writes, arraysize(writes));
2991 RunServerPushTest(&data, &response, &response2, kPushedData);
2993 // Verify the SYN_REPLY.
2994 EXPECT_TRUE(response.headers.get() != NULL);
2995 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2997 // Verify the pushed stream.
2998 EXPECT_TRUE(response2.headers.get() != NULL);
2999 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
3002 TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
3003 if (spdy_util_.spdy_version() == SPDY4) {
3004 // PUSH_PROMISE with stream id 0 is connection-level error.
3005 // TODO(baranovich): Test session going away.
3006 return;
3009 scoped_ptr<SpdyFrame> stream1_syn(
3010 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3011 scoped_ptr<SpdyFrame> stream1_body(
3012 spdy_util_.ConstructSpdyBodyFrame(1, true));
3013 scoped_ptr<SpdyFrame> stream2_rst(
3014 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
3015 MockWrite writes[] = {
3016 CreateMockWrite(*stream1_syn, 1),
3017 CreateMockWrite(*stream2_rst, 4),
3020 scoped_ptr<SpdyFrame>
3021 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3022 scoped_ptr<SpdyFrame>
3023 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
3027 "http://www.google.com/foo.dat"));
3028 MockRead reads[] = {
3029 CreateMockRead(*stream1_reply, 2),
3030 CreateMockRead(*stream2_syn, 3),
3031 CreateMockRead(*stream1_body, 4),
3032 MockRead(ASYNC, ERR_IO_PENDING, 5) // Force a pause
3035 OrderedSocketData data(reads, arraysize(reads),
3036 writes, arraysize(writes));
3037 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3038 BoundNetLog(), GetParam(), NULL);
3040 helper.RunPreTestSetup();
3041 helper.AddData(&data);
3043 HttpNetworkTransaction* trans = helper.trans();
3045 // Start the transaction with basic parameters.
3046 TestCompletionCallback callback;
3047 int rv = trans->Start(
3048 &CreateGetRequest(), callback.callback(), BoundNetLog());
3049 EXPECT_EQ(ERR_IO_PENDING, rv);
3050 rv = callback.WaitForResult();
3051 EXPECT_EQ(OK, rv);
3053 // Verify that we consumed all test data.
3054 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3055 << data.read_count()
3056 << " Read index: "
3057 << data.read_index();
3058 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3059 << data.write_count()
3060 << " Write index: "
3061 << data.write_index();
3063 // Verify the SYN_REPLY.
3064 HttpResponseInfo response = *trans->GetResponseInfo();
3065 EXPECT_TRUE(response.headers.get() != NULL);
3066 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3069 TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
3070 scoped_ptr<SpdyFrame> stream1_syn(
3071 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3072 scoped_ptr<SpdyFrame> stream1_body(
3073 spdy_util_.ConstructSpdyBodyFrame(1, true));
3074 scoped_ptr<SpdyFrame> stream2_rst(
3075 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM));
3076 MockWrite writes[] = {
3077 CreateMockWrite(*stream1_syn, 1),
3078 CreateMockWrite(*stream2_rst, 4),
3081 scoped_ptr<SpdyFrame>
3082 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3083 scoped_ptr<SpdyFrame>
3084 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
3088 "http://www.google.com/foo.dat"));
3089 MockRead reads[] = {
3090 CreateMockRead(*stream1_reply, 2),
3091 CreateMockRead(*stream2_syn, 3),
3092 CreateMockRead(*stream1_body, 4),
3093 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
3096 OrderedSocketData data(reads, arraysize(reads),
3097 writes, arraysize(writes));
3098 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3099 BoundNetLog(), GetParam(), NULL);
3101 helper.RunPreTestSetup();
3102 helper.AddData(&data);
3104 HttpNetworkTransaction* trans = helper.trans();
3106 // Start the transaction with basic parameters.
3107 TestCompletionCallback callback;
3108 int rv = trans->Start(
3109 &CreateGetRequest(), callback.callback(), BoundNetLog());
3110 EXPECT_EQ(ERR_IO_PENDING, rv);
3111 rv = callback.WaitForResult();
3112 EXPECT_EQ(OK, rv);
3114 // Verify that we consumed all test data.
3115 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3116 << data.read_count()
3117 << " Read index: "
3118 << data.read_index();
3119 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3120 << data.write_count()
3121 << " Write index: "
3122 << data.write_index();
3124 // Verify the SYN_REPLY.
3125 HttpResponseInfo response = *trans->GetResponseInfo();
3126 EXPECT_TRUE(response.headers.get() != NULL);
3127 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3130 TEST_P(SpdyNetworkTransactionTest, ServerPushNoURL) {
3131 scoped_ptr<SpdyFrame> stream1_syn(
3132 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3133 scoped_ptr<SpdyFrame> stream1_body(
3134 spdy_util_.ConstructSpdyBodyFrame(1, true));
3135 scoped_ptr<SpdyFrame> stream2_rst(
3136 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
3137 MockWrite writes[] = {
3138 CreateMockWrite(*stream1_syn, 1),
3139 CreateMockWrite(*stream2_rst, 4),
3142 scoped_ptr<SpdyFrame>
3143 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3144 scoped_ptr<SpdyHeaderBlock> incomplete_headers(new SpdyHeaderBlock());
3145 (*incomplete_headers)["hello"] = "bye";
3146 (*incomplete_headers)[spdy_util_.GetStatusKey()] = "200 OK";
3147 (*incomplete_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
3148 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
3149 incomplete_headers.Pass(), 2, 1));
3150 MockRead reads[] = {
3151 CreateMockRead(*stream1_reply, 2),
3152 CreateMockRead(*stream2_syn, 3),
3153 CreateMockRead(*stream1_body, 4),
3154 MockRead(ASYNC, ERR_IO_PENDING, 5) // Force a pause
3157 OrderedSocketData data(reads, arraysize(reads),
3158 writes, arraysize(writes));
3159 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3160 BoundNetLog(), GetParam(), NULL);
3162 helper.RunPreTestSetup();
3163 helper.AddData(&data);
3165 HttpNetworkTransaction* trans = helper.trans();
3167 // Start the transaction with basic parameters.
3168 TestCompletionCallback callback;
3169 int rv = trans->Start(
3170 &CreateGetRequest(), callback.callback(), BoundNetLog());
3171 EXPECT_EQ(ERR_IO_PENDING, rv);
3172 rv = callback.WaitForResult();
3173 EXPECT_EQ(OK, rv);
3174 // Verify that we consumed all test data.
3175 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3176 << data.read_count()
3177 << " Read index: "
3178 << data.read_index();
3179 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3180 << data.write_count()
3181 << " Write index: "
3182 << data.write_index();
3184 // Verify the SYN_REPLY.
3185 HttpResponseInfo response = *trans->GetResponseInfo();
3186 EXPECT_TRUE(response.headers.get() != NULL);
3187 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3190 // Verify that various SynReply headers parse correctly through the
3191 // HTTP layer.
3192 TEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) {
3193 struct SynReplyHeadersTests {
3194 int num_headers;
3195 const char* extra_headers[5];
3196 SpdyHeaderBlock expected_headers;
3197 } test_cases[] = {
3198 // This uses a multi-valued cookie header.
3199 { 2,
3200 { "cookie", "val1",
3201 "cookie", "val2", // will get appended separated by NULL
3202 NULL
3205 // This is the minimalist set of headers.
3206 { 0,
3207 { NULL },
3209 // Headers with a comma separated list.
3210 { 1,
3211 { "cookie", "val1,val2",
3212 NULL
3217 test_cases[0].expected_headers["cookie"] = "val1";
3218 test_cases[0].expected_headers["cookie"] += '\0';
3219 test_cases[0].expected_headers["cookie"] += "val2";
3220 test_cases[0].expected_headers["hello"] = "bye";
3221 test_cases[0].expected_headers["status"] = "200";
3223 test_cases[1].expected_headers["hello"] = "bye";
3224 test_cases[1].expected_headers["status"] = "200";
3226 test_cases[2].expected_headers["cookie"] = "val1,val2";
3227 test_cases[2].expected_headers["hello"] = "bye";
3228 test_cases[2].expected_headers["status"] = "200";
3230 if (spdy_util_.spdy_version() < SPDY4) {
3231 // SPDY4/HTTP2 eliminates use of the :version header.
3232 test_cases[0].expected_headers["version"] = "HTTP/1.1";
3233 test_cases[1].expected_headers["version"] = "HTTP/1.1";
3234 test_cases[2].expected_headers["version"] = "HTTP/1.1";
3237 for (size_t i = 0; i < arraysize(test_cases); ++i) {
3238 scoped_ptr<SpdyFrame> req(
3239 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3240 MockWrite writes[] = { CreateMockWrite(*req) };
3242 scoped_ptr<SpdyFrame> resp(
3243 spdy_util_.ConstructSpdyGetSynReply(test_cases[i].extra_headers,
3244 test_cases[i].num_headers,
3245 1));
3246 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3247 MockRead reads[] = {
3248 CreateMockRead(*resp),
3249 CreateMockRead(*body),
3250 MockRead(ASYNC, 0, 0) // EOF
3253 DelayedSocketData data(1, reads, arraysize(reads),
3254 writes, arraysize(writes));
3255 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3256 BoundNetLog(), GetParam(), NULL);
3257 helper.RunToCompletion(&data);
3258 TransactionHelperResult out = helper.output();
3260 EXPECT_EQ(OK, out.rv);
3261 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3262 EXPECT_EQ("hello!", out.response_data);
3264 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3265 EXPECT_TRUE(headers.get() != NULL);
3266 void* iter = NULL;
3267 std::string name, value;
3268 SpdyHeaderBlock header_block;
3269 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3270 if (header_block[name].empty()) {
3271 header_block[name] = value;
3272 } else {
3273 header_block[name] += '\0';
3274 header_block[name] += value;
3277 EXPECT_EQ(test_cases[i].expected_headers, header_block);
3281 // Verify that various SynReply headers parse vary fields correctly
3282 // through the HTTP layer, and the response matches the request.
3283 TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) {
3284 // Modify the following data to change/add test cases:
3285 struct SynReplyTests {
3286 bool vary_matches;
3287 int num_headers[2];
3288 const char* extra_headers[2][16];
3289 } test_cases[] = {
3290 // Test the case of a multi-valued cookie. When the value is delimited
3291 // with NUL characters, it needs to be unfolded into multiple headers.
3293 true,
3294 { 1, 4 },
3295 { { "cookie", "val1,val2",
3296 NULL
3298 { "vary", "cookie",
3299 spdy_util_.GetStatusKey(), "200",
3300 spdy_util_.GetPathKey(), "/index.php",
3301 spdy_util_.GetVersionKey(), "HTTP/1.1",
3302 NULL
3305 }, { // Multiple vary fields.
3306 true,
3307 { 2, 5 },
3308 { { "friend", "barney",
3309 "enemy", "snaggletooth",
3310 NULL
3312 { "vary", "friend",
3313 "vary", "enemy",
3314 spdy_util_.GetStatusKey(), "200",
3315 spdy_util_.GetPathKey(), "/index.php",
3316 spdy_util_.GetVersionKey(), "HTTP/1.1",
3317 NULL
3320 }, { // Test a '*' vary field.
3321 false,
3322 { 1, 4 },
3323 { { "cookie", "val1,val2",
3324 NULL
3326 { "vary", "*",
3327 spdy_util_.GetStatusKey(), "200",
3328 spdy_util_.GetPathKey(), "/index.php",
3329 spdy_util_.GetVersionKey(), "HTTP/1.1",
3330 NULL
3333 }, { // Multiple comma-separated vary fields.
3334 true,
3335 { 2, 4 },
3336 { { "friend", "barney",
3337 "enemy", "snaggletooth",
3338 NULL
3340 { "vary", "friend,enemy",
3341 spdy_util_.GetStatusKey(), "200",
3342 spdy_util_.GetPathKey(), "/index.php",
3343 spdy_util_.GetVersionKey(), "HTTP/1.1",
3344 NULL
3350 for (size_t i = 0; i < arraysize(test_cases); ++i) {
3351 // Construct the request.
3352 scoped_ptr<SpdyFrame> frame_req(
3353 spdy_util_.ConstructSpdyGet(test_cases[i].extra_headers[0],
3354 test_cases[i].num_headers[0],
3355 false, 1, LOWEST, true));
3357 MockWrite writes[] = {
3358 CreateMockWrite(*frame_req),
3361 // Construct the reply.
3362 SpdyHeaderBlock reply_headers;
3363 AppendToHeaderBlock(test_cases[i].extra_headers[1],
3364 test_cases[i].num_headers[1],
3365 &reply_headers);
3366 scoped_ptr<SpdyFrame> frame_reply(
3367 spdy_util_.ConstructSpdyReply(1, reply_headers));
3369 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3370 MockRead reads[] = {
3371 CreateMockRead(*frame_reply),
3372 CreateMockRead(*body),
3373 MockRead(ASYNC, 0, 0) // EOF
3376 // Attach the headers to the request.
3377 int header_count = test_cases[i].num_headers[0];
3379 HttpRequestInfo request = CreateGetRequest();
3380 for (int ct = 0; ct < header_count; ct++) {
3381 const char* header_key = test_cases[i].extra_headers[0][ct * 2];
3382 const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1];
3383 request.extra_headers.SetHeader(header_key, header_value);
3386 DelayedSocketData data(1, reads, arraysize(reads),
3387 writes, arraysize(writes));
3388 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
3389 BoundNetLog(), GetParam(), NULL);
3390 helper.RunToCompletion(&data);
3391 TransactionHelperResult out = helper.output();
3393 EXPECT_EQ(OK, out.rv) << i;
3394 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line) << i;
3395 EXPECT_EQ("hello!", out.response_data) << i;
3397 // Test the response information.
3398 EXPECT_TRUE(out.response_info.response_time >
3399 out.response_info.request_time) << i;
3400 base::TimeDelta test_delay = out.response_info.response_time -
3401 out.response_info.request_time;
3402 base::TimeDelta min_expected_delay;
3403 min_expected_delay.FromMilliseconds(10);
3404 EXPECT_GT(test_delay.InMillisecondsF(),
3405 min_expected_delay.InMillisecondsF()) << i;
3406 EXPECT_EQ(out.response_info.vary_data.is_valid(),
3407 test_cases[i].vary_matches) << i;
3409 // Check the headers.
3410 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3411 ASSERT_TRUE(headers.get() != NULL) << i;
3412 void* iter = NULL;
3413 std::string name, value, lines;
3414 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3415 lines.append(name);
3416 lines.append(": ");
3417 lines.append(value);
3418 lines.append("\n");
3421 // Construct the expected header reply string.
3422 std::string expected_reply =
3423 spdy_util_.ConstructSpdyReplyString(reply_headers);
3424 EXPECT_EQ(expected_reply, lines) << i;
3428 // Verify that we don't crash on invalid SynReply responses.
3429 TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) {
3430 struct InvalidSynReplyTests {
3431 int num_headers;
3432 const char* headers[10];
3433 } test_cases[] = {
3434 // SYN_REPLY missing status header
3435 { 4,
3436 { "cookie", "val1",
3437 "cookie", "val2",
3438 spdy_util_.GetPathKey(), "/index.php",
3439 spdy_util_.GetVersionKey(), "HTTP/1.1",
3440 NULL
3443 // SYN_REPLY missing version header
3444 { 2,
3445 { "status", "200",
3446 spdy_util_.GetPathKey(), "/index.php",
3447 NULL
3450 // SYN_REPLY with no headers
3451 { 0, { NULL }, },
3454 for (size_t i = 0; i < arraysize(test_cases); ++i) {
3455 scoped_ptr<SpdyFrame> req(
3456 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3457 scoped_ptr<SpdyFrame> rst(
3458 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
3459 MockWrite writes[] = {
3460 CreateMockWrite(*req),
3461 CreateMockWrite(*rst),
3464 // Construct the reply.
3465 SpdyHeaderBlock reply_headers;
3466 AppendToHeaderBlock(
3467 test_cases[i].headers, test_cases[i].num_headers, &reply_headers);
3468 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyReply(1, reply_headers));
3469 MockRead reads[] = {
3470 CreateMockRead(*resp),
3471 MockRead(ASYNC, 0, 0) // EOF
3474 DelayedSocketData data(1, reads, arraysize(reads),
3475 writes, arraysize(writes));
3476 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3477 BoundNetLog(), GetParam(), NULL);
3478 helper.RunToCompletion(&data);
3479 TransactionHelperResult out = helper.output();
3480 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3484 // Verify that we don't crash on some corrupt frames.
3485 // TODO(jgraettinger): SPDY4 and up treats a header decompression failure as a
3486 // connection error. I'd like to backport this behavior to SPDY3 as well.
3487 TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
3488 if (spdy_util_.spdy_version() >= SPDY4) {
3489 return;
3491 // This is the length field that's too short.
3492 scoped_ptr<SpdyFrame> syn_reply_wrong_length(
3493 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3494 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3495 size_t right_size =
3496 (spdy_util_.spdy_version() < SPDY4) ?
3497 syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize() :
3498 syn_reply_wrong_length->size();
3499 size_t wrong_size = right_size - 4;
3500 test::SetFrameLength(syn_reply_wrong_length.get(),
3501 wrong_size,
3502 spdy_util_.spdy_version());
3504 struct SynReplyTests {
3505 const SpdyFrame* syn_reply;
3506 } test_cases[] = {
3507 { syn_reply_wrong_length.get(), },
3510 for (size_t i = 0; i < arraysize(test_cases); ++i) {
3511 scoped_ptr<SpdyFrame> req(
3512 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3513 scoped_ptr<SpdyFrame> rst(
3514 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
3515 MockWrite writes[] = {
3516 CreateMockWrite(*req),
3517 CreateMockWrite(*rst),
3520 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3521 MockRead reads[] = {
3522 MockRead(ASYNC, test_cases[i].syn_reply->data(), wrong_size),
3523 CreateMockRead(*body),
3524 MockRead(ASYNC, 0, 0) // EOF
3527 DelayedSocketData data(1, reads, arraysize(reads),
3528 writes, arraysize(writes));
3529 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3530 BoundNetLog(), GetParam(), NULL);
3531 helper.RunToCompletion(&data);
3532 TransactionHelperResult out = helper.output();
3533 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3537 // SPDY4 treats a header decompression failure as a connection-level error.
3538 TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionErrorSpdy4) {
3539 if (spdy_util_.spdy_version() < SPDY4) {
3540 return;
3542 // This is the length field that's too short.
3543 scoped_ptr<SpdyFrame> syn_reply_wrong_length(
3544 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3545 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3546 size_t right_size =
3547 syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize();
3548 size_t wrong_size = right_size - 4;
3549 test::SetFrameLength(syn_reply_wrong_length.get(),
3550 wrong_size,
3551 spdy_util_.spdy_version());
3553 scoped_ptr<SpdyFrame> req(
3554 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3555 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3556 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3557 MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*goaway)};
3559 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3560 MockRead reads[] = {
3561 MockRead(ASYNC, syn_reply_wrong_length->data(),
3562 syn_reply_wrong_length->size() - 4),
3565 DelayedSocketData data(1, reads, arraysize(reads),
3566 writes, arraysize(writes));
3567 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3568 BoundNetLog(), GetParam(), NULL);
3569 helper.RunToCompletion(&data);
3570 TransactionHelperResult out = helper.output();
3571 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
3574 TEST_P(SpdyNetworkTransactionTest, GoAwayOnDecompressionFailure) {
3575 if (GetParam().protocol < kProtoSPDY4MinimumVersion) {
3576 // Decompression failures are a stream error in SPDY3 and above.
3577 return;
3579 scoped_ptr<SpdyFrame> req(
3580 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3581 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3582 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3583 MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*goaway)};
3585 // Read HEADERS with corrupted payload.
3586 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3587 memset(resp->data() + 12, 0xff, resp->size() - 12);
3588 MockRead reads[] = {CreateMockRead(*resp)};
3590 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
3591 NormalSpdyTransactionHelper helper(
3592 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
3593 helper.RunToCompletion(&data);
3594 TransactionHelperResult out = helper.output();
3595 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
3598 TEST_P(SpdyNetworkTransactionTest, GoAwayOnFrameSizeError) {
3599 scoped_ptr<SpdyFrame> req(
3600 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3601 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3602 0, GOAWAY_PROTOCOL_ERROR, "Framer error: 1 (INVALID_CONTROL_FRAME)."));
3603 MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*goaway)};
3605 // Read WINDOW_UPDATE with incorrectly-sized payload.
3606 // TODO(jgraettinger): SpdyFramer signals this as an INVALID_CONTROL_FRAME,
3607 // which is mapped to a protocol error, and not a frame size error.
3608 scoped_ptr<SpdyFrame> bad_window_update(
3609 spdy_util_.ConstructSpdyWindowUpdate(1, 1));
3610 test::SetFrameLength(bad_window_update.get(),
3611 bad_window_update->size() - 1,
3612 spdy_util_.spdy_version());
3613 MockRead reads[] = {CreateMockRead(*bad_window_update)};
3615 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
3616 NormalSpdyTransactionHelper helper(
3617 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
3618 helper.RunToCompletion(&data);
3619 TransactionHelperResult out = helper.output();
3620 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3623 // Test that we shutdown correctly on write errors.
3624 TEST_P(SpdyNetworkTransactionTest, WriteError) {
3625 scoped_ptr<SpdyFrame> req(
3626 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3627 MockWrite writes[] = {
3628 // We'll write 10 bytes successfully
3629 MockWrite(ASYNC, req->data(), 10, 0),
3630 // Followed by ERROR!
3631 MockWrite(ASYNC, ERR_FAILED, 1),
3632 // Session drains and attempts to write a GOAWAY: Another ERROR!
3633 MockWrite(ASYNC, ERR_FAILED, 2),
3636 MockRead reads[] = {
3637 MockRead(ASYNC, 0, 3) // EOF
3640 DeterministicSocketData data(reads, arraysize(reads),
3641 writes, arraysize(writes));
3643 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3644 BoundNetLog(), GetParam(), NULL);
3645 helper.SetDeterministic();
3646 helper.RunPreTestSetup();
3647 helper.AddDeterministicData(&data);
3648 EXPECT_TRUE(helper.StartDefaultTest());
3649 data.RunFor(2);
3650 helper.FinishDefaultTest();
3651 EXPECT_TRUE(data.at_write_eof());
3652 EXPECT_TRUE(!data.at_read_eof());
3653 TransactionHelperResult out = helper.output();
3654 EXPECT_EQ(ERR_FAILED, out.rv);
3657 // Test that partial writes work.
3658 TEST_P(SpdyNetworkTransactionTest, PartialWrite) {
3659 // Chop the SYN_STREAM frame into 5 chunks.
3660 scoped_ptr<SpdyFrame> req(
3661 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3662 const int kChunks = 5;
3663 scoped_ptr<MockWrite[]> writes(ChopWriteFrame(*req.get(), kChunks));
3665 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3666 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3667 MockRead reads[] = {
3668 CreateMockRead(*resp),
3669 CreateMockRead(*body),
3670 MockRead(ASYNC, 0, 0) // EOF
3673 DelayedSocketData data(kChunks, reads, arraysize(reads),
3674 writes.get(), kChunks);
3675 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3676 BoundNetLog(), GetParam(), NULL);
3677 helper.RunToCompletion(&data);
3678 TransactionHelperResult out = helper.output();
3679 EXPECT_EQ(OK, out.rv);
3680 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3681 EXPECT_EQ("hello!", out.response_data);
3684 // In this test, we enable compression, but get a uncompressed SynReply from
3685 // the server. Verify that teardown is all clean.
3686 TEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) {
3687 if (spdy_util_.spdy_version() >= SPDY4) {
3688 // HPACK doesn't use deflate compression.
3689 return;
3691 scoped_ptr<SpdyFrame> compressed(
3692 spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, LOWEST, true));
3693 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3694 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3695 MockWrite writes[] = {CreateMockWrite(*compressed), CreateMockWrite(*goaway)};
3697 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3698 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3699 MockRead reads[] = {
3700 CreateMockRead(*resp),
3703 DelayedSocketData data(1, reads, arraysize(reads),
3704 writes, arraysize(writes));
3705 SpdySessionDependencies* session_deps =
3706 CreateSpdySessionDependencies(GetParam());
3707 session_deps->enable_compression = true;
3708 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3709 BoundNetLog(), GetParam(), session_deps);
3710 helper.RunToCompletion(&data);
3711 TransactionHelperResult out = helper.output();
3712 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
3713 data.Reset();
3716 // Test that the NetLog contains good data for a simple GET request.
3717 TEST_P(SpdyNetworkTransactionTest, NetLog) {
3718 static const char* const kExtraHeaders[] = {
3719 "user-agent", "Chrome",
3721 scoped_ptr<SpdyFrame> req(
3722 spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, false, 1, LOWEST, true));
3723 MockWrite writes[] = { CreateMockWrite(*req) };
3725 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3726 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3727 MockRead reads[] = {
3728 CreateMockRead(*resp),
3729 CreateMockRead(*body),
3730 MockRead(ASYNC, 0, 0) // EOF
3733 CapturingBoundNetLog log;
3735 DelayedSocketData data(1, reads, arraysize(reads),
3736 writes, arraysize(writes));
3737 NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(),
3738 DEFAULT_PRIORITY,
3739 log.bound(), GetParam(), NULL);
3740 helper.RunToCompletion(&data);
3741 TransactionHelperResult out = helper.output();
3742 EXPECT_EQ(OK, out.rv);
3743 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3744 EXPECT_EQ("hello!", out.response_data);
3746 // Check that the NetLog was filled reasonably.
3747 // This test is intentionally non-specific about the exact ordering of the
3748 // log; instead we just check to make sure that certain events exist, and that
3749 // they are in the right order.
3750 CapturingNetLog::CapturedEntryList entries;
3751 log.GetEntries(&entries);
3753 EXPECT_LT(0u, entries.size());
3754 int pos = 0;
3755 pos = ExpectLogContainsSomewhere(entries, 0,
3756 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3757 NetLog::PHASE_BEGIN);
3758 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3759 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3760 NetLog::PHASE_END);
3761 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3762 NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3763 NetLog::PHASE_BEGIN);
3764 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3765 NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3766 NetLog::PHASE_END);
3767 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3768 NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3769 NetLog::PHASE_BEGIN);
3770 pos = ExpectLogContainsSomewhere(entries, pos + 1,
3771 NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3772 NetLog::PHASE_END);
3774 // Check that we logged all the headers correctly
3775 const NetLog::EventType type = (GetParam().protocol <= kProtoSPDY31)
3776 ? NetLog::TYPE_HTTP2_SESSION_SYN_STREAM
3777 : NetLog::TYPE_HTTP2_SESSION_SEND_HEADERS;
3778 pos = ExpectLogContainsSomewhere(entries, 0, type, NetLog::PHASE_NONE);
3780 base::ListValue* header_list;
3781 ASSERT_TRUE(entries[pos].params.get());
3782 ASSERT_TRUE(entries[pos].params->GetList("headers", &header_list));
3784 std::vector<std::string> expected;
3785 expected.push_back(std::string(spdy_util_.GetHostKey()) + ": www.google.com");
3786 expected.push_back(std::string(spdy_util_.GetPathKey()) + ": /");
3787 expected.push_back(std::string(spdy_util_.GetSchemeKey()) + ": http");
3788 expected.push_back(std::string(spdy_util_.GetMethodKey()) + ": GET");
3789 expected.push_back("user-agent: Chrome");
3790 if (spdy_util_.spdy_version() < SPDY4) {
3791 // SPDY4/HTTP2 eliminates use of the :version header.
3792 expected.push_back(std::string(spdy_util_.GetVersionKey()) + ": HTTP/1.1");
3794 EXPECT_EQ(expected.size(), header_list->GetSize());
3795 for (std::vector<std::string>::const_iterator it = expected.begin();
3796 it != expected.end();
3797 ++it) {
3798 base::StringValue header(*it);
3799 EXPECT_NE(header_list->end(), header_list->Find(header)) <<
3800 "Header not found: " << *it;
3804 // Since we buffer the IO from the stream to the renderer, this test verifies
3805 // that when we read out the maximum amount of data (e.g. we received 50 bytes
3806 // on the network, but issued a Read for only 5 of those bytes) that the data
3807 // flow still works correctly.
3808 TEST_P(SpdyNetworkTransactionTest, BufferFull) {
3809 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3811 scoped_ptr<SpdyFrame> req(
3812 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3813 MockWrite writes[] = { CreateMockWrite(*req) };
3815 // 2 data frames in a single read.
3816 scoped_ptr<SpdyFrame> data_frame_1(
3817 framer.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE));
3818 scoped_ptr<SpdyFrame> data_frame_2(
3819 framer.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE));
3820 const SpdyFrame* data_frames[2] = {
3821 data_frame_1.get(),
3822 data_frame_2.get(),
3824 char combined_data_frames[100];
3825 int combined_data_frames_len =
3826 CombineFrames(data_frames, arraysize(data_frames),
3827 combined_data_frames, arraysize(combined_data_frames));
3828 scoped_ptr<SpdyFrame> last_frame(
3829 framer.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN));
3831 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3832 MockRead reads[] = {
3833 CreateMockRead(*resp),
3834 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3835 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
3836 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3837 CreateMockRead(*last_frame),
3838 MockRead(ASYNC, 0, 0) // EOF
3841 DelayedSocketData data(1, reads, arraysize(reads),
3842 writes, arraysize(writes));
3844 TestCompletionCallback callback;
3846 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3847 BoundNetLog(), GetParam(), NULL);
3848 helper.RunPreTestSetup();
3849 helper.AddData(&data);
3850 HttpNetworkTransaction* trans = helper.trans();
3851 int rv = trans->Start(
3852 &CreateGetRequest(), callback.callback(), BoundNetLog());
3853 EXPECT_EQ(ERR_IO_PENDING, rv);
3855 TransactionHelperResult out = helper.output();
3856 out.rv = callback.WaitForResult();
3857 EXPECT_EQ(out.rv, OK);
3859 const HttpResponseInfo* response = trans->GetResponseInfo();
3860 EXPECT_TRUE(response->headers.get() != NULL);
3861 EXPECT_TRUE(response->was_fetched_via_spdy);
3862 out.status_line = response->headers->GetStatusLine();
3863 out.response_info = *response; // Make a copy so we can verify.
3865 // Read Data
3866 TestCompletionCallback read_callback;
3868 std::string content;
3869 do {
3870 // Read small chunks at a time.
3871 const int kSmallReadSize = 3;
3872 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
3873 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
3874 if (rv == ERR_IO_PENDING) {
3875 data.CompleteRead();
3876 rv = read_callback.WaitForResult();
3878 if (rv > 0) {
3879 content.append(buf->data(), rv);
3880 } else if (rv < 0) {
3881 NOTREACHED();
3883 } while (rv > 0);
3885 out.response_data.swap(content);
3887 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3888 // MockClientSocketFactory) are still alive.
3889 base::RunLoop().RunUntilIdle();
3891 // Verify that we consumed all test data.
3892 helper.VerifyDataConsumed();
3894 EXPECT_EQ(OK, out.rv);
3895 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3896 EXPECT_EQ("goodbye world", out.response_data);
3899 // Verify that basic buffering works; when multiple data frames arrive
3900 // at the same time, ensure that we don't notify a read completion for
3901 // each data frame individually.
3902 TEST_P(SpdyNetworkTransactionTest, Buffering) {
3903 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3905 scoped_ptr<SpdyFrame> req(
3906 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3907 MockWrite writes[] = { CreateMockWrite(*req) };
3909 // 4 data frames in a single read.
3910 scoped_ptr<SpdyFrame> data_frame(
3911 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
3912 scoped_ptr<SpdyFrame> data_frame_fin(
3913 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
3914 const SpdyFrame* data_frames[4] = {
3915 data_frame.get(),
3916 data_frame.get(),
3917 data_frame.get(),
3918 data_frame_fin.get()
3920 char combined_data_frames[100];
3921 int combined_data_frames_len =
3922 CombineFrames(data_frames, arraysize(data_frames),
3923 combined_data_frames, arraysize(combined_data_frames));
3925 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3926 MockRead reads[] = {
3927 CreateMockRead(*resp),
3928 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3929 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
3930 MockRead(ASYNC, 0, 0) // EOF
3933 DelayedSocketData data(1, reads, arraysize(reads),
3934 writes, arraysize(writes));
3936 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3937 BoundNetLog(), GetParam(), NULL);
3938 helper.RunPreTestSetup();
3939 helper.AddData(&data);
3940 HttpNetworkTransaction* trans = helper.trans();
3942 TestCompletionCallback callback;
3943 int rv = trans->Start(
3944 &CreateGetRequest(), callback.callback(), BoundNetLog());
3945 EXPECT_EQ(ERR_IO_PENDING, rv);
3947 TransactionHelperResult out = helper.output();
3948 out.rv = callback.WaitForResult();
3949 EXPECT_EQ(out.rv, OK);
3951 const HttpResponseInfo* response = trans->GetResponseInfo();
3952 EXPECT_TRUE(response->headers.get() != NULL);
3953 EXPECT_TRUE(response->was_fetched_via_spdy);
3954 out.status_line = response->headers->GetStatusLine();
3955 out.response_info = *response; // Make a copy so we can verify.
3957 // Read Data
3958 TestCompletionCallback read_callback;
3960 std::string content;
3961 int reads_completed = 0;
3962 do {
3963 // Read small chunks at a time.
3964 const int kSmallReadSize = 14;
3965 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
3966 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
3967 if (rv == ERR_IO_PENDING) {
3968 data.CompleteRead();
3969 rv = read_callback.WaitForResult();
3971 if (rv > 0) {
3972 EXPECT_EQ(kSmallReadSize, rv);
3973 content.append(buf->data(), rv);
3974 } else if (rv < 0) {
3975 FAIL() << "Unexpected read error: " << rv;
3977 reads_completed++;
3978 } while (rv > 0);
3980 EXPECT_EQ(3, reads_completed); // Reads are: 14 bytes, 14 bytes, 0 bytes.
3982 out.response_data.swap(content);
3984 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3985 // MockClientSocketFactory) are still alive.
3986 base::RunLoop().RunUntilIdle();
3988 // Verify that we consumed all test data.
3989 helper.VerifyDataConsumed();
3991 EXPECT_EQ(OK, out.rv);
3992 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3993 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3996 // Verify the case where we buffer data but read it after it has been buffered.
3997 TEST_P(SpdyNetworkTransactionTest, BufferedAll) {
3998 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4000 scoped_ptr<SpdyFrame> req(
4001 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4002 MockWrite writes[] = { CreateMockWrite(*req) };
4004 // 5 data frames in a single read.
4005 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4006 scoped_ptr<SpdyFrame> data_frame(
4007 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4008 scoped_ptr<SpdyFrame> data_frame_fin(
4009 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
4010 const SpdyFrame* frames[5] = {reply.get(), data_frame.get(), data_frame.get(),
4011 data_frame.get(), data_frame_fin.get()};
4012 char combined_frames[200];
4013 int combined_frames_len =
4014 CombineFrames(frames, arraysize(frames),
4015 combined_frames, arraysize(combined_frames));
4017 MockRead reads[] = {
4018 MockRead(ASYNC, combined_frames, combined_frames_len),
4019 MockRead(ASYNC, 0, 0) // EOF
4022 DelayedSocketData data(1, reads, arraysize(reads),
4023 writes, arraysize(writes));
4025 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4026 BoundNetLog(), GetParam(), NULL);
4027 helper.RunPreTestSetup();
4028 helper.AddData(&data);
4029 HttpNetworkTransaction* trans = helper.trans();
4031 TestCompletionCallback callback;
4032 int rv = trans->Start(
4033 &CreateGetRequest(), callback.callback(), BoundNetLog());
4034 EXPECT_EQ(ERR_IO_PENDING, rv);
4036 TransactionHelperResult out = helper.output();
4037 out.rv = callback.WaitForResult();
4038 EXPECT_EQ(out.rv, OK);
4040 const HttpResponseInfo* response = trans->GetResponseInfo();
4041 EXPECT_TRUE(response->headers.get() != NULL);
4042 EXPECT_TRUE(response->was_fetched_via_spdy);
4043 out.status_line = response->headers->GetStatusLine();
4044 out.response_info = *response; // Make a copy so we can verify.
4046 // Read Data
4047 TestCompletionCallback read_callback;
4049 std::string content;
4050 int reads_completed = 0;
4051 do {
4052 // Read small chunks at a time.
4053 const int kSmallReadSize = 14;
4054 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
4055 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
4056 if (rv > 0) {
4057 EXPECT_EQ(kSmallReadSize, rv);
4058 content.append(buf->data(), rv);
4059 } else if (rv < 0) {
4060 FAIL() << "Unexpected read error: " << rv;
4062 reads_completed++;
4063 } while (rv > 0);
4065 EXPECT_EQ(3, reads_completed);
4067 out.response_data.swap(content);
4069 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4070 // MockClientSocketFactory) are still alive.
4071 base::RunLoop().RunUntilIdle();
4073 // Verify that we consumed all test data.
4074 helper.VerifyDataConsumed();
4076 EXPECT_EQ(OK, out.rv);
4077 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4078 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
4081 // Verify the case where we buffer data and close the connection.
4082 TEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
4083 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4085 scoped_ptr<SpdyFrame> req(
4086 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4087 MockWrite writes[] = { CreateMockWrite(*req) };
4089 // All data frames in a single read.
4090 // NOTE: We don't FIN the stream.
4091 scoped_ptr<SpdyFrame> data_frame(
4092 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4093 const SpdyFrame* data_frames[4] = {
4094 data_frame.get(),
4095 data_frame.get(),
4096 data_frame.get(),
4097 data_frame.get()
4099 char combined_data_frames[100];
4100 int combined_data_frames_len =
4101 CombineFrames(data_frames, arraysize(data_frames),
4102 combined_data_frames, arraysize(combined_data_frames));
4103 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4104 MockRead reads[] = {
4105 CreateMockRead(*resp),
4106 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait
4107 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
4108 MockRead(ASYNC, 0, 0) // EOF
4111 DelayedSocketData data(1, reads, arraysize(reads),
4112 writes, arraysize(writes));
4114 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4115 BoundNetLog(), GetParam(), NULL);
4116 helper.RunPreTestSetup();
4117 helper.AddData(&data);
4118 HttpNetworkTransaction* trans = helper.trans();
4120 TestCompletionCallback callback;
4122 int rv = trans->Start(
4123 &CreateGetRequest(), callback.callback(), BoundNetLog());
4124 EXPECT_EQ(ERR_IO_PENDING, rv);
4126 TransactionHelperResult out = helper.output();
4127 out.rv = callback.WaitForResult();
4128 EXPECT_EQ(out.rv, OK);
4130 const HttpResponseInfo* response = trans->GetResponseInfo();
4131 EXPECT_TRUE(response->headers.get() != NULL);
4132 EXPECT_TRUE(response->was_fetched_via_spdy);
4133 out.status_line = response->headers->GetStatusLine();
4134 out.response_info = *response; // Make a copy so we can verify.
4136 // Read Data
4137 TestCompletionCallback read_callback;
4139 std::string content;
4140 int reads_completed = 0;
4141 do {
4142 // Read small chunks at a time.
4143 const int kSmallReadSize = 14;
4144 scoped_refptr<IOBuffer> buf(new IOBuffer(kSmallReadSize));
4145 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
4146 if (rv == ERR_IO_PENDING) {
4147 data.CompleteRead();
4148 rv = read_callback.WaitForResult();
4150 if (rv > 0) {
4151 content.append(buf->data(), rv);
4152 } else if (rv < 0) {
4153 // This test intentionally closes the connection, and will get an error.
4154 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
4155 break;
4157 reads_completed++;
4158 } while (rv > 0);
4160 EXPECT_EQ(0, reads_completed);
4162 out.response_data.swap(content);
4164 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4165 // MockClientSocketFactory) are still alive.
4166 base::RunLoop().RunUntilIdle();
4168 // Verify that we consumed all test data.
4169 helper.VerifyDataConsumed();
4172 // Verify the case where we buffer data and cancel the transaction.
4173 TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) {
4174 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4176 scoped_ptr<SpdyFrame> req(
4177 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4178 scoped_ptr<SpdyFrame> rst(
4179 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
4180 MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*rst)};
4182 // NOTE: We don't FIN the stream.
4183 scoped_ptr<SpdyFrame> data_frame(
4184 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4186 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4187 MockRead reads[] = {
4188 CreateMockRead(*resp),
4189 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait
4190 CreateMockRead(*data_frame),
4191 MockRead(ASYNC, 0, 0) // EOF
4194 DelayedSocketData data(1, reads, arraysize(reads),
4195 writes, arraysize(writes));
4197 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4198 BoundNetLog(), GetParam(), NULL);
4199 helper.RunPreTestSetup();
4200 helper.AddData(&data);
4201 HttpNetworkTransaction* trans = helper.trans();
4202 TestCompletionCallback callback;
4204 int rv = trans->Start(
4205 &CreateGetRequest(), callback.callback(), BoundNetLog());
4206 EXPECT_EQ(ERR_IO_PENDING, rv);
4208 TransactionHelperResult out = helper.output();
4209 out.rv = callback.WaitForResult();
4210 EXPECT_EQ(out.rv, OK);
4212 const HttpResponseInfo* response = trans->GetResponseInfo();
4213 EXPECT_TRUE(response->headers.get() != NULL);
4214 EXPECT_TRUE(response->was_fetched_via_spdy);
4215 out.status_line = response->headers->GetStatusLine();
4216 out.response_info = *response; // Make a copy so we can verify.
4218 // Read Data
4219 TestCompletionCallback read_callback;
4221 const int kReadSize = 256;
4222 scoped_refptr<IOBuffer> buf(new IOBuffer(kReadSize));
4223 rv = trans->Read(buf.get(), kReadSize, read_callback.callback());
4224 ASSERT_EQ(ERR_IO_PENDING, rv) << "Unexpected read: " << rv;
4226 // Complete the read now, which causes buffering to start.
4227 data.CompleteRead();
4228 // Destroy the transaction, causing the stream to get cancelled
4229 // and orphaning the buffered IO task.
4230 helper.ResetTrans();
4232 // Flush the MessageLoop; this will cause the buffered IO task
4233 // to run for the final time.
4234 base::RunLoop().RunUntilIdle();
4236 // Verify that we consumed all test data.
4237 helper.VerifyDataConsumed();
4240 // Test that if the server requests persistence of settings, that we save
4241 // the settings in the HttpServerProperties.
4242 TEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
4243 if (spdy_util_.spdy_version() >= SPDY4) {
4244 // SPDY4 doesn't support settings persistence.
4245 return;
4247 static const SpdyHeaderInfo kSynReplyInfo = {
4248 SYN_REPLY, // Syn Reply
4249 1, // Stream ID
4250 0, // Associated Stream ID
4251 ConvertRequestPriorityToSpdyPriority(
4252 LOWEST, spdy_util_.spdy_version()),
4253 kSpdyCredentialSlotUnused,
4254 CONTROL_FLAG_NONE, // Control Flags
4255 false, // Compressed
4256 RST_STREAM_INVALID, // Status
4257 NULL, // Data
4258 0, // Data Length
4259 DATA_FLAG_NONE // Data Flags
4262 BoundNetLog net_log;
4263 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4264 net_log, GetParam(), NULL);
4265 helper.RunPreTestSetup();
4267 // Verify that no settings exist initially.
4268 HostPortPair host_port_pair("www.google.com", helper.port());
4269 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4270 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4271 host_port_pair).empty());
4273 // Construct the request.
4274 scoped_ptr<SpdyFrame> req(
4275 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4276 MockWrite writes[] = { CreateMockWrite(*req) };
4278 // Construct the reply.
4279 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4280 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4281 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
4282 scoped_ptr<SpdyFrame> reply(
4283 spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
4285 const SpdySettingsIds kSampleId1 = SETTINGS_UPLOAD_BANDWIDTH;
4286 unsigned int kSampleValue1 = 0x0a0a0a0a;
4287 const SpdySettingsIds kSampleId2 = SETTINGS_DOWNLOAD_BANDWIDTH;
4288 unsigned int kSampleValue2 = 0x0b0b0b0b;
4289 const SpdySettingsIds kSampleId3 = SETTINGS_ROUND_TRIP_TIME;
4290 unsigned int kSampleValue3 = 0x0c0c0c0c;
4291 scoped_ptr<SpdyFrame> settings_frame;
4293 // Construct the SETTINGS frame.
4294 SettingsMap settings;
4295 // First add a persisted setting.
4296 settings[kSampleId1] =
4297 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue1);
4298 // Next add a non-persisted setting.
4299 settings[kSampleId2] =
4300 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kSampleValue2);
4301 // Next add another persisted setting.
4302 settings[kSampleId3] =
4303 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue3);
4304 settings_frame.reset(spdy_util_.ConstructSpdySettings(settings));
4307 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4308 MockRead reads[] = {
4309 CreateMockRead(*reply),
4310 CreateMockRead(*body),
4311 CreateMockRead(*settings_frame),
4312 MockRead(ASYNC, 0, 0) // EOF
4315 DelayedSocketData data(1, reads, arraysize(reads),
4316 writes, arraysize(writes));
4317 helper.AddData(&data);
4318 helper.RunDefaultTest();
4319 helper.VerifyDataConsumed();
4320 TransactionHelperResult out = helper.output();
4321 EXPECT_EQ(OK, out.rv);
4322 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4323 EXPECT_EQ("hello!", out.response_data);
4326 // Verify we had two persisted settings.
4327 const SettingsMap& settings_map =
4328 spdy_session_pool->http_server_properties()->GetSpdySettings(
4329 host_port_pair);
4330 ASSERT_EQ(2u, settings_map.size());
4332 // Verify the first persisted setting.
4333 SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4334 EXPECT_TRUE(it1 != settings_map.end());
4335 SettingsFlagsAndValue flags_and_value1 = it1->second;
4336 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4337 EXPECT_EQ(kSampleValue1, flags_and_value1.second);
4339 // Verify the second persisted setting.
4340 SettingsMap::const_iterator it3 = settings_map.find(kSampleId3);
4341 EXPECT_TRUE(it3 != settings_map.end());
4342 SettingsFlagsAndValue flags_and_value3 = it3->second;
4343 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value3.first);
4344 EXPECT_EQ(kSampleValue3, flags_and_value3.second);
4348 // Test that when there are settings saved that they are sent back to the
4349 // server upon session establishment.
4350 TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) {
4351 if (spdy_util_.spdy_version() >= SPDY4) {
4352 // SPDY4 doesn't support settings persistence.
4353 return;
4355 static const SpdyHeaderInfo kSynReplyInfo = {
4356 SYN_REPLY, // Syn Reply
4357 1, // Stream ID
4358 0, // Associated Stream ID
4359 ConvertRequestPriorityToSpdyPriority(
4360 LOWEST, spdy_util_.spdy_version()),
4361 kSpdyCredentialSlotUnused,
4362 CONTROL_FLAG_NONE, // Control Flags
4363 false, // Compressed
4364 RST_STREAM_INVALID, // Status
4365 NULL, // Data
4366 0, // Data Length
4367 DATA_FLAG_NONE // Data Flags
4370 BoundNetLog net_log;
4371 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4372 net_log, GetParam(), NULL);
4373 helper.RunPreTestSetup();
4375 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4377 SpdySessionPoolPeer pool_peer(spdy_session_pool);
4378 pool_peer.SetEnableSendingInitialData(true);
4380 // Verify that no settings exist initially.
4381 HostPortPair host_port_pair("www.google.com", helper.port());
4382 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4383 host_port_pair).empty());
4385 const SpdySettingsIds kSampleId1 = SETTINGS_MAX_CONCURRENT_STREAMS;
4386 unsigned int kSampleValue1 = 0x0a0a0a0a;
4387 const SpdySettingsIds kSampleId2 = SETTINGS_INITIAL_WINDOW_SIZE;
4388 unsigned int kSampleValue2 = 0x0c0c0c0c;
4390 // First add a persisted setting.
4391 spdy_session_pool->http_server_properties()->SetSpdySetting(
4392 host_port_pair,
4393 kSampleId1,
4394 SETTINGS_FLAG_PLEASE_PERSIST,
4395 kSampleValue1);
4397 // Next add another persisted setting.
4398 spdy_session_pool->http_server_properties()->SetSpdySetting(
4399 host_port_pair,
4400 kSampleId2,
4401 SETTINGS_FLAG_PLEASE_PERSIST,
4402 kSampleValue2);
4404 EXPECT_EQ(2u, spdy_session_pool->http_server_properties()->GetSpdySettings(
4405 host_port_pair).size());
4407 // Construct the initial SETTINGS frame.
4408 SettingsMap initial_settings;
4409 initial_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4410 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
4411 scoped_ptr<SpdyFrame> initial_settings_frame(
4412 spdy_util_.ConstructSpdySettings(initial_settings));
4414 // Construct the initial window update.
4415 scoped_ptr<SpdyFrame> initial_window_update(
4416 spdy_util_.ConstructSpdyWindowUpdate(
4417 kSessionFlowControlStreamId,
4418 kDefaultInitialRecvWindowSize -
4419 SpdySession::GetInitialWindowSize(GetParam().protocol)));
4421 // Construct the persisted SETTINGS frame.
4422 const SettingsMap& settings =
4423 spdy_session_pool->http_server_properties()->GetSpdySettings(
4424 host_port_pair);
4425 scoped_ptr<SpdyFrame> settings_frame(
4426 spdy_util_.ConstructSpdySettings(settings));
4428 // Construct the request.
4429 scoped_ptr<SpdyFrame> req(
4430 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4432 std::vector<MockWrite> writes;
4433 if ((GetParam().protocol >= kProtoSPDY4MinimumVersion) &&
4434 (GetParam().protocol <= kProtoSPDY4MaximumVersion)) {
4435 writes.push_back(
4436 MockWrite(ASYNC,
4437 kHttp2ConnectionHeaderPrefix,
4438 kHttp2ConnectionHeaderPrefixSize));
4440 writes.push_back(CreateMockWrite(*initial_settings_frame));
4441 if (GetParam().protocol >= kProtoSPDY31) {
4442 writes.push_back(CreateMockWrite(*initial_window_update));
4444 writes.push_back(CreateMockWrite(*settings_frame));
4445 writes.push_back(CreateMockWrite(*req));
4447 // Construct the reply.
4448 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4449 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4450 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
4451 scoped_ptr<SpdyFrame> reply(
4452 spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
4454 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4455 MockRead reads[] = {
4456 CreateMockRead(*reply),
4457 CreateMockRead(*body),
4458 MockRead(ASYNC, 0, 0) // EOF
4461 DelayedSocketData data(2, reads, arraysize(reads),
4462 vector_as_array(&writes), writes.size());
4463 helper.AddData(&data);
4464 helper.RunDefaultTest();
4465 helper.VerifyDataConsumed();
4466 TransactionHelperResult out = helper.output();
4467 EXPECT_EQ(OK, out.rv);
4468 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4469 EXPECT_EQ("hello!", out.response_data);
4472 // Verify we had two persisted settings.
4473 const SettingsMap& settings_map =
4474 spdy_session_pool->http_server_properties()->GetSpdySettings(
4475 host_port_pair);
4476 ASSERT_EQ(2u, settings_map.size());
4478 // Verify the first persisted setting.
4479 SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4480 EXPECT_TRUE(it1 != settings_map.end());
4481 SettingsFlagsAndValue flags_and_value1 = it1->second;
4482 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4483 EXPECT_EQ(kSampleValue1, flags_and_value1.second);
4485 // Verify the second persisted setting.
4486 SettingsMap::const_iterator it2 = settings_map.find(kSampleId2);
4487 EXPECT_TRUE(it2 != settings_map.end());
4488 SettingsFlagsAndValue flags_and_value2 = it2->second;
4489 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value2.first);
4490 EXPECT_EQ(kSampleValue2, flags_and_value2.second);
4494 TEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
4495 scoped_ptr<SpdyFrame> req(
4496 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4497 MockWrite writes[] = { CreateMockWrite(*req) };
4499 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway());
4500 MockRead reads[] = {
4501 CreateMockRead(*go_away),
4504 DelayedSocketData data(1, reads, arraysize(reads),
4505 writes, arraysize(writes));
4506 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4507 BoundNetLog(), GetParam(), NULL);
4508 helper.AddData(&data);
4509 helper.RunToCompletion(&data);
4510 TransactionHelperResult out = helper.output();
4511 EXPECT_EQ(ERR_ABORTED, out.rv);
4514 TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) {
4515 scoped_ptr<SpdyFrame> req(
4516 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4517 MockWrite writes[] = { CreateMockWrite(*req) };
4519 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4520 MockRead reads[] = {
4521 CreateMockRead(*resp),
4522 MockRead(SYNCHRONOUS, 0, 0) // EOF
4525 DelayedSocketData data(1, reads, arraysize(reads),
4526 writes, arraysize(writes));
4527 BoundNetLog log;
4528 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4529 log, GetParam(), NULL);
4530 helper.RunPreTestSetup();
4531 helper.AddData(&data);
4532 HttpNetworkTransaction* trans = helper.trans();
4534 TestCompletionCallback callback;
4535 TransactionHelperResult out;
4536 out.rv = trans->Start(&CreateGetRequest(), callback.callback(), log);
4538 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4539 out.rv = callback.WaitForResult();
4540 EXPECT_EQ(out.rv, OK);
4542 const HttpResponseInfo* response = trans->GetResponseInfo();
4543 EXPECT_TRUE(response->headers.get() != NULL);
4544 EXPECT_TRUE(response->was_fetched_via_spdy);
4545 out.rv = ReadTransaction(trans, &out.response_data);
4546 EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv);
4548 // Verify that we consumed all test data.
4549 helper.VerifyDataConsumed();
4552 // HTTP_1_1_REQUIRED results in ERR_HTTP_1_1_REQUIRED.
4553 TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredError) {
4554 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4555 if (spdy_util_.spdy_version() < SPDY4)
4556 return;
4558 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4559 BoundNetLog(), GetParam(), nullptr);
4561 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway(
4562 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
4563 MockRead reads[] = {
4564 CreateMockRead(*go_away),
4566 DelayedSocketData data(0, reads, arraysize(reads), nullptr, 0);
4568 helper.RunToCompletion(&data);
4569 TransactionHelperResult out = helper.output();
4570 EXPECT_EQ(ERR_HTTP_1_1_REQUIRED, out.rv);
4573 // Retry with HTTP/1.1 when receiving HTTP_1_1_REQUIRED. Note that no actual
4574 // protocol negotiation happens, instead this test forces protocols for both
4575 // sockets.
4576 TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredRetry) {
4577 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4578 if (spdy_util_.spdy_version() < SPDY4)
4579 return;
4580 // HTTP_1_1_REQUIRED implementation relies on the assumption that HTTP/2 is
4581 // only spoken over SSL.
4582 if (GetParam().ssl_type != SPDYSSL)
4583 return;
4585 HttpRequestInfo request;
4586 request.method = "GET";
4587 request.url = GURL("https://www.google.com/");
4588 scoped_ptr<SpdySessionDependencies> session_deps(
4589 CreateSpdySessionDependencies(GetParam()));
4590 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
4591 session_deps->force_spdy_over_ssl = false;
4592 session_deps->force_spdy_always = false;
4593 session_deps->next_protos = SpdyNextProtos();
4594 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
4595 GetParam(), session_deps.release());
4597 // First socket: HTTP/2 request rejected with HTTP_1_1_REQUIRED.
4598 const char* url = "https://www.google.com/";
4599 scoped_ptr<SpdyHeaderBlock> headers(spdy_util_.ConstructGetHeaderBlock(url));
4600 scoped_ptr<SpdyFrame> req(
4601 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
4602 MockWrite writes0[] = {CreateMockWrite(*req)};
4603 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway(
4604 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
4605 MockRead reads0[] = {CreateMockRead(*go_away)};
4606 DelayedSocketData data0(1, reads0, arraysize(reads0), writes0,
4607 arraysize(writes0));
4609 scoped_ptr<SSLSocketDataProvider> ssl_provider0(
4610 new SSLSocketDataProvider(ASYNC, OK));
4611 // Expect HTTP/2 protocols too in SSLConfig.
4612 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4613 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY31);
4614 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY4_14);
4615 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY4);
4616 // Force SPDY.
4617 ssl_provider0->SetNextProto(GetParam().protocol);
4618 helper.AddDataWithSSLSocketDataProvider(&data0, ssl_provider0.Pass());
4620 // Second socket: falling back to HTTP/1.1.
4621 MockWrite writes1[] = {MockWrite(
4622 "GET / HTTP/1.1\r\n"
4623 "Host: www.google.com\r\n"
4624 "Connection: keep-alive\r\n\r\n")};
4625 MockRead reads1[] = {MockRead(
4626 "HTTP/1.1 200 OK\r\n"
4627 "Content-Length: 5\r\n\r\n"
4628 "hello")};
4629 DelayedSocketData data1(1, reads1, arraysize(reads1), writes1,
4630 arraysize(writes1));
4632 scoped_ptr<SSLSocketDataProvider> ssl_provider1(
4633 new SSLSocketDataProvider(ASYNC, OK));
4634 // Expect only HTTP/1.1 protocol in SSLConfig.
4635 ssl_provider1->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4636 // Force HTTP/1.1.
4637 ssl_provider1->SetNextProto(kProtoHTTP11);
4638 helper.AddDataWithSSLSocketDataProvider(&data1, ssl_provider1.Pass());
4640 base::WeakPtr<HttpServerProperties> http_server_properties =
4641 helper.session()->spdy_session_pool()->http_server_properties();
4642 const HostPortPair host_port_pair = HostPortPair::FromURL(GURL(url));
4643 EXPECT_FALSE(http_server_properties->RequiresHTTP11(host_port_pair));
4645 helper.RunPreTestSetup();
4646 helper.StartDefaultTest();
4647 helper.FinishDefaultTestWithoutVerification();
4648 helper.VerifyDataConsumed();
4649 EXPECT_TRUE(http_server_properties->RequiresHTTP11(host_port_pair));
4651 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
4652 ASSERT_TRUE(response != nullptr);
4653 ASSERT_TRUE(response->headers.get() != nullptr);
4654 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4655 EXPECT_FALSE(response->was_fetched_via_spdy);
4656 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1, response->connection_info);
4657 EXPECT_TRUE(response->was_npn_negotiated);
4658 EXPECT_TRUE(request.url.SchemeIs("https"));
4659 EXPECT_EQ("127.0.0.1", response->socket_address.host());
4660 EXPECT_EQ(443, response->socket_address.port());
4661 std::string response_data;
4662 ASSERT_EQ(OK, ReadTransaction(helper.trans(), &response_data));
4663 EXPECT_EQ("hello", response_data);
4666 // Retry with HTTP/1.1 to the proxy when receiving HTTP_1_1_REQUIRED from the
4667 // proxy. Note that no actual protocol negotiation happens, instead this test
4668 // forces protocols for both sockets.
4669 TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredProxyRetry) {
4670 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4671 if (spdy_util_.spdy_version() < SPDY4)
4672 return;
4673 // HTTP_1_1_REQUIRED implementation relies on the assumption that HTTP/2 is
4674 // only spoken over SSL.
4675 if (GetParam().ssl_type != SPDYSSL)
4676 return;
4678 HttpRequestInfo request;
4679 request.method = "GET";
4680 request.url = GURL("https://www.google.com/");
4681 scoped_ptr<SpdySessionDependencies> session_deps(
4682 CreateSpdySessionDependencies(
4683 GetParam(),
4684 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70")));
4685 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
4686 session_deps->force_spdy_over_ssl = false;
4687 session_deps->force_spdy_always = false;
4688 session_deps->next_protos = SpdyNextProtos();
4689 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
4690 GetParam(), session_deps.release());
4692 // First socket: HTTP/2 CONNECT rejected with HTTP_1_1_REQUIRED.
4693 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(
4694 nullptr, 0, 1, LOWEST, HostPortPair("www.google.com", 443)));
4695 MockWrite writes0[] = {CreateMockWrite(*req)};
4696 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway(
4697 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
4698 MockRead reads0[] = {CreateMockRead(*go_away)};
4699 DelayedSocketData data0(1, reads0, arraysize(reads0), writes0,
4700 arraysize(writes0));
4702 scoped_ptr<SSLSocketDataProvider> ssl_provider0(
4703 new SSLSocketDataProvider(ASYNC, OK));
4704 // Expect HTTP/2 protocols too in SSLConfig.
4705 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4706 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY31);
4707 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY4_14);
4708 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY4);
4709 // Force SPDY.
4710 ssl_provider0->SetNextProto(GetParam().protocol);
4711 helper.AddDataWithSSLSocketDataProvider(&data0, ssl_provider0.Pass());
4713 // Second socket: retry using HTTP/1.1.
4714 MockWrite writes1[] = {
4715 MockWrite(ASYNC, 1,
4716 "CONNECT www.google.com:443 HTTP/1.1\r\n"
4717 "Host: www.google.com\r\n"
4718 "Proxy-Connection: keep-alive\r\n\r\n"),
4719 MockWrite(ASYNC, 3,
4720 "GET / HTTP/1.1\r\n"
4721 "Host: www.google.com\r\n"
4722 "Connection: keep-alive\r\n\r\n"),
4725 MockRead reads1[] = {
4726 MockRead(ASYNC, 2, "HTTP/1.1 200 OK\r\n\r\n"),
4727 MockRead(ASYNC, 4,
4728 "HTTP/1.1 200 OK\r\n"
4729 "Content-Length: 5\r\n\r\n"
4730 "hello"),
4732 DelayedSocketData data1(1, reads1, arraysize(reads1), writes1,
4733 arraysize(writes1));
4735 scoped_ptr<SSLSocketDataProvider> ssl_provider1(
4736 new SSLSocketDataProvider(ASYNC, OK));
4737 // Expect only HTTP/1.1 protocol in SSLConfig.
4738 ssl_provider1->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4739 // Force HTTP/1.1.
4740 ssl_provider1->SetNextProto(kProtoHTTP11);
4741 helper.AddDataWithSSLSocketDataProvider(&data1, ssl_provider1.Pass());
4743 // A third socket is needed for the tunnelled connection.
4744 scoped_ptr<SSLSocketDataProvider> ssl_provider2(
4745 new SSLSocketDataProvider(ASYNC, OK));
4746 helper.session_deps()->socket_factory->AddSSLSocketDataProvider(
4747 ssl_provider2.get());
4749 base::WeakPtr<HttpServerProperties> http_server_properties =
4750 helper.session()->spdy_session_pool()->http_server_properties();
4751 const HostPortPair proxy_host_port_pair = HostPortPair("myproxy", 70);
4752 EXPECT_FALSE(http_server_properties->RequiresHTTP11(proxy_host_port_pair));
4754 helper.RunPreTestSetup();
4755 helper.StartDefaultTest();
4756 helper.FinishDefaultTestWithoutVerification();
4757 helper.VerifyDataConsumed();
4758 EXPECT_TRUE(http_server_properties->RequiresHTTP11(proxy_host_port_pair));
4760 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
4761 ASSERT_TRUE(response != nullptr);
4762 ASSERT_TRUE(response->headers.get() != nullptr);
4763 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4764 EXPECT_FALSE(response->was_fetched_via_spdy);
4765 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1, response->connection_info);
4766 EXPECT_FALSE(response->was_npn_negotiated);
4767 EXPECT_TRUE(request.url.SchemeIs("https"));
4768 EXPECT_EQ("127.0.0.1", response->socket_address.host());
4769 EXPECT_EQ(70, response->socket_address.port());
4770 std::string response_data;
4771 ASSERT_EQ(OK, ReadTransaction(helper.trans(), &response_data));
4772 EXPECT_EQ("hello", response_data);
4775 // Test to make sure we can correctly connect through a proxy.
4776 TEST_P(SpdyNetworkTransactionTest, ProxyConnect) {
4777 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4778 BoundNetLog(), GetParam(), NULL);
4779 helper.session_deps().reset(CreateSpdySessionDependencies(
4780 GetParam(),
4781 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
4782 helper.SetSession(make_scoped_refptr(
4783 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
4784 helper.RunPreTestSetup();
4785 HttpNetworkTransaction* trans = helper.trans();
4787 const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4788 "Host: www.google.com\r\n"
4789 "Proxy-Connection: keep-alive\r\n\r\n"};
4790 const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4791 "Host: www.google.com\r\n"
4792 "Proxy-Connection: keep-alive\r\n\r\n"};
4793 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4794 scoped_ptr<SpdyFrame> req(
4795 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4796 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4797 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4799 MockWrite writes_SPDYNPN[] = {
4800 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4801 CreateMockWrite(*req, 2),
4803 MockRead reads_SPDYNPN[] = {
4804 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4805 CreateMockRead(*resp, 3),
4806 CreateMockRead(*body.get(), 4),
4807 MockRead(ASYNC, 0, 0, 5),
4810 MockWrite writes_SPDYSSL[] = {
4811 MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0),
4812 CreateMockWrite(*req, 2),
4814 MockRead reads_SPDYSSL[] = {
4815 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4816 CreateMockRead(*resp, 3),
4817 CreateMockRead(*body.get(), 4),
4818 MockRead(ASYNC, 0, 0, 5),
4821 MockWrite writes_SPDYNOSSL[] = {
4822 CreateMockWrite(*req, 0),
4825 MockRead reads_SPDYNOSSL[] = {
4826 CreateMockRead(*resp, 1),
4827 CreateMockRead(*body.get(), 2),
4828 MockRead(ASYNC, 0, 0, 3),
4831 scoped_ptr<OrderedSocketData> data;
4832 switch (GetParam().ssl_type) {
4833 case SPDYNOSSL:
4834 data.reset(new OrderedSocketData(reads_SPDYNOSSL,
4835 arraysize(reads_SPDYNOSSL),
4836 writes_SPDYNOSSL,
4837 arraysize(writes_SPDYNOSSL)));
4838 break;
4839 case SPDYSSL:
4840 data.reset(new OrderedSocketData(reads_SPDYSSL,
4841 arraysize(reads_SPDYSSL),
4842 writes_SPDYSSL,
4843 arraysize(writes_SPDYSSL)));
4844 break;
4845 case SPDYNPN:
4846 data.reset(new OrderedSocketData(reads_SPDYNPN,
4847 arraysize(reads_SPDYNPN),
4848 writes_SPDYNPN,
4849 arraysize(writes_SPDYNPN)));
4850 break;
4851 default:
4852 NOTREACHED();
4855 helper.AddData(data.get());
4856 TestCompletionCallback callback;
4858 int rv = trans->Start(
4859 &CreateGetRequest(), callback.callback(), BoundNetLog());
4860 EXPECT_EQ(ERR_IO_PENDING, rv);
4862 rv = callback.WaitForResult();
4863 EXPECT_EQ(0, rv);
4865 // Verify the SYN_REPLY.
4866 HttpResponseInfo response = *trans->GetResponseInfo();
4867 EXPECT_TRUE(response.headers.get() != NULL);
4868 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
4870 std::string response_data;
4871 ASSERT_EQ(OK, ReadTransaction(trans, &response_data));
4872 EXPECT_EQ("hello!", response_data);
4873 helper.VerifyDataConsumed();
4876 // Test to make sure we can correctly connect through a proxy to www.google.com,
4877 // if there already exists a direct spdy connection to www.google.com. See
4878 // http://crbug.com/49874
4879 TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
4880 // When setting up the first transaction, we store the SpdySessionPool so that
4881 // we can use the same pool in the second transaction.
4882 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4883 BoundNetLog(), GetParam(), NULL);
4885 // Use a proxy service which returns a proxy fallback list from DIRECT to
4886 // myproxy:70. For this test there will be no fallback, so it is equivalent
4887 // to simply DIRECT. The reason for appending the second proxy is to verify
4888 // that the session pool key used does is just "DIRECT".
4889 helper.session_deps().reset(CreateSpdySessionDependencies(
4890 GetParam(),
4891 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
4892 helper.SetSession(make_scoped_refptr(
4893 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
4895 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4896 helper.RunPreTestSetup();
4898 // Construct and send a simple GET request.
4899 scoped_ptr<SpdyFrame> req(
4900 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4901 MockWrite writes[] = {
4902 CreateMockWrite(*req, 1),
4905 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4906 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4907 MockRead reads[] = {
4908 CreateMockRead(*resp, 2),
4909 CreateMockRead(*body, 3),
4910 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause
4911 MockRead(ASYNC, 0, 5) // EOF
4913 OrderedSocketData data(reads, arraysize(reads),
4914 writes, arraysize(writes));
4915 helper.AddData(&data);
4916 HttpNetworkTransaction* trans = helper.trans();
4918 TestCompletionCallback callback;
4919 TransactionHelperResult out;
4920 out.rv = trans->Start(
4921 &CreateGetRequest(), callback.callback(), BoundNetLog());
4923 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4924 out.rv = callback.WaitForResult();
4925 EXPECT_EQ(out.rv, OK);
4927 const HttpResponseInfo* response = trans->GetResponseInfo();
4928 EXPECT_TRUE(response->headers.get() != NULL);
4929 EXPECT_TRUE(response->was_fetched_via_spdy);
4930 out.rv = ReadTransaction(trans, &out.response_data);
4931 EXPECT_EQ(OK, out.rv);
4932 out.status_line = response->headers->GetStatusLine();
4933 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4934 EXPECT_EQ("hello!", out.response_data);
4936 // Check that the SpdySession is still in the SpdySessionPool.
4937 HostPortPair host_port_pair("www.google.com", helper.port());
4938 SpdySessionKey session_pool_key_direct(
4939 host_port_pair, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
4940 EXPECT_TRUE(HasSpdySession(spdy_session_pool, session_pool_key_direct));
4941 SpdySessionKey session_pool_key_proxy(
4942 host_port_pair,
4943 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP),
4944 PRIVACY_MODE_DISABLED);
4945 EXPECT_FALSE(HasSpdySession(spdy_session_pool, session_pool_key_proxy));
4947 // Set up data for the proxy connection.
4948 const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4949 "Host: www.google.com\r\n"
4950 "Proxy-Connection: keep-alive\r\n\r\n"};
4951 const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4952 "Host: www.google.com\r\n"
4953 "Proxy-Connection: keep-alive\r\n\r\n"};
4954 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4955 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyGet(
4956 "http://www.google.com/foo.dat", false, 1, LOWEST));
4957 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4958 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
4960 MockWrite writes_SPDYNPN[] = {
4961 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4962 CreateMockWrite(*req2, 2),
4964 MockRead reads_SPDYNPN[] = {
4965 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4966 CreateMockRead(*resp2, 3),
4967 CreateMockRead(*body2, 4),
4968 MockRead(ASYNC, 0, 5) // EOF
4971 MockWrite writes_SPDYNOSSL[] = {
4972 CreateMockWrite(*req2, 0),
4974 MockRead reads_SPDYNOSSL[] = {
4975 CreateMockRead(*resp2, 1),
4976 CreateMockRead(*body2, 2),
4977 MockRead(ASYNC, 0, 3) // EOF
4980 MockWrite writes_SPDYSSL[] = {
4981 MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0),
4982 CreateMockWrite(*req2, 2),
4984 MockRead reads_SPDYSSL[] = {
4985 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4986 CreateMockRead(*resp2, 3),
4987 CreateMockRead(*body2, 4),
4988 MockRead(ASYNC, 0, 0, 5),
4991 scoped_ptr<OrderedSocketData> data_proxy;
4992 switch (GetParam().ssl_type) {
4993 case SPDYNPN:
4994 data_proxy.reset(new OrderedSocketData(reads_SPDYNPN,
4995 arraysize(reads_SPDYNPN),
4996 writes_SPDYNPN,
4997 arraysize(writes_SPDYNPN)));
4998 break;
4999 case SPDYNOSSL:
5000 data_proxy.reset(new OrderedSocketData(reads_SPDYNOSSL,
5001 arraysize(reads_SPDYNOSSL),
5002 writes_SPDYNOSSL,
5003 arraysize(writes_SPDYNOSSL)));
5004 break;
5005 case SPDYSSL:
5006 data_proxy.reset(new OrderedSocketData(reads_SPDYSSL,
5007 arraysize(reads_SPDYSSL),
5008 writes_SPDYSSL,
5009 arraysize(writes_SPDYSSL)));
5010 break;
5011 default:
5012 NOTREACHED();
5015 // Create another request to www.google.com, but this time through a proxy.
5016 HttpRequestInfo request_proxy;
5017 request_proxy.method = "GET";
5018 request_proxy.url = GURL("http://www.google.com/foo.dat");
5019 request_proxy.load_flags = 0;
5020 scoped_ptr<SpdySessionDependencies> ssd_proxy(
5021 CreateSpdySessionDependencies(GetParam()));
5022 // Ensure that this transaction uses the same SpdySessionPool.
5023 scoped_refptr<HttpNetworkSession> session_proxy(
5024 SpdySessionDependencies::SpdyCreateSession(ssd_proxy.get()));
5025 NormalSpdyTransactionHelper helper_proxy(request_proxy, DEFAULT_PRIORITY,
5026 BoundNetLog(), GetParam(), NULL);
5027 HttpNetworkSessionPeer session_peer(session_proxy);
5028 scoped_ptr<ProxyService> proxy_service(
5029 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
5030 session_peer.SetProxyService(proxy_service.get());
5031 helper_proxy.session_deps().swap(ssd_proxy);
5032 helper_proxy.SetSession(session_proxy);
5033 helper_proxy.RunPreTestSetup();
5034 helper_proxy.AddData(data_proxy.get());
5036 HttpNetworkTransaction* trans_proxy = helper_proxy.trans();
5037 TestCompletionCallback callback_proxy;
5038 int rv = trans_proxy->Start(
5039 &request_proxy, callback_proxy.callback(), BoundNetLog());
5040 EXPECT_EQ(ERR_IO_PENDING, rv);
5041 rv = callback_proxy.WaitForResult();
5042 EXPECT_EQ(0, rv);
5044 HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo();
5045 EXPECT_TRUE(response_proxy.headers.get() != NULL);
5046 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy.headers->GetStatusLine());
5048 std::string response_data;
5049 ASSERT_EQ(OK, ReadTransaction(trans_proxy, &response_data));
5050 EXPECT_EQ("hello!", response_data);
5052 data.CompleteRead();
5053 helper_proxy.VerifyDataConsumed();
5056 // When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
5057 // on a new connection, if the connection was previously known to be good.
5058 // This can happen when a server reboots without saying goodbye, or when
5059 // we're behind a NAT that masked the RST.
5060 TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
5061 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5062 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
5063 MockRead reads[] = {
5064 CreateMockRead(*resp),
5065 CreateMockRead(*body),
5066 MockRead(ASYNC, ERR_IO_PENDING),
5067 MockRead(ASYNC, ERR_CONNECTION_RESET),
5070 MockRead reads2[] = {
5071 CreateMockRead(*resp),
5072 CreateMockRead(*body),
5073 MockRead(ASYNC, 0, 0) // EOF
5076 // This test has a couple of variants.
5077 enum {
5078 // Induce the RST while waiting for our transaction to send.
5079 VARIANT_RST_DURING_SEND_COMPLETION,
5080 // Induce the RST while waiting for our transaction to read.
5081 // In this case, the send completed - everything copied into the SNDBUF.
5082 VARIANT_RST_DURING_READ_COMPLETION
5085 for (int variant = VARIANT_RST_DURING_SEND_COMPLETION;
5086 variant <= VARIANT_RST_DURING_READ_COMPLETION;
5087 ++variant) {
5088 DelayedSocketData data1(1, reads, arraysize(reads), NULL, 0);
5090 DelayedSocketData data2(1, reads2, arraysize(reads2), NULL, 0);
5092 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5093 BoundNetLog(), GetParam(), NULL);
5094 helper.AddData(&data1);
5095 helper.AddData(&data2);
5096 helper.RunPreTestSetup();
5098 for (int i = 0; i < 2; ++i) {
5099 scoped_ptr<HttpNetworkTransaction> trans(
5100 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5102 TestCompletionCallback callback;
5103 int rv = trans->Start(
5104 &helper.request(), callback.callback(), BoundNetLog());
5105 EXPECT_EQ(ERR_IO_PENDING, rv);
5106 // On the second transaction, we trigger the RST.
5107 if (i == 1) {
5108 if (variant == VARIANT_RST_DURING_READ_COMPLETION) {
5109 // Writes to the socket complete asynchronously on SPDY by running
5110 // through the message loop. Complete the write here.
5111 base::RunLoop().RunUntilIdle();
5114 // Now schedule the ERR_CONNECTION_RESET.
5115 EXPECT_EQ(3u, data1.read_index());
5116 data1.CompleteRead();
5117 EXPECT_EQ(4u, data1.read_index());
5119 rv = callback.WaitForResult();
5120 EXPECT_EQ(OK, rv);
5122 const HttpResponseInfo* response = trans->GetResponseInfo();
5123 ASSERT_TRUE(response != NULL);
5124 EXPECT_TRUE(response->headers.get() != NULL);
5125 EXPECT_TRUE(response->was_fetched_via_spdy);
5126 std::string response_data;
5127 rv = ReadTransaction(trans.get(), &response_data);
5128 EXPECT_EQ(OK, rv);
5129 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5130 EXPECT_EQ("hello!", response_data);
5133 helper.VerifyDataConsumed();
5137 // Test that turning SPDY on and off works properly.
5138 TEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) {
5139 HttpStreamFactory::set_spdy_enabled(true);
5140 scoped_ptr<SpdyFrame> req(
5141 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5142 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
5144 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5145 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
5146 MockRead spdy_reads[] = {
5147 CreateMockRead(*resp),
5148 CreateMockRead(*body),
5149 MockRead(ASYNC, 0, 0) // EOF
5152 DelayedSocketData data(1, spdy_reads, arraysize(spdy_reads),
5153 spdy_writes, arraysize(spdy_writes));
5154 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5155 BoundNetLog(), GetParam(), NULL);
5156 helper.RunToCompletion(&data);
5157 TransactionHelperResult out = helper.output();
5158 EXPECT_EQ(OK, out.rv);
5159 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
5160 EXPECT_EQ("hello!", out.response_data);
5162 HttpStreamFactory::set_spdy_enabled(false);
5163 MockRead http_reads[] = {
5164 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5165 MockRead("hello from http"),
5166 MockRead(SYNCHRONOUS, OK),
5168 DelayedSocketData data2(1, http_reads, arraysize(http_reads), NULL, 0);
5169 NormalSpdyTransactionHelper helper2(CreateGetRequest(), DEFAULT_PRIORITY,
5170 BoundNetLog(), GetParam(), NULL);
5171 helper2.SetSpdyDisabled();
5172 helper2.RunToCompletion(&data2);
5173 TransactionHelperResult out2 = helper2.output();
5174 EXPECT_EQ(OK, out2.rv);
5175 EXPECT_EQ("HTTP/1.1 200 OK", out2.status_line);
5176 EXPECT_EQ("hello from http", out2.response_data);
5178 HttpStreamFactory::set_spdy_enabled(true);
5181 // Tests that Basic authentication works over SPDY
5182 TEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) {
5183 HttpStreamFactory::set_spdy_enabled(true);
5185 // The first request will be a bare GET, the second request will be a
5186 // GET with an Authorization header.
5187 scoped_ptr<SpdyFrame> req_get(
5188 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5189 const char* const kExtraAuthorizationHeaders[] = {
5190 "authorization", "Basic Zm9vOmJhcg=="
5192 scoped_ptr<SpdyFrame> req_get_authorization(
5193 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
5194 arraysize(kExtraAuthorizationHeaders) / 2,
5195 false, 3, LOWEST, true));
5196 MockWrite spdy_writes[] = {
5197 CreateMockWrite(*req_get, 1),
5198 CreateMockWrite(*req_get_authorization, 4),
5201 // The first response is a 401 authentication challenge, and the second
5202 // response will be a 200 response since the second request includes a valid
5203 // Authorization header.
5204 const char* const kExtraAuthenticationHeaders[] = {
5205 "www-authenticate",
5206 "Basic realm=\"MyRealm\""
5208 scoped_ptr<SpdyFrame> resp_authentication(
5209 spdy_util_.ConstructSpdySynReplyError(
5210 "401 Authentication Required",
5211 kExtraAuthenticationHeaders,
5212 arraysize(kExtraAuthenticationHeaders) / 2,
5213 1));
5214 scoped_ptr<SpdyFrame> body_authentication(
5215 spdy_util_.ConstructSpdyBodyFrame(1, true));
5216 scoped_ptr<SpdyFrame> resp_data(
5217 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5218 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
5219 MockRead spdy_reads[] = {
5220 CreateMockRead(*resp_authentication, 2),
5221 CreateMockRead(*body_authentication, 3),
5222 CreateMockRead(*resp_data, 5),
5223 CreateMockRead(*body_data, 6),
5224 MockRead(ASYNC, 0, 7),
5227 OrderedSocketData data(spdy_reads, arraysize(spdy_reads),
5228 spdy_writes, arraysize(spdy_writes));
5229 HttpRequestInfo request(CreateGetRequest());
5230 BoundNetLog net_log;
5231 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5232 net_log, GetParam(), NULL);
5234 helper.RunPreTestSetup();
5235 helper.AddData(&data);
5236 HttpNetworkTransaction* trans = helper.trans();
5237 TestCompletionCallback callback;
5238 const int rv_start = trans->Start(&request, callback.callback(), net_log);
5239 EXPECT_EQ(ERR_IO_PENDING, rv_start);
5240 const int rv_start_complete = callback.WaitForResult();
5241 EXPECT_EQ(OK, rv_start_complete);
5243 // Make sure the response has an auth challenge.
5244 const HttpResponseInfo* const response_start = trans->GetResponseInfo();
5245 ASSERT_TRUE(response_start != NULL);
5246 ASSERT_TRUE(response_start->headers.get() != NULL);
5247 EXPECT_EQ(401, response_start->headers->response_code());
5248 EXPECT_TRUE(response_start->was_fetched_via_spdy);
5249 AuthChallengeInfo* auth_challenge = response_start->auth_challenge.get();
5250 ASSERT_TRUE(auth_challenge != NULL);
5251 EXPECT_FALSE(auth_challenge->is_proxy);
5252 EXPECT_EQ("basic", auth_challenge->scheme);
5253 EXPECT_EQ("MyRealm", auth_challenge->realm);
5255 // Restart with a username/password.
5256 AuthCredentials credentials(base::ASCIIToUTF16("foo"),
5257 base::ASCIIToUTF16("bar"));
5258 TestCompletionCallback callback_restart;
5259 const int rv_restart = trans->RestartWithAuth(
5260 credentials, callback_restart.callback());
5261 EXPECT_EQ(ERR_IO_PENDING, rv_restart);
5262 const int rv_restart_complete = callback_restart.WaitForResult();
5263 EXPECT_EQ(OK, rv_restart_complete);
5264 // TODO(cbentzel): This is actually the same response object as before, but
5265 // data has changed.
5266 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
5267 ASSERT_TRUE(response_restart != NULL);
5268 ASSERT_TRUE(response_restart->headers.get() != NULL);
5269 EXPECT_EQ(200, response_restart->headers->response_code());
5270 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
5273 TEST_P(SpdyNetworkTransactionTest, ServerPushWithHeaders) {
5274 scoped_ptr<SpdyFrame> stream1_syn(
5275 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5276 scoped_ptr<SpdyFrame> stream1_body(
5277 spdy_util_.ConstructSpdyBodyFrame(1, true));
5278 MockWrite writes[] = {
5279 CreateMockWrite(*stream1_syn, 1),
5282 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5283 spdy_util_.AddUrlToHeaderBlock(
5284 "http://www.google.com/foo.dat", initial_headers.get());
5285 scoped_ptr<SpdyFrame> stream2_syn(
5286 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
5288 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5289 (*late_headers)["hello"] = "bye";
5290 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5291 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5292 scoped_ptr<SpdyFrame> stream2_headers(
5293 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5294 false,
5296 LOWEST,
5297 HEADERS,
5298 CONTROL_FLAG_NONE,
5299 0));
5301 scoped_ptr<SpdyFrame>
5302 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5303 const char kPushedData[] = "pushed";
5304 scoped_ptr<SpdyFrame> stream2_body(
5305 spdy_util_.ConstructSpdyBodyFrame(
5306 2, kPushedData, strlen(kPushedData), true));
5307 MockRead reads[] = {
5308 CreateMockRead(*stream1_reply, 2),
5309 CreateMockRead(*stream2_syn, 3),
5310 CreateMockRead(*stream2_headers, 4),
5311 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
5312 CreateMockRead(*stream2_body, 5),
5313 MockRead(ASYNC, ERR_IO_PENDING, 7), // Force a pause
5316 HttpResponseInfo response;
5317 HttpResponseInfo response2;
5318 std::string expected_push_result("pushed");
5319 OrderedSocketData data(reads, arraysize(reads),
5320 writes, arraysize(writes));
5321 RunServerPushTest(&data,
5322 &response,
5323 &response2,
5324 expected_push_result);
5326 // Verify the SYN_REPLY.
5327 EXPECT_TRUE(response.headers.get() != NULL);
5328 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5330 // Verify the pushed stream.
5331 EXPECT_TRUE(response2.headers.get() != NULL);
5332 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5335 TEST_P(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
5336 // We push a stream and attempt to claim it before the headers come down.
5337 scoped_ptr<SpdyFrame> stream1_syn(
5338 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5339 scoped_ptr<SpdyFrame> stream1_body(
5340 spdy_util_.ConstructSpdyBodyFrame(1, true));
5341 MockWrite writes[] = {
5342 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5345 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5346 spdy_util_.AddUrlToHeaderBlock(
5347 "http://www.google.com/foo.dat", initial_headers.get());
5348 scoped_ptr<SpdyFrame> stream2_syn(
5349 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
5351 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5352 (*late_headers)["hello"] = "bye";
5353 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5354 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5355 scoped_ptr<SpdyFrame> stream2_headers(
5356 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5357 false,
5359 LOWEST,
5360 HEADERS,
5361 CONTROL_FLAG_NONE,
5362 0));
5364 scoped_ptr<SpdyFrame>
5365 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5366 const char kPushedData[] = "pushed";
5367 scoped_ptr<SpdyFrame> stream2_body(
5368 spdy_util_.ConstructSpdyBodyFrame(
5369 2, kPushedData, strlen(kPushedData), true));
5370 MockRead reads[] = {
5371 CreateMockRead(*stream1_reply, 1),
5372 CreateMockRead(*stream2_syn, 2),
5373 CreateMockRead(*stream1_body, 3),
5374 CreateMockRead(*stream2_headers, 4),
5375 CreateMockRead(*stream2_body, 5),
5376 MockRead(ASYNC, 0, 6), // EOF
5379 HttpResponseInfo response;
5380 HttpResponseInfo response2;
5381 std::string expected_push_result("pushed");
5382 DeterministicSocketData data(reads, arraysize(reads),
5383 writes, arraysize(writes));
5385 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5386 BoundNetLog(), GetParam(), NULL);
5387 helper.SetDeterministic();
5388 helper.AddDeterministicData(&data);
5389 helper.RunPreTestSetup();
5391 HttpNetworkTransaction* trans = helper.trans();
5393 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5394 // and the body of the primary stream, but before we've received the HEADERS
5395 // for the pushed stream.
5396 data.SetStop(3);
5398 // Start the transaction.
5399 TestCompletionCallback callback;
5400 int rv = trans->Start(
5401 &CreateGetRequest(), callback.callback(), BoundNetLog());
5402 EXPECT_EQ(ERR_IO_PENDING, rv);
5403 data.Run();
5404 rv = callback.WaitForResult();
5405 EXPECT_EQ(0, rv);
5407 // Request the pushed path. At this point, we've received the push, but the
5408 // headers are not yet complete.
5409 scoped_ptr<HttpNetworkTransaction> trans2(
5410 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5411 rv = trans2->Start(
5412 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5413 EXPECT_EQ(ERR_IO_PENDING, rv);
5414 data.RunFor(3);
5415 base::RunLoop().RunUntilIdle();
5417 // Read the server push body.
5418 std::string result2;
5419 ReadResult(trans2.get(), &data, &result2);
5420 // Read the response body.
5421 std::string result;
5422 ReadResult(trans, &data, &result);
5424 // Verify that the received push data is same as the expected push data.
5425 EXPECT_EQ(result2.compare(expected_push_result), 0)
5426 << "Received data: "
5427 << result2
5428 << "||||| Expected data: "
5429 << expected_push_result;
5431 // Verify the SYN_REPLY.
5432 // Copy the response info, because trans goes away.
5433 response = *trans->GetResponseInfo();
5434 response2 = *trans2->GetResponseInfo();
5436 VerifyStreamsClosed(helper);
5438 // Verify the SYN_REPLY.
5439 EXPECT_TRUE(response.headers.get() != NULL);
5440 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5442 // Verify the pushed stream.
5443 EXPECT_TRUE(response2.headers.get() != NULL);
5444 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5446 // Read the final EOF (which will close the session)
5447 data.RunFor(1);
5449 // Verify that we consumed all test data.
5450 EXPECT_TRUE(data.at_read_eof());
5451 EXPECT_TRUE(data.at_write_eof());
5454 // TODO(baranovich): HTTP 2 does not allow multiple HEADERS frames
5455 TEST_P(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) {
5456 // We push a stream and attempt to claim it before the headers come down.
5457 scoped_ptr<SpdyFrame> stream1_syn(
5458 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5459 scoped_ptr<SpdyFrame> stream1_body(
5460 spdy_util_.ConstructSpdyBodyFrame(1, true));
5461 MockWrite writes[] = {
5462 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5465 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5466 if (spdy_util_.spdy_version() < SPDY4) {
5467 // In SPDY4 PUSH_PROMISE headers won't show up in the response headers.
5468 (*initial_headers)["alpha"] = "beta";
5470 spdy_util_.AddUrlToHeaderBlock(
5471 "http://www.google.com/foo.dat", initial_headers.get());
5472 scoped_ptr<SpdyFrame> stream2_syn(
5473 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
5475 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5476 (*middle_headers)["hello"] = "bye";
5477 scoped_ptr<SpdyFrame> stream2_headers1(
5478 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(),
5479 false,
5481 LOWEST,
5482 HEADERS,
5483 CONTROL_FLAG_NONE,
5484 0));
5486 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5487 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5488 if (spdy_util_.spdy_version() < SPDY4) {
5489 // SPDY4/HTTP2 eliminates use of the :version header.
5490 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5492 scoped_ptr<SpdyFrame> stream2_headers2(
5493 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5494 false,
5496 LOWEST,
5497 HEADERS,
5498 CONTROL_FLAG_NONE,
5499 0));
5501 scoped_ptr<SpdyFrame>
5502 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5503 const char kPushedData[] = "pushed";
5504 scoped_ptr<SpdyFrame> stream2_body(
5505 spdy_util_.ConstructSpdyBodyFrame(
5506 2, kPushedData, strlen(kPushedData), true));
5507 MockRead reads[] = {
5508 CreateMockRead(*stream1_reply, 1),
5509 CreateMockRead(*stream2_syn, 2),
5510 CreateMockRead(*stream1_body, 3),
5511 CreateMockRead(*stream2_headers1, 4),
5512 CreateMockRead(*stream2_headers2, 5),
5513 CreateMockRead(*stream2_body, 6),
5514 MockRead(ASYNC, 0, 7), // EOF
5517 HttpResponseInfo response;
5518 HttpResponseInfo response2;
5519 std::string expected_push_result("pushed");
5520 DeterministicSocketData data(reads, arraysize(reads),
5521 writes, arraysize(writes));
5523 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5524 BoundNetLog(), GetParam(), NULL);
5525 helper.SetDeterministic();
5526 helper.AddDeterministicData(&data);
5527 helper.RunPreTestSetup();
5529 HttpNetworkTransaction* trans = helper.trans();
5531 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5532 // the first HEADERS frame, and the body of the primary stream, but before
5533 // we've received the final HEADERS for the pushed stream.
5534 data.SetStop(4);
5536 // Start the transaction.
5537 TestCompletionCallback callback;
5538 int rv = trans->Start(
5539 &CreateGetRequest(), callback.callback(), BoundNetLog());
5540 EXPECT_EQ(ERR_IO_PENDING, rv);
5541 data.Run();
5542 rv = callback.WaitForResult();
5543 EXPECT_EQ(0, rv);
5545 // Request the pushed path. At this point, we've received the push, but the
5546 // headers are not yet complete.
5547 scoped_ptr<HttpNetworkTransaction> trans2(
5548 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5549 rv = trans2->Start(
5550 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5551 EXPECT_EQ(ERR_IO_PENDING, rv);
5552 data.RunFor(3);
5553 base::RunLoop().RunUntilIdle();
5555 // Read the server push body.
5556 std::string result2;
5557 ReadResult(trans2.get(), &data, &result2);
5558 // Read the response body.
5559 std::string result;
5560 ReadResult(trans, &data, &result);
5562 // Verify that the received push data is same as the expected push data.
5563 EXPECT_EQ(expected_push_result, result2);
5565 // Verify the SYN_REPLY.
5566 // Copy the response info, because trans goes away.
5567 response = *trans->GetResponseInfo();
5568 response2 = *trans2->GetResponseInfo();
5570 VerifyStreamsClosed(helper);
5572 // Verify the SYN_REPLY.
5573 EXPECT_TRUE(response.headers.get() != NULL);
5574 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5576 // Verify the pushed stream.
5577 EXPECT_TRUE(response2.headers.get() != NULL);
5578 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5580 // Verify we got all the headers from all header blocks.
5581 if (spdy_util_.spdy_version() < SPDY4)
5582 EXPECT_TRUE(response2.headers->HasHeaderValue("alpha", "beta"));
5583 EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye"));
5584 EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200"));
5586 // Read the final EOF (which will close the session)
5587 data.RunFor(1);
5589 // Verify that we consumed all test data.
5590 EXPECT_TRUE(data.at_read_eof());
5591 EXPECT_TRUE(data.at_write_eof());
5594 TEST_P(SpdyNetworkTransactionTest, ServerPushWithNoStatusHeaderFrames) {
5595 // We push a stream and attempt to claim it before the headers come down.
5596 scoped_ptr<SpdyFrame> stream1_syn(
5597 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5598 scoped_ptr<SpdyFrame> stream1_body(
5599 spdy_util_.ConstructSpdyBodyFrame(1, true));
5600 MockWrite writes[] = {
5601 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5604 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5605 spdy_util_.AddUrlToHeaderBlock(
5606 "http://www.google.com/foo.dat", initial_headers.get());
5607 scoped_ptr<SpdyFrame> stream2_syn(
5608 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
5610 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5611 (*middle_headers)["hello"] = "bye";
5612 scoped_ptr<SpdyFrame> stream2_headers1(
5613 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(),
5614 false,
5616 LOWEST,
5617 HEADERS,
5618 CONTROL_FLAG_NONE,
5619 0));
5621 scoped_ptr<SpdyFrame>
5622 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5623 const char kPushedData[] = "pushed";
5624 scoped_ptr<SpdyFrame> stream2_body(
5625 spdy_util_.ConstructSpdyBodyFrame(
5626 2, kPushedData, strlen(kPushedData), true));
5627 MockRead reads[] = {
5628 CreateMockRead(*stream1_reply, 1),
5629 CreateMockRead(*stream2_syn, 2),
5630 CreateMockRead(*stream1_body, 3),
5631 CreateMockRead(*stream2_headers1, 4),
5632 CreateMockRead(*stream2_body, 5),
5633 MockRead(ASYNC, 0, 6), // EOF
5636 DeterministicSocketData data(reads, arraysize(reads),
5637 writes, arraysize(writes));
5639 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5640 BoundNetLog(), GetParam(), NULL);
5641 helper.SetDeterministic();
5642 helper.AddDeterministicData(&data);
5643 helper.RunPreTestSetup();
5645 HttpNetworkTransaction* trans = helper.trans();
5647 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5648 // the first HEADERS frame, and the body of the primary stream, but before
5649 // we've received the final HEADERS for the pushed stream.
5650 data.SetStop(4);
5652 // Start the transaction.
5653 TestCompletionCallback callback;
5654 int rv = trans->Start(
5655 &CreateGetRequest(), callback.callback(), BoundNetLog());
5656 EXPECT_EQ(ERR_IO_PENDING, rv);
5657 data.Run();
5658 rv = callback.WaitForResult();
5659 EXPECT_EQ(0, rv);
5661 // Request the pushed path. At this point, we've received the push, but the
5662 // headers are not yet complete.
5663 scoped_ptr<HttpNetworkTransaction> trans2(
5664 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5665 rv = trans2->Start(
5666 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5667 EXPECT_EQ(ERR_IO_PENDING, rv);
5668 data.RunFor(2);
5669 base::RunLoop().RunUntilIdle();
5671 // Read the server push body.
5672 std::string result2;
5673 ReadResult(trans2.get(), &data, &result2);
5674 // Read the response body.
5675 std::string result;
5676 ReadResult(trans, &data, &result);
5677 EXPECT_EQ("hello!", result);
5679 // Verify that we haven't received any push data.
5680 EXPECT_EQ("", result2);
5682 // Verify the SYN_REPLY.
5683 // Copy the response info, because trans goes away.
5684 HttpResponseInfo response = *trans->GetResponseInfo();
5685 ASSERT_TRUE(trans2->GetResponseInfo() == NULL);
5687 VerifyStreamsClosed(helper);
5689 // Verify the SYN_REPLY.
5690 EXPECT_TRUE(response.headers.get() != NULL);
5691 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5693 // Read the final EOF (which will close the session).
5694 data.RunFor(1);
5696 // Verify that we consumed all test data.
5697 EXPECT_TRUE(data.at_read_eof());
5698 EXPECT_TRUE(data.at_write_eof());
5701 TEST_P(SpdyNetworkTransactionTest, SynReplyWithHeaders) {
5702 scoped_ptr<SpdyFrame> req(
5703 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5704 scoped_ptr<SpdyFrame> rst(
5705 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
5706 MockWrite writes[] = {
5707 CreateMockWrite(*req), CreateMockWrite(*rst),
5710 scoped_ptr<SpdyFrame> stream1_reply(
5711 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5713 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5714 (*late_headers)["hello"] = "bye";
5715 scoped_ptr<SpdyFrame> stream1_headers(
5716 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5717 false,
5719 LOWEST,
5720 HEADERS,
5721 CONTROL_FLAG_NONE,
5722 0));
5723 scoped_ptr<SpdyFrame> stream1_body(
5724 spdy_util_.ConstructSpdyBodyFrame(1, true));
5725 MockRead reads[] = {
5726 CreateMockRead(*stream1_reply),
5727 CreateMockRead(*stream1_headers),
5728 CreateMockRead(*stream1_body),
5729 MockRead(ASYNC, 0, 0) // EOF
5732 DelayedSocketData data(1, reads, arraysize(reads),
5733 writes, arraysize(writes));
5734 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5735 BoundNetLog(), GetParam(), NULL);
5736 helper.RunToCompletion(&data);
5737 TransactionHelperResult out = helper.output();
5738 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
5741 TEST_P(SpdyNetworkTransactionTest, SynReplyWithLateHeaders) {
5742 scoped_ptr<SpdyFrame> req(
5743 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5744 scoped_ptr<SpdyFrame> rst(
5745 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
5746 MockWrite writes[] = {
5747 CreateMockWrite(*req),
5748 CreateMockWrite(*rst),
5751 scoped_ptr<SpdyFrame> stream1_reply(
5752 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5754 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5755 (*late_headers)["hello"] = "bye";
5756 scoped_ptr<SpdyFrame> stream1_headers(
5757 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5758 false,
5760 LOWEST,
5761 HEADERS,
5762 CONTROL_FLAG_NONE,
5763 0));
5764 scoped_ptr<SpdyFrame> stream1_body(
5765 spdy_util_.ConstructSpdyBodyFrame(1, false));
5766 scoped_ptr<SpdyFrame> stream1_body2(
5767 spdy_util_.ConstructSpdyBodyFrame(1, true));
5768 MockRead reads[] = {
5769 CreateMockRead(*stream1_reply),
5770 CreateMockRead(*stream1_body),
5771 CreateMockRead(*stream1_headers),
5772 CreateMockRead(*stream1_body2),
5773 MockRead(ASYNC, 0, 0) // EOF
5776 DelayedSocketData data(1, reads, arraysize(reads),
5777 writes, arraysize(writes));
5778 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5779 BoundNetLog(), GetParam(), NULL);
5780 helper.RunToCompletion(&data);
5781 TransactionHelperResult out = helper.output();
5782 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
5785 TEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
5786 // In this test we want to verify that we can't accidentally push content
5787 // which can't be pushed by this content server.
5788 // This test assumes that:
5789 // - if we're requesting http://www.foo.com/barbaz
5790 // - the browser has made a connection to "www.foo.com".
5792 // A list of the URL to fetch, followed by the URL being pushed.
5793 static const char* const kTestCases[] = {
5794 "http://www.google.com/foo.html",
5795 "http://www.google.com:81/foo.js", // Bad port
5797 "http://www.google.com/foo.html",
5798 "https://www.google.com/foo.js", // Bad protocol
5800 "http://www.google.com/foo.html",
5801 "ftp://www.google.com/foo.js", // Invalid Protocol
5803 "http://www.google.com/foo.html",
5804 "http://blat.www.google.com/foo.js", // Cross subdomain
5806 "http://www.google.com/foo.html",
5807 "http://www.foo.com/foo.js", // Cross domain
5810 for (size_t index = 0; index < arraysize(kTestCases); index += 2) {
5811 const char* url_to_fetch = kTestCases[index];
5812 const char* url_to_push = kTestCases[index + 1];
5814 scoped_ptr<SpdyFrame> stream1_syn(
5815 spdy_util_.ConstructSpdyGet(url_to_fetch, false, 1, LOWEST));
5816 scoped_ptr<SpdyFrame> stream1_body(
5817 spdy_util_.ConstructSpdyBodyFrame(1, true));
5818 scoped_ptr<SpdyFrame> push_rst(
5819 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
5820 MockWrite writes[] = {
5821 CreateMockWrite(*stream1_syn, 1),
5822 CreateMockWrite(*push_rst, 4),
5825 scoped_ptr<SpdyFrame>
5826 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5827 scoped_ptr<SpdyFrame>
5828 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
5832 url_to_push));
5833 const char kPushedData[] = "pushed";
5834 scoped_ptr<SpdyFrame> stream2_body(
5835 spdy_util_.ConstructSpdyBodyFrame(
5836 2, kPushedData, strlen(kPushedData), true));
5837 scoped_ptr<SpdyFrame> rst(
5838 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
5840 MockRead reads[] = {
5841 CreateMockRead(*stream1_reply, 2),
5842 CreateMockRead(*stream2_syn, 3),
5843 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
5844 CreateMockRead(*stream2_body, 6),
5845 MockRead(ASYNC, ERR_IO_PENDING, 7), // Force a pause
5848 HttpResponseInfo response;
5849 OrderedSocketData data(reads, arraysize(reads),
5850 writes, arraysize(writes));
5852 HttpRequestInfo request;
5853 request.method = "GET";
5854 request.url = GURL(url_to_fetch);
5855 request.load_flags = 0;
5857 // Enable cross-origin push. Since we are not using a proxy, this should
5858 // not actually enable cross-origin SPDY push.
5859 scoped_ptr<SpdySessionDependencies> session_deps(
5860 CreateSpdySessionDependencies(GetParam()));
5861 session_deps->trusted_spdy_proxy = "123.45.67.89:8080";
5862 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5863 BoundNetLog(), GetParam(),
5864 session_deps.release());
5865 helper.RunPreTestSetup();
5866 helper.AddData(&data);
5868 HttpNetworkTransaction* trans = helper.trans();
5870 // Start the transaction with basic parameters.
5871 TestCompletionCallback callback;
5873 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5874 EXPECT_EQ(ERR_IO_PENDING, rv);
5875 rv = callback.WaitForResult();
5877 // Read the response body.
5878 std::string result;
5879 ReadResult(trans, &data, &result);
5881 // Verify that we consumed all test data.
5882 EXPECT_TRUE(data.at_read_eof());
5883 EXPECT_TRUE(data.at_write_eof());
5885 // Verify the SYN_REPLY.
5886 // Copy the response info, because trans goes away.
5887 response = *trans->GetResponseInfo();
5889 VerifyStreamsClosed(helper);
5891 // Verify the SYN_REPLY.
5892 EXPECT_TRUE(response.headers.get() != NULL);
5893 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5897 TEST_P(SpdyNetworkTransactionTest, RetryAfterRefused) {
5898 // Construct the request.
5899 scoped_ptr<SpdyFrame> req(
5900 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5901 scoped_ptr<SpdyFrame> req2(
5902 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
5903 MockWrite writes[] = {
5904 CreateMockWrite(*req, 1),
5905 CreateMockWrite(*req2, 3),
5908 scoped_ptr<SpdyFrame> refused(
5909 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
5910 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5911 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(3, true));
5912 MockRead reads[] = {
5913 CreateMockRead(*refused, 2),
5914 CreateMockRead(*resp, 4),
5915 CreateMockRead(*body, 5),
5916 MockRead(ASYNC, 0, 6) // EOF
5919 OrderedSocketData data(reads, arraysize(reads),
5920 writes, arraysize(writes));
5921 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5922 BoundNetLog(), GetParam(), NULL);
5924 helper.RunPreTestSetup();
5925 helper.AddData(&data);
5927 HttpNetworkTransaction* trans = helper.trans();
5929 // Start the transaction with basic parameters.
5930 TestCompletionCallback callback;
5931 int rv = trans->Start(
5932 &CreateGetRequest(), callback.callback(), BoundNetLog());
5933 EXPECT_EQ(ERR_IO_PENDING, rv);
5934 rv = callback.WaitForResult();
5935 EXPECT_EQ(OK, rv);
5937 // Verify that we consumed all test data.
5938 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
5939 << data.read_count()
5940 << " Read index: "
5941 << data.read_index();
5942 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
5943 << data.write_count()
5944 << " Write index: "
5945 << data.write_index();
5947 // Verify the SYN_REPLY.
5948 HttpResponseInfo response = *trans->GetResponseInfo();
5949 EXPECT_TRUE(response.headers.get() != NULL);
5950 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5953 TEST_P(SpdyNetworkTransactionTest, OutOfOrderSynStream) {
5954 // This first request will start to establish the SpdySession.
5955 // Then we will start the second (MEDIUM priority) and then third
5956 // (HIGHEST priority) request in such a way that the third will actually
5957 // start before the second, causing the second to be numbered differently
5958 // than the order they were created.
5959 scoped_ptr<SpdyFrame> req1(
5960 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5961 scoped_ptr<SpdyFrame> req2(
5962 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, HIGHEST, true));
5963 scoped_ptr<SpdyFrame> req3(
5964 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, MEDIUM, true));
5965 MockWrite writes[] = {
5966 CreateMockWrite(*req1, 0),
5967 CreateMockWrite(*req2, 3),
5968 CreateMockWrite(*req3, 4),
5971 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5972 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
5973 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5974 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
5975 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
5976 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
5977 MockRead reads[] = {
5978 CreateMockRead(*resp1, 1),
5979 CreateMockRead(*body1, 2),
5980 CreateMockRead(*resp2, 5),
5981 CreateMockRead(*body2, 6),
5982 CreateMockRead(*resp3, 7),
5983 CreateMockRead(*body3, 8),
5984 MockRead(ASYNC, 0, 9) // EOF
5987 DeterministicSocketData data(reads, arraysize(reads),
5988 writes, arraysize(writes));
5989 NormalSpdyTransactionHelper helper(CreateGetRequest(), LOWEST,
5990 BoundNetLog(), GetParam(), NULL);
5991 helper.SetDeterministic();
5992 helper.RunPreTestSetup();
5993 helper.AddDeterministicData(&data);
5995 // Start the first transaction to set up the SpdySession
5996 HttpNetworkTransaction* trans = helper.trans();
5997 TestCompletionCallback callback;
5998 HttpRequestInfo info1 = CreateGetRequest();
5999 int rv = trans->Start(&info1, callback.callback(), BoundNetLog());
6000 EXPECT_EQ(ERR_IO_PENDING, rv);
6002 // Run the message loop, but do not allow the write to complete.
6003 // This leaves the SpdySession with a write pending, which prevents
6004 // SpdySession from attempting subsequent writes until this write completes.
6005 base::RunLoop().RunUntilIdle();
6007 // Now, start both new transactions
6008 HttpRequestInfo info2 = CreateGetRequest();
6009 TestCompletionCallback callback2;
6010 scoped_ptr<HttpNetworkTransaction> trans2(
6011 new HttpNetworkTransaction(MEDIUM, helper.session().get()));
6012 rv = trans2->Start(&info2, callback2.callback(), BoundNetLog());
6013 EXPECT_EQ(ERR_IO_PENDING, rv);
6014 base::RunLoop().RunUntilIdle();
6016 HttpRequestInfo info3 = CreateGetRequest();
6017 TestCompletionCallback callback3;
6018 scoped_ptr<HttpNetworkTransaction> trans3(
6019 new HttpNetworkTransaction(HIGHEST, helper.session().get()));
6020 rv = trans3->Start(&info3, callback3.callback(), BoundNetLog());
6021 EXPECT_EQ(ERR_IO_PENDING, rv);
6022 base::RunLoop().RunUntilIdle();
6024 // We now have two SYN_STREAM frames queued up which will be
6025 // dequeued only once the first write completes, which we
6026 // now allow to happen.
6027 data.RunFor(2);
6028 EXPECT_EQ(OK, callback.WaitForResult());
6030 // And now we can allow everything else to run to completion.
6031 data.SetStop(10);
6032 data.Run();
6033 EXPECT_EQ(OK, callback2.WaitForResult());
6034 EXPECT_EQ(OK, callback3.WaitForResult());
6036 helper.VerifyDataConsumed();
6039 // The tests below are only for SPDY/3 and above.
6041 // Test that sent data frames and received WINDOW_UPDATE frames change
6042 // the send_window_size_ correctly.
6044 // WINDOW_UPDATE is different than most other frames in that it can arrive
6045 // while the client is still sending the request body. In order to enforce
6046 // this scenario, we feed a couple of dummy frames and give a delay of 0 to
6047 // socket data provider, so that initial read that is done as soon as the
6048 // stream is created, succeeds and schedules another read. This way reads
6049 // and writes are interleaved; after doing a full frame write, SpdyStream
6050 // will break out of DoLoop and will read and process a WINDOW_UPDATE.
6051 // Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
6052 // since request has not been completely written, therefore we feed
6053 // enough number of WINDOW_UPDATEs to finish the first read and cause a
6054 // write, leading to a complete write of request body; after that we send
6055 // a reply with a body, to cause a graceful shutdown.
6057 // TODO(agayev): develop a socket data provider where both, reads and
6058 // writes are ordered so that writing tests like these are easy and rewrite
6059 // all these tests using it. Right now we are working around the
6060 // limitations as described above and it's not deterministic, tests may
6061 // fail under specific circumstances.
6062 TEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) {
6063 static int kFrameCount = 2;
6064 scoped_ptr<std::string> content(
6065 new std::string(kMaxSpdyFrameChunkSize, 'a'));
6066 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6067 kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
6068 scoped_ptr<SpdyFrame> body(
6069 spdy_util_.ConstructSpdyBodyFrame(
6070 1, content->c_str(), content->size(), false));
6071 scoped_ptr<SpdyFrame> body_end(
6072 spdy_util_.ConstructSpdyBodyFrame(
6073 1, content->c_str(), content->size(), true));
6075 MockWrite writes[] = {
6076 CreateMockWrite(*req, 0),
6077 CreateMockWrite(*body, 1),
6078 CreateMockWrite(*body_end, 2),
6081 static const int32 kDeltaWindowSize = 0xff;
6082 static const int kDeltaCount = 4;
6083 scoped_ptr<SpdyFrame> window_update(
6084 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
6085 scoped_ptr<SpdyFrame> window_update_dummy(
6086 spdy_util_.ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
6087 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6088 MockRead reads[] = {
6089 CreateMockRead(*window_update_dummy, 3),
6090 CreateMockRead(*window_update_dummy, 4),
6091 CreateMockRead(*window_update_dummy, 5),
6092 CreateMockRead(*window_update, 6), // Four updates, therefore window
6093 CreateMockRead(*window_update, 7), // size should increase by
6094 CreateMockRead(*window_update, 8), // kDeltaWindowSize * 4
6095 CreateMockRead(*window_update, 9),
6096 CreateMockRead(*resp, 10),
6097 CreateMockRead(*body_end, 11),
6098 MockRead(ASYNC, 0, 0, 12) // EOF
6101 DeterministicSocketData data(reads, arraysize(reads),
6102 writes, arraysize(writes));
6104 ScopedVector<UploadElementReader> element_readers;
6105 for (int i = 0; i < kFrameCount; ++i) {
6106 element_readers.push_back(
6107 new UploadBytesElementReader(content->c_str(), content->size()));
6109 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
6111 // Setup the request
6112 HttpRequestInfo request;
6113 request.method = "POST";
6114 request.url = GURL(kDefaultURL);
6115 request.upload_data_stream = &upload_data_stream;
6117 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6118 BoundNetLog(), GetParam(), NULL);
6119 helper.SetDeterministic();
6120 helper.AddDeterministicData(&data);
6121 helper.RunPreTestSetup();
6123 HttpNetworkTransaction* trans = helper.trans();
6125 TestCompletionCallback callback;
6126 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6128 EXPECT_EQ(ERR_IO_PENDING, rv);
6130 data.RunFor(11);
6132 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6133 ASSERT_TRUE(stream != NULL);
6134 ASSERT_TRUE(stream->stream() != NULL);
6135 EXPECT_EQ(
6136 static_cast<int>(SpdySession::GetInitialWindowSize(GetParam().protocol)) +
6137 kDeltaWindowSize * kDeltaCount - kMaxSpdyFrameChunkSize * kFrameCount,
6138 stream->stream()->send_window_size());
6140 data.RunFor(1);
6142 rv = callback.WaitForResult();
6143 EXPECT_EQ(OK, rv);
6145 helper.VerifyDataConsumed();
6148 // Test that received data frames and sent WINDOW_UPDATE frames change
6149 // the recv_window_size_ correctly.
6150 TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) {
6151 const int32 initial_window_size =
6152 SpdySession::GetInitialWindowSize(GetParam().protocol);
6153 // Amount of body required to trigger a sent window update.
6154 const size_t kTargetSize = initial_window_size / 2 + 1;
6156 scoped_ptr<SpdyFrame> req(
6157 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
6158 scoped_ptr<SpdyFrame> session_window_update(
6159 spdy_util_.ConstructSpdyWindowUpdate(0, kTargetSize));
6160 scoped_ptr<SpdyFrame> window_update(
6161 spdy_util_.ConstructSpdyWindowUpdate(1, kTargetSize));
6163 std::vector<MockWrite> writes;
6164 writes.push_back(CreateMockWrite(*req));
6165 if (GetParam().protocol >= kProtoSPDY31)
6166 writes.push_back(CreateMockWrite(*session_window_update));
6167 writes.push_back(CreateMockWrite(*window_update));
6169 std::vector<MockRead> reads;
6170 scoped_ptr<SpdyFrame> resp(
6171 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6172 reads.push_back(CreateMockRead(*resp));
6174 ScopedVector<SpdyFrame> body_frames;
6175 const std::string body_data(4096, 'x');
6176 for (size_t remaining = kTargetSize; remaining != 0;) {
6177 size_t frame_size = std::min(remaining, body_data.size());
6178 body_frames.push_back(spdy_util_.ConstructSpdyBodyFrame(
6179 1, body_data.data(), frame_size, false));
6180 reads.push_back(CreateMockRead(*body_frames.back()));
6181 remaining -= frame_size;
6183 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, 0)); // Yield.
6185 DelayedSocketData data(1, vector_as_array(&reads), reads.size(),
6186 vector_as_array(&writes), writes.size());
6188 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
6189 BoundNetLog(), GetParam(), NULL);
6190 helper.AddData(&data);
6191 helper.RunPreTestSetup();
6192 HttpNetworkTransaction* trans = helper.trans();
6194 TestCompletionCallback callback;
6195 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6197 EXPECT_EQ(ERR_IO_PENDING, rv);
6198 rv = callback.WaitForResult();
6199 EXPECT_EQ(OK, rv);
6201 SpdyHttpStream* stream =
6202 static_cast<SpdyHttpStream*>(trans->stream_.get());
6203 ASSERT_TRUE(stream != NULL);
6204 ASSERT_TRUE(stream->stream() != NULL);
6206 // All data has been read, but not consumed. The window reflects this.
6207 EXPECT_EQ(static_cast<int>(initial_window_size - kTargetSize),
6208 stream->stream()->recv_window_size());
6210 const HttpResponseInfo* response = trans->GetResponseInfo();
6211 ASSERT_TRUE(response != NULL);
6212 ASSERT_TRUE(response->headers.get() != NULL);
6213 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6214 EXPECT_TRUE(response->was_fetched_via_spdy);
6216 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
6217 // size increased to default.
6218 scoped_refptr<IOBuffer> buf(new IOBuffer(kTargetSize));
6219 EXPECT_EQ(static_cast<int>(kTargetSize),
6220 trans->Read(buf.get(), kTargetSize, CompletionCallback()));
6221 EXPECT_EQ(static_cast<int>(initial_window_size),
6222 stream->stream()->recv_window_size());
6223 EXPECT_THAT(base::StringPiece(buf->data(), kTargetSize), Each(Eq('x')));
6225 // Allow scheduled WINDOW_UPDATE frames to write.
6226 base::RunLoop().RunUntilIdle();
6227 helper.VerifyDataConsumed();
6230 // Test that WINDOW_UPDATE frame causing overflow is handled correctly.
6231 TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
6232 // Number of full frames we hope to write (but will not, used to
6233 // set content-length header correctly)
6234 static int kFrameCount = 3;
6236 scoped_ptr<std::string> content(
6237 new std::string(kMaxSpdyFrameChunkSize, 'a'));
6238 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6239 kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
6240 scoped_ptr<SpdyFrame> body(
6241 spdy_util_.ConstructSpdyBodyFrame(
6242 1, content->c_str(), content->size(), false));
6243 scoped_ptr<SpdyFrame> rst(
6244 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
6246 // We're not going to write a data frame with FIN, we'll receive a bad
6247 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
6248 MockWrite writes[] = {
6249 CreateMockWrite(*req, 0),
6250 CreateMockWrite(*body, 2),
6251 CreateMockWrite(*rst, 3),
6254 static const int32 kDeltaWindowSize = 0x7fffffff; // cause an overflow
6255 scoped_ptr<SpdyFrame> window_update(
6256 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
6257 MockRead reads[] = {
6258 CreateMockRead(*window_update, 1),
6259 MockRead(ASYNC, 0, 4) // EOF
6262 DeterministicSocketData data(reads, arraysize(reads),
6263 writes, arraysize(writes));
6265 ScopedVector<UploadElementReader> element_readers;
6266 for (int i = 0; i < kFrameCount; ++i) {
6267 element_readers.push_back(
6268 new UploadBytesElementReader(content->c_str(), content->size()));
6270 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
6272 // Setup the request
6273 HttpRequestInfo request;
6274 request.method = "POST";
6275 request.url = GURL("http://www.google.com/");
6276 request.upload_data_stream = &upload_data_stream;
6278 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6279 BoundNetLog(), GetParam(), NULL);
6280 helper.SetDeterministic();
6281 helper.RunPreTestSetup();
6282 helper.AddDeterministicData(&data);
6283 HttpNetworkTransaction* trans = helper.trans();
6285 TestCompletionCallback callback;
6286 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6287 ASSERT_EQ(ERR_IO_PENDING, rv);
6289 data.RunFor(5);
6290 ASSERT_TRUE(callback.have_result());
6291 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, callback.WaitForResult());
6292 helper.VerifyDataConsumed();
6295 // Test that after hitting a send window size of 0, the write process
6296 // stalls and upon receiving WINDOW_UPDATE frame write resumes.
6298 // This test constructs a POST request followed by enough data frames
6299 // containing 'a' that would make the window size 0, followed by another
6300 // data frame containing default content (which is "hello!") and this frame
6301 // also contains a FIN flag. DelayedSocketData is used to enforce all
6302 // writes go through before a read could happen. However, the last frame
6303 // ("hello!") is not supposed to go through since by the time its turn
6304 // arrives, window size is 0. At this point MessageLoop::Run() called via
6305 // callback would block. Therefore we call MessageLoop::RunUntilIdle()
6306 // which returns after performing all possible writes. We use DCHECKS to
6307 // ensure that last data frame is still there and stream has stalled.
6308 // After that, next read is artifically enforced, which causes a
6309 // WINDOW_UPDATE to be read and I/O process resumes.
6310 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) {
6311 const int32 initial_window_size =
6312 SpdySession::GetInitialWindowSize(GetParam().protocol);
6313 // Number of frames we need to send to zero out the window size: data
6314 // frames plus SYN_STREAM plus the last data frame; also we need another
6315 // data frame that we will send once the WINDOW_UPDATE is received,
6316 // therefore +3.
6317 size_t num_writes = initial_window_size / kMaxSpdyFrameChunkSize + 3;
6319 // Calculate last frame's size; 0 size data frame is legal.
6320 size_t last_frame_size = initial_window_size % kMaxSpdyFrameChunkSize;
6322 // Construct content for a data frame of maximum size.
6323 std::string content(kMaxSpdyFrameChunkSize, 'a');
6325 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6326 kRequestUrl, 1, initial_window_size + kUploadDataSize, LOWEST, NULL, 0));
6328 // Full frames.
6329 scoped_ptr<SpdyFrame> body1(
6330 spdy_util_.ConstructSpdyBodyFrame(
6331 1, content.c_str(), content.size(), false));
6333 // Last frame to zero out the window size.
6334 scoped_ptr<SpdyFrame> body2(
6335 spdy_util_.ConstructSpdyBodyFrame(
6336 1, content.c_str(), last_frame_size, false));
6338 // Data frame to be sent once WINDOW_UPDATE frame is received.
6339 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6341 // Fill in mock writes.
6342 scoped_ptr<MockWrite[]> writes(new MockWrite[num_writes]);
6343 size_t i = 0;
6344 writes[i] = CreateMockWrite(*req);
6345 for (i = 1; i < num_writes - 2; i++)
6346 writes[i] = CreateMockWrite(*body1);
6347 writes[i++] = CreateMockWrite(*body2);
6348 writes[i] = CreateMockWrite(*body3);
6350 // Construct read frame, give enough space to upload the rest of the
6351 // data.
6352 scoped_ptr<SpdyFrame> session_window_update(
6353 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6354 scoped_ptr<SpdyFrame> window_update(
6355 spdy_util_.ConstructSpdyWindowUpdate(1, kUploadDataSize));
6356 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6357 MockRead reads[] = {
6358 CreateMockRead(*session_window_update),
6359 CreateMockRead(*session_window_update),
6360 CreateMockRead(*window_update),
6361 CreateMockRead(*window_update),
6362 CreateMockRead(*reply),
6363 CreateMockRead(*body2),
6364 CreateMockRead(*body3),
6365 MockRead(ASYNC, 0, 0) // EOF
6368 // Skip the session window updates unless we're using SPDY/3.1 and
6369 // above.
6370 size_t read_offset = (GetParam().protocol >= kProtoSPDY31) ? 0 : 2;
6371 size_t num_reads = arraysize(reads) - read_offset;
6373 // Force all writes to happen before any read, last write will not
6374 // actually queue a frame, due to window size being 0.
6375 DelayedSocketData data(num_writes, reads + read_offset, num_reads,
6376 writes.get(), num_writes);
6378 ScopedVector<UploadElementReader> element_readers;
6379 std::string upload_data_string(initial_window_size, 'a');
6380 upload_data_string.append(kUploadData, kUploadDataSize);
6381 element_readers.push_back(new UploadBytesElementReader(
6382 upload_data_string.c_str(), upload_data_string.size()));
6383 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
6385 HttpRequestInfo request;
6386 request.method = "POST";
6387 request.url = GURL("http://www.google.com/");
6388 request.upload_data_stream = &upload_data_stream;
6389 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6390 BoundNetLog(), GetParam(), NULL);
6391 helper.AddData(&data);
6392 helper.RunPreTestSetup();
6394 HttpNetworkTransaction* trans = helper.trans();
6396 TestCompletionCallback callback;
6397 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6398 EXPECT_EQ(ERR_IO_PENDING, rv);
6400 base::RunLoop().RunUntilIdle(); // Write as much as we can.
6402 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6403 ASSERT_TRUE(stream != NULL);
6404 ASSERT_TRUE(stream->stream() != NULL);
6405 EXPECT_EQ(0, stream->stream()->send_window_size());
6406 // All the body data should have been read.
6407 // TODO(satorux): This is because of the weirdness in reading the request
6408 // body in OnSendBodyComplete(). See crbug.com/113107.
6409 EXPECT_TRUE(upload_data_stream.IsEOF());
6410 // But the body is not yet fully sent (kUploadData is not yet sent)
6411 // since we're send-stalled.
6412 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6414 data.ForceNextRead(); // Read in WINDOW_UPDATE frame.
6415 rv = callback.WaitForResult();
6416 helper.VerifyDataConsumed();
6419 // Test we correctly handle the case where the SETTINGS frame results in
6420 // unstalling the send window.
6421 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
6422 const int32 initial_window_size =
6423 SpdySession::GetInitialWindowSize(GetParam().protocol);
6425 // Number of frames we need to send to zero out the window size: data
6426 // frames plus SYN_STREAM plus the last data frame; also we need another
6427 // data frame that we will send once the SETTING is received, therefore +3.
6428 size_t num_writes = initial_window_size / kMaxSpdyFrameChunkSize + 3;
6430 // Calculate last frame's size; 0 size data frame is legal.
6431 size_t last_frame_size = initial_window_size % kMaxSpdyFrameChunkSize;
6433 // Construct content for a data frame of maximum size.
6434 std::string content(kMaxSpdyFrameChunkSize, 'a');
6436 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6437 kRequestUrl, 1, initial_window_size + kUploadDataSize, LOWEST, NULL, 0));
6439 // Full frames.
6440 scoped_ptr<SpdyFrame> body1(
6441 spdy_util_.ConstructSpdyBodyFrame(
6442 1, content.c_str(), content.size(), false));
6444 // Last frame to zero out the window size.
6445 scoped_ptr<SpdyFrame> body2(
6446 spdy_util_.ConstructSpdyBodyFrame(
6447 1, content.c_str(), last_frame_size, false));
6449 // Data frame to be sent once SETTINGS frame is received.
6450 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6452 // Fill in mock reads/writes.
6453 std::vector<MockRead> reads;
6454 std::vector<MockWrite> writes;
6455 size_t i = 0;
6456 writes.push_back(CreateMockWrite(*req, i++));
6457 while (i < num_writes - 2)
6458 writes.push_back(CreateMockWrite(*body1, i++));
6459 writes.push_back(CreateMockWrite(*body2, i++));
6461 // Construct read frame for SETTINGS that gives enough space to upload the
6462 // rest of the data.
6463 SettingsMap settings;
6464 settings[SETTINGS_INITIAL_WINDOW_SIZE] =
6465 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_window_size * 2);
6466 scoped_ptr<SpdyFrame> settings_frame_large(
6467 spdy_util_.ConstructSpdySettings(settings));
6469 reads.push_back(CreateMockRead(*settings_frame_large, i++));
6471 scoped_ptr<SpdyFrame> session_window_update(
6472 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6473 if (GetParam().protocol >= kProtoSPDY31)
6474 reads.push_back(CreateMockRead(*session_window_update, i++));
6476 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
6477 writes.push_back(CreateMockWrite(*settings_ack, i++));
6479 writes.push_back(CreateMockWrite(*body3, i++));
6481 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6482 reads.push_back(CreateMockRead(*reply, i++));
6483 reads.push_back(CreateMockRead(*body2, i++));
6484 reads.push_back(CreateMockRead(*body3, i++));
6485 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6487 // Force all writes to happen before any read, last write will not
6488 // actually queue a frame, due to window size being 0.
6489 DeterministicSocketData data(vector_as_array(&reads), reads.size(),
6490 vector_as_array(&writes), writes.size());
6492 ScopedVector<UploadElementReader> element_readers;
6493 std::string upload_data_string(initial_window_size, 'a');
6494 upload_data_string.append(kUploadData, kUploadDataSize);
6495 element_readers.push_back(new UploadBytesElementReader(
6496 upload_data_string.c_str(), upload_data_string.size()));
6497 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
6499 HttpRequestInfo request;
6500 request.method = "POST";
6501 request.url = GURL("http://www.google.com/");
6502 request.upload_data_stream = &upload_data_stream;
6503 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6504 BoundNetLog(), GetParam(), NULL);
6505 helper.SetDeterministic();
6506 helper.RunPreTestSetup();
6507 helper.AddDeterministicData(&data);
6509 HttpNetworkTransaction* trans = helper.trans();
6511 TestCompletionCallback callback;
6512 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6513 EXPECT_EQ(ERR_IO_PENDING, rv);
6515 data.RunFor(num_writes - 1); // Write as much as we can.
6517 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6518 ASSERT_TRUE(stream != NULL);
6519 ASSERT_TRUE(stream->stream() != NULL);
6520 EXPECT_EQ(0, stream->stream()->send_window_size());
6522 // All the body data should have been read.
6523 // TODO(satorux): This is because of the weirdness in reading the request
6524 // body in OnSendBodyComplete(). See crbug.com/113107.
6525 EXPECT_TRUE(upload_data_stream.IsEOF());
6526 // But the body is not yet fully sent (kUploadData is not yet sent)
6527 // since we're send-stalled.
6528 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6530 data.RunFor(7); // Read in SETTINGS frame to unstall.
6531 rv = callback.WaitForResult();
6532 helper.VerifyDataConsumed();
6533 // If stream is NULL, that means it was unstalled and closed.
6534 EXPECT_TRUE(stream->stream() == NULL);
6537 // Test we correctly handle the case where the SETTINGS frame results in a
6538 // negative send window size.
6539 TEST_P(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
6540 const int32 initial_window_size =
6541 SpdySession::GetInitialWindowSize(GetParam().protocol);
6542 // Number of frames we need to send to zero out the window size: data
6543 // frames plus SYN_STREAM plus the last data frame; also we need another
6544 // data frame that we will send once the SETTING is received, therefore +3.
6545 size_t num_writes = initial_window_size / kMaxSpdyFrameChunkSize + 3;
6547 // Calculate last frame's size; 0 size data frame is legal.
6548 size_t last_frame_size = initial_window_size % kMaxSpdyFrameChunkSize;
6550 // Construct content for a data frame of maximum size.
6551 std::string content(kMaxSpdyFrameChunkSize, 'a');
6553 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6554 kRequestUrl, 1, initial_window_size + kUploadDataSize, LOWEST, NULL, 0));
6556 // Full frames.
6557 scoped_ptr<SpdyFrame> body1(
6558 spdy_util_.ConstructSpdyBodyFrame(
6559 1, content.c_str(), content.size(), false));
6561 // Last frame to zero out the window size.
6562 scoped_ptr<SpdyFrame> body2(
6563 spdy_util_.ConstructSpdyBodyFrame(
6564 1, content.c_str(), last_frame_size, false));
6566 // Data frame to be sent once SETTINGS frame is received.
6567 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6569 // Fill in mock reads/writes.
6570 std::vector<MockRead> reads;
6571 std::vector<MockWrite> writes;
6572 size_t i = 0;
6573 writes.push_back(CreateMockWrite(*req, i++));
6574 while (i < num_writes - 2)
6575 writes.push_back(CreateMockWrite(*body1, i++));
6576 writes.push_back(CreateMockWrite(*body2, i++));
6578 // Construct read frame for SETTINGS that makes the send_window_size
6579 // negative.
6580 SettingsMap new_settings;
6581 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
6582 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_window_size / 2);
6583 scoped_ptr<SpdyFrame> settings_frame_small(
6584 spdy_util_.ConstructSpdySettings(new_settings));
6585 // Construct read frames for WINDOW_UPDATE that makes the send_window_size
6586 // positive.
6587 scoped_ptr<SpdyFrame> session_window_update_init_size(
6588 spdy_util_.ConstructSpdyWindowUpdate(0, initial_window_size));
6589 scoped_ptr<SpdyFrame> window_update_init_size(
6590 spdy_util_.ConstructSpdyWindowUpdate(1, initial_window_size));
6592 reads.push_back(CreateMockRead(*settings_frame_small, i++));
6593 reads.push_back(CreateMockRead(*session_window_update_init_size, i++));
6594 reads.push_back(CreateMockRead(*window_update_init_size, i++));
6596 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
6597 writes.push_back(CreateMockWrite(*settings_ack, i++));
6599 writes.push_back(CreateMockWrite(*body3, i++));
6601 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6602 reads.push_back(CreateMockRead(*reply, i++));
6603 reads.push_back(CreateMockRead(*body2, i++));
6604 reads.push_back(CreateMockRead(*body3, i++));
6605 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6607 // Force all writes to happen before any read, last write will not
6608 // actually queue a frame, due to window size being 0.
6609 DeterministicSocketData data(vector_as_array(&reads), reads.size(),
6610 vector_as_array(&writes), writes.size());
6612 ScopedVector<UploadElementReader> element_readers;
6613 std::string upload_data_string(initial_window_size, 'a');
6614 upload_data_string.append(kUploadData, kUploadDataSize);
6615 element_readers.push_back(new UploadBytesElementReader(
6616 upload_data_string.c_str(), upload_data_string.size()));
6617 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
6619 HttpRequestInfo request;
6620 request.method = "POST";
6621 request.url = GURL("http://www.google.com/");
6622 request.upload_data_stream = &upload_data_stream;
6623 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6624 BoundNetLog(), GetParam(), NULL);
6625 helper.SetDeterministic();
6626 helper.RunPreTestSetup();
6627 helper.AddDeterministicData(&data);
6629 HttpNetworkTransaction* trans = helper.trans();
6631 TestCompletionCallback callback;
6632 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6633 EXPECT_EQ(ERR_IO_PENDING, rv);
6635 data.RunFor(num_writes - 1); // Write as much as we can.
6637 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6638 ASSERT_TRUE(stream != NULL);
6639 ASSERT_TRUE(stream->stream() != NULL);
6640 EXPECT_EQ(0, stream->stream()->send_window_size());
6642 // All the body data should have been read.
6643 // TODO(satorux): This is because of the weirdness in reading the request
6644 // body in OnSendBodyComplete(). See crbug.com/113107.
6645 EXPECT_TRUE(upload_data_stream.IsEOF());
6646 // But the body is not yet fully sent (kUploadData is not yet sent)
6647 // since we're send-stalled.
6648 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6650 // Read in WINDOW_UPDATE or SETTINGS frame.
6651 data.RunFor((GetParam().protocol >= kProtoSPDY31) ? 9 : 8);
6652 rv = callback.WaitForResult();
6653 helper.VerifyDataConsumed();
6656 TEST_P(SpdyNetworkTransactionTest, GoAwayOnOddPushStreamId) {
6657 if (spdy_util_.spdy_version() < SPDY3)
6658 return;
6660 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
6661 spdy_util_.AddUrlToHeaderBlock("http://www.google.com/a.dat",
6662 push_headers.get());
6663 scoped_ptr<SpdyFrame> push(
6664 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 3, 1));
6665 MockRead reads[] = {CreateMockRead(*push, 1)};
6667 scoped_ptr<SpdyFrame> req(
6668 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
6669 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
6670 0, GOAWAY_PROTOCOL_ERROR, "Odd push stream id."));
6671 MockWrite writes[] = {
6672 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2),
6675 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
6676 NormalSpdyTransactionHelper helper(
6677 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6678 helper.RunToCompletion(&data);
6679 TransactionHelperResult out = helper.output();
6680 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
6683 TEST_P(SpdyNetworkTransactionTest,
6684 GoAwayOnPushStreamIdLesserOrEqualThanLastAccepted) {
6685 if (spdy_util_.spdy_version() < SPDY3)
6686 return;
6688 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
6689 NULL, 0, 4, 1, "http://www.google.com/a.dat"));
6690 scoped_ptr<SpdyHeaderBlock> push_b_headers(new SpdyHeaderBlock);
6691 spdy_util_.AddUrlToHeaderBlock("http://www.google.com/b.dat",
6692 push_b_headers.get());
6693 scoped_ptr<SpdyFrame> push_b(
6694 spdy_util_.ConstructInitialSpdyPushFrame(push_b_headers.Pass(), 2, 1));
6695 MockRead reads[] = {
6696 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
6699 scoped_ptr<SpdyFrame> req(
6700 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
6701 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
6703 GOAWAY_PROTOCOL_ERROR,
6704 "New push stream id must be greater than the last accepted."));
6705 MockWrite writes[] = {
6706 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 3),
6709 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
6710 NormalSpdyTransactionHelper helper(
6711 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6712 helper.RunToCompletion(&data);
6713 TransactionHelperResult out = helper.output();
6714 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
6717 class SpdyNetworkTransactionNoTLSUsageCheckTest
6718 : public SpdyNetworkTransactionTest {
6719 protected:
6720 void RunNoTLSUsageCheckTest(scoped_ptr<SSLSocketDataProvider> ssl_provider) {
6721 // Construct the request.
6722 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyGet(
6723 "https://www.google.com/", false, 1, LOWEST));
6724 MockWrite writes[] = {CreateMockWrite(*req)};
6726 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6727 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6728 MockRead reads[] = {
6729 CreateMockRead(*resp), CreateMockRead(*body),
6730 MockRead(ASYNC, 0, 0) // EOF
6733 DelayedSocketData data(
6734 1, reads, arraysize(reads), writes, arraysize(writes));
6735 HttpRequestInfo request;
6736 request.method = "GET";
6737 request.url = GURL("https://www.google.com/");
6738 NormalSpdyTransactionHelper helper(
6739 request, DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6740 helper.RunToCompletionWithSSLData(&data, ssl_provider.Pass());
6741 TransactionHelperResult out = helper.output();
6742 EXPECT_EQ(OK, out.rv);
6743 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
6744 EXPECT_EQ("hello!", out.response_data);
6748 //-----------------------------------------------------------------------------
6749 // All tests are run with three different connection types: SPDY after NPN
6750 // negotiation, SPDY without SSL, and SPDY with SSL.
6752 // TODO(akalin): Use ::testing::Combine() when we are able to use
6753 // <tr1/tuple>.
6754 INSTANTIATE_TEST_CASE_P(
6755 Spdy,
6756 SpdyNetworkTransactionNoTLSUsageCheckTest,
6757 ::testing::Values(SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNPN)));
6759 TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest, TLSVersionTooOld) {
6760 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6761 new SSLSocketDataProvider(ASYNC, OK));
6762 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6763 &ssl_provider->connection_status);
6765 RunNoTLSUsageCheckTest(ssl_provider.Pass());
6768 TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest, TLSCipherSuiteSucky) {
6769 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6770 new SSLSocketDataProvider(ASYNC, OK));
6771 // Set to TLS_RSA_WITH_NULL_MD5
6772 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider->connection_status);
6774 RunNoTLSUsageCheckTest(ssl_provider.Pass());
6777 class SpdyNetworkTransactionTLSUsageCheckTest
6778 : public SpdyNetworkTransactionTest {
6779 protected:
6780 void RunTLSUsageCheckTest(scoped_ptr<SSLSocketDataProvider> ssl_provider) {
6781 scoped_ptr<SpdyFrame> goaway(
6782 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_INADEQUATE_SECURITY, ""));
6783 MockWrite writes[] = {CreateMockWrite(*goaway)};
6785 DelayedSocketData data(1, NULL, 0, writes, arraysize(writes));
6786 HttpRequestInfo request;
6787 request.method = "GET";
6788 request.url = GURL("https://www.google.com/");
6789 NormalSpdyTransactionHelper helper(
6790 request, DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6791 helper.RunToCompletionWithSSLData(&data, ssl_provider.Pass());
6792 TransactionHelperResult out = helper.output();
6793 EXPECT_EQ(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY, out.rv);
6797 INSTANTIATE_TEST_CASE_P(
6798 Spdy,
6799 SpdyNetworkTransactionTLSUsageCheckTest,
6800 ::testing::Values(SpdyNetworkTransactionTestParams(kProtoSPDY4_14, SPDYNPN),
6801 SpdyNetworkTransactionTestParams(kProtoSPDY4, SPDYNPN)));
6803 TEST_P(SpdyNetworkTransactionTLSUsageCheckTest, TLSVersionTooOld) {
6804 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6805 new SSLSocketDataProvider(ASYNC, OK));
6806 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6807 &ssl_provider->connection_status);
6809 RunTLSUsageCheckTest(ssl_provider.Pass());
6812 TEST_P(SpdyNetworkTransactionTLSUsageCheckTest, TLSCipherSuiteSucky) {
6813 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6814 new SSLSocketDataProvider(ASYNC, OK));
6815 // Set to TLS_RSA_WITH_NULL_MD5
6816 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider->connection_status);
6818 RunTLSUsageCheckTest(ssl_provider.Pass());
6821 } // namespace net