Sort unlaunched apps on app list start page by apps grid order.
[chromium-blink-merge.git] / net / spdy / spdy_network_transaction_unittest.cc
blobe286333617d117775414cc0ef3f4aeb901bb205c
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.SetAlternateProtocol(
80 HostPortPair("www.google.com", 80), 443,
81 AlternateProtocolFromNextProto(test_params.protocol), 1);
82 session_deps->use_alternate_protocols = true;
83 session_deps->next_protos = SpdyNextProtos();
84 break;
85 case SPDYNOSSL:
86 session_deps->force_spdy_over_ssl = false;
87 session_deps->force_spdy_always = true;
88 break;
89 case SPDYSSL:
90 session_deps->force_spdy_over_ssl = true;
91 session_deps->force_spdy_always = true;
92 break;
93 default:
94 NOTREACHED();
98 SpdySessionDependencies* CreateSpdySessionDependencies(
99 SpdyNetworkTransactionTestParams test_params) {
100 SpdySessionDependencies* session_deps =
101 new SpdySessionDependencies(test_params.protocol);
102 UpdateSpdySessionDependencies(test_params, session_deps);
103 return session_deps;
106 SpdySessionDependencies* CreateSpdySessionDependencies(
107 SpdyNetworkTransactionTestParams test_params,
108 ProxyService* proxy_service) {
109 SpdySessionDependencies* session_deps =
110 new SpdySessionDependencies(test_params.protocol, proxy_service);
111 UpdateSpdySessionDependencies(test_params, session_deps);
112 return session_deps;
115 } // namespace
117 class SpdyNetworkTransactionTest
118 : public ::testing::TestWithParam<SpdyNetworkTransactionTestParams> {
119 protected:
120 SpdyNetworkTransactionTest() : spdy_util_(GetParam().protocol) {
123 virtual ~SpdyNetworkTransactionTest() {
124 // UploadDataStream may post a deletion tasks back to the message loop on
125 // destruction.
126 upload_data_stream_.reset();
127 base::RunLoop().RunUntilIdle();
130 void SetUp() override {
131 google_get_request_initialized_ = false;
132 google_post_request_initialized_ = false;
133 google_chunked_post_request_initialized_ = false;
134 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
137 struct TransactionHelperResult {
138 int rv;
139 std::string status_line;
140 std::string response_data;
141 HttpResponseInfo response_info;
144 // A helper class that handles all the initial npn/ssl setup.
145 class NormalSpdyTransactionHelper {
146 public:
147 NormalSpdyTransactionHelper(const HttpRequestInfo& request,
148 RequestPriority priority,
149 const BoundNetLog& log,
150 SpdyNetworkTransactionTestParams test_params,
151 SpdySessionDependencies* session_deps)
152 : request_(request),
153 priority_(priority),
154 session_deps_(session_deps == NULL ?
155 CreateSpdySessionDependencies(test_params) :
156 session_deps),
157 session_(SpdySessionDependencies::SpdyCreateSession(
158 session_deps_.get())),
159 log_(log),
160 test_params_(test_params),
161 deterministic_(false),
162 spdy_enabled_(true) {
163 switch (test_params_.ssl_type) {
164 case SPDYNOSSL:
165 case SPDYSSL:
166 port_ = 80;
167 break;
168 case SPDYNPN:
169 port_ = 443;
170 break;
171 default:
172 NOTREACHED();
176 ~NormalSpdyTransactionHelper() {
177 // Any test which doesn't close the socket by sending it an EOF will
178 // have a valid session left open, which leaks the entire session pool.
179 // This is just fine - in fact, some of our tests intentionally do this
180 // so that we can check consistency of the SpdySessionPool as the test
181 // finishes. If we had put an EOF on the socket, the SpdySession would
182 // have closed and we wouldn't be able to check the consistency.
184 // Forcefully close existing sessions here.
185 session()->spdy_session_pool()->CloseAllSessions();
188 void SetDeterministic() {
189 session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
190 session_deps_.get());
191 deterministic_ = true;
194 void SetSpdyDisabled() {
195 spdy_enabled_ = false;
196 port_ = 80;
199 void RunPreTestSetup() {
200 if (!session_deps_.get())
201 session_deps_.reset(CreateSpdySessionDependencies(test_params_));
202 if (!session_.get()) {
203 session_ = SpdySessionDependencies::SpdyCreateSession(
204 session_deps_.get());
207 // We're now ready to use SSL-npn SPDY.
208 trans_.reset(new HttpNetworkTransaction(priority_, session_.get()));
211 // Start the transaction, read some data, finish.
212 void RunDefaultTest() {
213 if (!StartDefaultTest())
214 return;
215 FinishDefaultTest();
218 bool StartDefaultTest() {
219 output_.rv = trans_->Start(&request_, callback_.callback(), log_);
221 // We expect an IO Pending or some sort of error.
222 EXPECT_LT(output_.rv, 0);
223 return output_.rv == ERR_IO_PENDING;
226 void FinishDefaultTest() {
227 output_.rv = callback_.WaitForResult();
228 if (output_.rv != OK) {
229 session_->spdy_session_pool()->CloseCurrentSessions(net::ERR_ABORTED);
230 return;
233 // Verify responses.
234 const HttpResponseInfo* response = trans_->GetResponseInfo();
235 ASSERT_TRUE(response != NULL);
236 ASSERT_TRUE(response->headers.get() != NULL);
237 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
238 EXPECT_EQ(spdy_enabled_, response->was_fetched_via_spdy);
239 if (HttpStreamFactory::spdy_enabled()) {
240 EXPECT_EQ(
241 HttpResponseInfo::ConnectionInfoFromNextProto(
242 test_params_.protocol),
243 response->connection_info);
244 } else {
245 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1,
246 response->connection_info);
248 if (test_params_.ssl_type == SPDYNPN && spdy_enabled_) {
249 EXPECT_TRUE(response->was_npn_negotiated);
250 } else {
251 EXPECT_TRUE(!response->was_npn_negotiated);
253 // If SPDY is not enabled, a HTTP request should not be diverted
254 // over a SSL session.
255 if (!spdy_enabled_) {
256 EXPECT_EQ(request_.url.SchemeIs("https"),
257 response->was_npn_negotiated);
259 EXPECT_EQ("127.0.0.1", response->socket_address.host());
260 EXPECT_EQ(port_, response->socket_address.port());
261 output_.status_line = response->headers->GetStatusLine();
262 output_.response_info = *response; // Make a copy so we can verify.
263 output_.rv = ReadTransaction(trans_.get(), &output_.response_data);
266 void FinishDefaultTestWithoutVerification() {
267 output_.rv = callback_.WaitForResult();
268 if (output_.rv != OK)
269 session_->spdy_session_pool()->CloseCurrentSessions(net::ERR_ABORTED);
272 // Most tests will want to call this function. In particular, the MockReads
273 // should end with an empty read, and that read needs to be processed to
274 // ensure proper deletion of the spdy_session_pool.
275 void VerifyDataConsumed() {
276 for (DataVector::iterator it = data_vector_.begin();
277 it != data_vector_.end(); ++it) {
278 EXPECT_TRUE((*it)->at_read_eof()) << "Read count: "
279 << (*it)->read_count()
280 << " Read index: "
281 << (*it)->read_index();
282 EXPECT_TRUE((*it)->at_write_eof()) << "Write count: "
283 << (*it)->write_count()
284 << " Write index: "
285 << (*it)->write_index();
289 // Occasionally a test will expect to error out before certain reads are
290 // processed. In that case we want to explicitly ensure that the reads were
291 // not processed.
292 void VerifyDataNotConsumed() {
293 for (DataVector::iterator it = data_vector_.begin();
294 it != data_vector_.end(); ++it) {
295 EXPECT_TRUE(!(*it)->at_read_eof()) << "Read count: "
296 << (*it)->read_count()
297 << " Read index: "
298 << (*it)->read_index();
299 EXPECT_TRUE(!(*it)->at_write_eof()) << "Write count: "
300 << (*it)->write_count()
301 << " Write index: "
302 << (*it)->write_index();
306 void RunToCompletion(StaticSocketDataProvider* data) {
307 RunPreTestSetup();
308 AddData(data);
309 RunDefaultTest();
310 VerifyDataConsumed();
313 void RunToCompletionWithSSLData(
314 StaticSocketDataProvider* data,
315 scoped_ptr<SSLSocketDataProvider> ssl_provider) {
316 RunPreTestSetup();
317 AddDataWithSSLSocketDataProvider(data, ssl_provider.Pass());
318 RunDefaultTest();
319 VerifyDataConsumed();
322 void AddData(StaticSocketDataProvider* data) {
323 scoped_ptr<SSLSocketDataProvider> ssl_provider(
324 new SSLSocketDataProvider(ASYNC, OK));
325 AddDataWithSSLSocketDataProvider(data, ssl_provider.Pass());
328 void AddDataWithSSLSocketDataProvider(
329 StaticSocketDataProvider* data,
330 scoped_ptr<SSLSocketDataProvider> ssl_provider) {
331 DCHECK(!deterministic_);
332 data_vector_.push_back(data);
333 if (test_params_.ssl_type == SPDYNPN)
334 ssl_provider->SetNextProto(test_params_.protocol);
336 if (test_params_.ssl_type == SPDYNPN ||
337 test_params_.ssl_type == SPDYSSL) {
338 session_deps_->socket_factory->AddSSLSocketDataProvider(
339 ssl_provider.get());
341 ssl_vector_.push_back(ssl_provider.release());
343 session_deps_->socket_factory->AddSocketDataProvider(data);
344 if (test_params_.ssl_type == SPDYNPN) {
345 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
346 StaticSocketDataProvider* hanging_non_alternate_protocol_socket =
347 new StaticSocketDataProvider(NULL, 0, NULL, 0);
348 hanging_non_alternate_protocol_socket->set_connect_data(
349 never_finishing_connect);
350 session_deps_->socket_factory->AddSocketDataProvider(
351 hanging_non_alternate_protocol_socket);
352 alternate_vector_.push_back(hanging_non_alternate_protocol_socket);
356 void AddDeterministicData(DeterministicSocketData* data) {
357 DCHECK(deterministic_);
358 data_vector_.push_back(data);
359 SSLSocketDataProvider* ssl_provider =
360 new SSLSocketDataProvider(ASYNC, OK);
361 if (test_params_.ssl_type == SPDYNPN)
362 ssl_provider->SetNextProto(test_params_.protocol);
364 ssl_vector_.push_back(ssl_provider);
365 if (test_params_.ssl_type == SPDYNPN ||
366 test_params_.ssl_type == SPDYSSL) {
367 session_deps_->deterministic_socket_factory->
368 AddSSLSocketDataProvider(ssl_provider);
370 session_deps_->deterministic_socket_factory->AddSocketDataProvider(data);
371 if (test_params_.ssl_type == SPDYNPN) {
372 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
373 DeterministicSocketData* hanging_non_alternate_protocol_socket =
374 new DeterministicSocketData(NULL, 0, NULL, 0);
375 hanging_non_alternate_protocol_socket->set_connect_data(
376 never_finishing_connect);
377 session_deps_->deterministic_socket_factory->AddSocketDataProvider(
378 hanging_non_alternate_protocol_socket);
379 alternate_deterministic_vector_.push_back(
380 hanging_non_alternate_protocol_socket);
384 void SetSession(const scoped_refptr<HttpNetworkSession>& session) {
385 session_ = session;
387 HttpNetworkTransaction* trans() { return trans_.get(); }
388 void ResetTrans() { trans_.reset(); }
389 TransactionHelperResult& output() { return output_; }
390 const HttpRequestInfo& request() const { return request_; }
391 const scoped_refptr<HttpNetworkSession>& session() const {
392 return session_;
394 scoped_ptr<SpdySessionDependencies>& session_deps() {
395 return session_deps_;
397 int port() const { return port_; }
398 SpdyNetworkTransactionTestParams test_params() const {
399 return test_params_;
402 private:
403 typedef std::vector<StaticSocketDataProvider*> DataVector;
404 typedef ScopedVector<SSLSocketDataProvider> SSLVector;
405 typedef ScopedVector<StaticSocketDataProvider> AlternateVector;
406 typedef ScopedVector<DeterministicSocketData> AlternateDeterministicVector;
407 HttpRequestInfo request_;
408 RequestPriority priority_;
409 scoped_ptr<SpdySessionDependencies> session_deps_;
410 scoped_refptr<HttpNetworkSession> session_;
411 TransactionHelperResult output_;
412 scoped_ptr<StaticSocketDataProvider> first_transaction_;
413 SSLVector ssl_vector_;
414 TestCompletionCallback callback_;
415 scoped_ptr<HttpNetworkTransaction> trans_;
416 scoped_ptr<HttpNetworkTransaction> trans_http_;
417 DataVector data_vector_;
418 AlternateVector alternate_vector_;
419 AlternateDeterministicVector alternate_deterministic_vector_;
420 const BoundNetLog log_;
421 SpdyNetworkTransactionTestParams test_params_;
422 int port_;
423 bool deterministic_;
424 bool spdy_enabled_;
427 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
428 int expected_status);
430 void ConnectStatusHelper(const MockRead& status);
432 const HttpRequestInfo& CreateGetPushRequest() {
433 google_get_push_request_.method = "GET";
434 google_get_push_request_.url = GURL("http://www.google.com/foo.dat");
435 google_get_push_request_.load_flags = 0;
436 return google_get_push_request_;
439 const HttpRequestInfo& CreateGetRequest() {
440 if (!google_get_request_initialized_) {
441 google_get_request_.method = "GET";
442 google_get_request_.url = GURL(kDefaultURL);
443 google_get_request_.load_flags = 0;
444 google_get_request_initialized_ = true;
446 return google_get_request_;
449 const HttpRequestInfo& CreateGetRequestWithUserAgent() {
450 if (!google_get_request_initialized_) {
451 google_get_request_.method = "GET";
452 google_get_request_.url = GURL(kDefaultURL);
453 google_get_request_.load_flags = 0;
454 google_get_request_.extra_headers.SetHeader("User-Agent", "Chrome");
455 google_get_request_initialized_ = true;
457 return google_get_request_;
460 const HttpRequestInfo& CreatePostRequest() {
461 if (!google_post_request_initialized_) {
462 ScopedVector<UploadElementReader> element_readers;
463 element_readers.push_back(
464 new UploadBytesElementReader(kUploadData, kUploadDataSize));
465 upload_data_stream_.reset(
466 new ElementsUploadDataStream(element_readers.Pass(), 0));
468 google_post_request_.method = "POST";
469 google_post_request_.url = GURL(kDefaultURL);
470 google_post_request_.upload_data_stream = upload_data_stream_.get();
471 google_post_request_initialized_ = true;
473 return google_post_request_;
476 const HttpRequestInfo& CreateFilePostRequest() {
477 if (!google_post_request_initialized_) {
478 base::FilePath file_path;
479 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
480 CHECK_EQ(static_cast<int>(kUploadDataSize),
481 base::WriteFile(file_path, kUploadData, kUploadDataSize));
483 ScopedVector<UploadElementReader> element_readers;
484 element_readers.push_back(
485 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
486 file_path,
488 kUploadDataSize,
489 base::Time()));
490 upload_data_stream_.reset(
491 new ElementsUploadDataStream(element_readers.Pass(), 0));
493 google_post_request_.method = "POST";
494 google_post_request_.url = GURL(kDefaultURL);
495 google_post_request_.upload_data_stream = upload_data_stream_.get();
496 google_post_request_initialized_ = true;
498 return google_post_request_;
501 const HttpRequestInfo& CreateUnreadableFilePostRequest() {
502 if (google_post_request_initialized_)
503 return google_post_request_;
505 base::FilePath file_path;
506 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
507 CHECK_EQ(static_cast<int>(kUploadDataSize),
508 base::WriteFile(file_path, kUploadData, kUploadDataSize));
509 CHECK(base::MakeFileUnreadable(file_path));
511 ScopedVector<UploadElementReader> element_readers;
512 element_readers.push_back(
513 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
514 file_path,
516 kUploadDataSize,
517 base::Time()));
518 upload_data_stream_.reset(
519 new ElementsUploadDataStream(element_readers.Pass(), 0));
521 google_post_request_.method = "POST";
522 google_post_request_.url = GURL(kDefaultURL);
523 google_post_request_.upload_data_stream = upload_data_stream_.get();
524 google_post_request_initialized_ = true;
525 return google_post_request_;
528 const HttpRequestInfo& CreateComplexPostRequest() {
529 if (!google_post_request_initialized_) {
530 const int kFileRangeOffset = 1;
531 const int kFileRangeLength = 3;
532 CHECK_LT(kFileRangeOffset + kFileRangeLength, kUploadDataSize);
534 base::FilePath file_path;
535 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
536 CHECK_EQ(static_cast<int>(kUploadDataSize),
537 base::WriteFile(file_path, kUploadData, kUploadDataSize));
539 ScopedVector<UploadElementReader> element_readers;
540 element_readers.push_back(
541 new UploadBytesElementReader(kUploadData, kFileRangeOffset));
542 element_readers.push_back(
543 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
544 file_path,
545 kFileRangeOffset,
546 kFileRangeLength,
547 base::Time()));
548 element_readers.push_back(new UploadBytesElementReader(
549 kUploadData + kFileRangeOffset + kFileRangeLength,
550 kUploadDataSize - (kFileRangeOffset + kFileRangeLength)));
551 upload_data_stream_.reset(
552 new ElementsUploadDataStream(element_readers.Pass(), 0));
554 google_post_request_.method = "POST";
555 google_post_request_.url = GURL(kDefaultURL);
556 google_post_request_.upload_data_stream = upload_data_stream_.get();
557 google_post_request_initialized_ = true;
559 return google_post_request_;
562 const HttpRequestInfo& CreateChunkedPostRequest() {
563 if (!google_chunked_post_request_initialized_) {
564 upload_chunked_data_stream_.reset(new ChunkedUploadDataStream(0));
565 google_chunked_post_request_.method = "POST";
566 google_chunked_post_request_.url = GURL(kDefaultURL);
567 google_chunked_post_request_.upload_data_stream =
568 upload_chunked_data_stream_.get();
569 google_chunked_post_request_initialized_ = true;
571 return google_chunked_post_request_;
574 // Read the result of a particular transaction, knowing that we've got
575 // multiple transactions in the read pipeline; so as we read, we may have
576 // to skip over data destined for other transactions while we consume
577 // the data for |trans|.
578 int ReadResult(HttpNetworkTransaction* trans,
579 StaticSocketDataProvider* data,
580 std::string* result) {
581 const int kSize = 3000;
583 int bytes_read = 0;
584 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(kSize));
585 TestCompletionCallback callback;
586 while (true) {
587 int rv = trans->Read(buf.get(), kSize, callback.callback());
588 if (rv == ERR_IO_PENDING) {
589 // Multiple transactions may be in the data set. Keep pulling off
590 // reads until we complete our callback.
591 while (!callback.have_result()) {
592 data->CompleteRead();
593 base::RunLoop().RunUntilIdle();
595 rv = callback.WaitForResult();
596 } else if (rv <= 0) {
597 break;
599 result->append(buf->data(), rv);
600 bytes_read += rv;
602 return bytes_read;
605 void VerifyStreamsClosed(const NormalSpdyTransactionHelper& helper) {
606 // This lengthy block is reaching into the pool to dig out the active
607 // session. Once we have the session, we verify that the streams are
608 // all closed and not leaked at this point.
609 const GURL& url = helper.request().url;
610 int port = helper.test_params().ssl_type == SPDYNPN ? 443 : 80;
611 HostPortPair host_port_pair(url.host(), port);
612 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
613 PRIVACY_MODE_DISABLED);
614 BoundNetLog log;
615 const scoped_refptr<HttpNetworkSession>& session = helper.session();
616 base::WeakPtr<SpdySession> spdy_session =
617 session->spdy_session_pool()->FindAvailableSession(key, log);
618 ASSERT_TRUE(spdy_session != NULL);
619 EXPECT_EQ(0u, spdy_session->num_active_streams());
620 EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams());
623 void RunServerPushTest(OrderedSocketData* data,
624 HttpResponseInfo* response,
625 HttpResponseInfo* push_response,
626 const std::string& expected) {
627 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
628 BoundNetLog(), GetParam(), NULL);
629 helper.RunPreTestSetup();
630 helper.AddData(data);
632 HttpNetworkTransaction* trans = helper.trans();
634 // Start the transaction with basic parameters.
635 TestCompletionCallback callback;
636 int rv = trans->Start(
637 &CreateGetRequest(), callback.callback(), BoundNetLog());
638 EXPECT_EQ(ERR_IO_PENDING, rv);
639 rv = callback.WaitForResult();
641 // Request the pushed path.
642 scoped_ptr<HttpNetworkTransaction> trans2(
643 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
644 rv = trans2->Start(
645 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
646 EXPECT_EQ(ERR_IO_PENDING, rv);
647 base::RunLoop().RunUntilIdle();
649 // The data for the pushed path may be coming in more than 1 frame. Compile
650 // the results into a single string.
652 // Read the server push body.
653 std::string result2;
654 ReadResult(trans2.get(), data, &result2);
655 // Read the response body.
656 std::string result;
657 ReadResult(trans, data, &result);
659 // Verify that we consumed all test data.
660 EXPECT_TRUE(data->at_read_eof());
661 EXPECT_TRUE(data->at_write_eof());
663 // Verify that the received push data is same as the expected push data.
664 EXPECT_EQ(result2.compare(expected), 0) << "Received data: "
665 << result2
666 << "||||| Expected data: "
667 << expected;
669 // Verify the SYN_REPLY.
670 // Copy the response info, because trans goes away.
671 *response = *trans->GetResponseInfo();
672 *push_response = *trans2->GetResponseInfo();
674 VerifyStreamsClosed(helper);
677 static void DeleteSessionCallback(NormalSpdyTransactionHelper* helper,
678 int result) {
679 helper->ResetTrans();
682 static void StartTransactionCallback(
683 const scoped_refptr<HttpNetworkSession>& session,
684 int result) {
685 scoped_ptr<HttpNetworkTransaction> trans(
686 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
687 TestCompletionCallback callback;
688 HttpRequestInfo request;
689 request.method = "GET";
690 request.url = GURL("http://www.google.com/");
691 request.load_flags = 0;
692 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
693 EXPECT_EQ(ERR_IO_PENDING, rv);
694 callback.WaitForResult();
697 ChunkedUploadDataStream* upload_chunked_data_stream() const {
698 return upload_chunked_data_stream_.get();
701 SpdyTestUtil spdy_util_;
703 private:
704 scoped_ptr<ChunkedUploadDataStream> upload_chunked_data_stream_;
705 scoped_ptr<UploadDataStream> upload_data_stream_;
706 bool google_get_request_initialized_;
707 bool google_post_request_initialized_;
708 bool google_chunked_post_request_initialized_;
709 HttpRequestInfo google_get_request_;
710 HttpRequestInfo google_post_request_;
711 HttpRequestInfo google_chunked_post_request_;
712 HttpRequestInfo google_get_push_request_;
713 base::ScopedTempDir temp_dir_;
716 //-----------------------------------------------------------------------------
717 // All tests are run with three different connection types: SPDY after NPN
718 // negotiation, SPDY without SSL, and SPDY with SSL.
720 // TODO(akalin): Use ::testing::Combine() when we are able to use
721 // <tr1/tuple>.
722 INSTANTIATE_TEST_CASE_P(
723 Spdy,
724 SpdyNetworkTransactionTest,
725 ::testing::Values(
726 SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNOSSL),
727 SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYSSL),
728 SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNPN),
729 SpdyNetworkTransactionTestParams(kProtoSPDY4_14, SPDYNOSSL),
730 SpdyNetworkTransactionTestParams(kProtoSPDY4_14, SPDYSSL),
731 SpdyNetworkTransactionTestParams(kProtoSPDY4_14, SPDYNPN),
732 SpdyNetworkTransactionTestParams(kProtoSPDY4_15, SPDYNOSSL),
733 SpdyNetworkTransactionTestParams(kProtoSPDY4_15, SPDYSSL),
734 SpdyNetworkTransactionTestParams(kProtoSPDY4_15, SPDYNPN)));
736 // Verify HttpNetworkTransaction constructor.
737 TEST_P(SpdyNetworkTransactionTest, Constructor) {
738 scoped_ptr<SpdySessionDependencies> session_deps(
739 CreateSpdySessionDependencies(GetParam()));
740 scoped_refptr<HttpNetworkSession> session(
741 SpdySessionDependencies::SpdyCreateSession(session_deps.get()));
742 scoped_ptr<HttpTransaction> trans(
743 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
746 TEST_P(SpdyNetworkTransactionTest, Get) {
747 // Construct the request.
748 scoped_ptr<SpdyFrame> req(
749 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
750 MockWrite writes[] = { CreateMockWrite(*req) };
752 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
753 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
754 MockRead reads[] = {
755 CreateMockRead(*resp),
756 CreateMockRead(*body),
757 MockRead(ASYNC, 0, 0) // EOF
760 DelayedSocketData data(1, reads, arraysize(reads),
761 writes, arraysize(writes));
762 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
763 BoundNetLog(), GetParam(), NULL);
764 helper.RunToCompletion(&data);
765 TransactionHelperResult out = helper.output();
766 EXPECT_EQ(OK, out.rv);
767 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
768 EXPECT_EQ("hello!", out.response_data);
771 TEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) {
772 for (RequestPriority p = MINIMUM_PRIORITY; p <= MAXIMUM_PRIORITY;
773 p = RequestPriority(p + 1)) {
774 // Construct the request.
775 scoped_ptr<SpdyFrame> req(
776 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, p, true));
777 MockWrite writes[] = { CreateMockWrite(*req) };
779 SpdyPriority spdy_prio = 0;
780 EXPECT_TRUE(GetSpdyPriority(spdy_util_.spdy_version(), *req, &spdy_prio));
781 // this repeats the RequestPriority-->SpdyPriority mapping from
782 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
783 // sure it's being done right.
784 if (spdy_util_.spdy_version() < SPDY3) {
785 switch (p) {
786 case HIGHEST:
787 EXPECT_EQ(0, spdy_prio);
788 break;
789 case MEDIUM:
790 EXPECT_EQ(1, spdy_prio);
791 break;
792 case LOW:
793 case LOWEST:
794 EXPECT_EQ(2, spdy_prio);
795 break;
796 case IDLE:
797 EXPECT_EQ(3, spdy_prio);
798 break;
799 default:
800 FAIL();
802 } else {
803 switch(p) {
804 case HIGHEST:
805 EXPECT_EQ(0, spdy_prio);
806 break;
807 case MEDIUM:
808 EXPECT_EQ(1, spdy_prio);
809 break;
810 case LOW:
811 EXPECT_EQ(2, spdy_prio);
812 break;
813 case LOWEST:
814 EXPECT_EQ(3, spdy_prio);
815 break;
816 case IDLE:
817 EXPECT_EQ(4, spdy_prio);
818 break;
819 default:
820 FAIL();
824 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
825 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
826 MockRead reads[] = {
827 CreateMockRead(*resp),
828 CreateMockRead(*body),
829 MockRead(ASYNC, 0, 0) // EOF
832 DelayedSocketData data(1, reads, arraysize(reads),
833 writes, arraysize(writes));
834 HttpRequestInfo http_req = CreateGetRequest();
836 NormalSpdyTransactionHelper helper(http_req, p, BoundNetLog(),
837 GetParam(), NULL);
838 helper.RunToCompletion(&data);
839 TransactionHelperResult out = helper.output();
840 EXPECT_EQ(OK, out.rv);
841 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
842 EXPECT_EQ("hello!", out.response_data);
846 // Start three gets simultaniously; making sure that multiplexed
847 // streams work properly.
849 // This can't use the TransactionHelper method, since it only
850 // handles a single transaction, and finishes them as soon
851 // as it launches them.
853 // TODO(gavinp): create a working generalized TransactionHelper that
854 // can allow multiple streams in flight.
856 TEST_P(SpdyNetworkTransactionTest, ThreeGets) {
857 scoped_ptr<SpdyFrame> req(
858 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
859 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
860 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
861 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
863 scoped_ptr<SpdyFrame> req2(
864 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
865 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
866 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
867 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
869 scoped_ptr<SpdyFrame> req3(
870 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
871 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
872 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
873 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
875 MockWrite writes[] = {
876 CreateMockWrite(*req),
877 CreateMockWrite(*req2),
878 CreateMockWrite(*req3),
880 MockRead reads[] = {
881 CreateMockRead(*resp, 1),
882 CreateMockRead(*body),
883 CreateMockRead(*resp2, 4),
884 CreateMockRead(*body2),
885 CreateMockRead(*resp3, 7),
886 CreateMockRead(*body3),
888 CreateMockRead(*fbody),
889 CreateMockRead(*fbody2),
890 CreateMockRead(*fbody3),
892 MockRead(ASYNC, 0, 0), // EOF
894 OrderedSocketData data(reads, arraysize(reads),
895 writes, arraysize(writes));
896 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
898 BoundNetLog log;
899 TransactionHelperResult out;
900 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
901 BoundNetLog(), GetParam(), NULL);
902 helper.RunPreTestSetup();
903 helper.AddData(&data);
904 // We require placeholder data because three get requests are sent out, so
905 // there needs to be three sets of SSL connection data.
906 helper.AddData(&data_placeholder);
907 helper.AddData(&data_placeholder);
908 scoped_ptr<HttpNetworkTransaction> trans1(
909 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
910 scoped_ptr<HttpNetworkTransaction> trans2(
911 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
912 scoped_ptr<HttpNetworkTransaction> trans3(
913 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
915 TestCompletionCallback callback1;
916 TestCompletionCallback callback2;
917 TestCompletionCallback callback3;
919 HttpRequestInfo httpreq1 = CreateGetRequest();
920 HttpRequestInfo httpreq2 = CreateGetRequest();
921 HttpRequestInfo httpreq3 = CreateGetRequest();
923 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
924 ASSERT_EQ(ERR_IO_PENDING, out.rv);
925 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
926 ASSERT_EQ(ERR_IO_PENDING, out.rv);
927 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
928 ASSERT_EQ(ERR_IO_PENDING, out.rv);
930 out.rv = callback1.WaitForResult();
931 ASSERT_EQ(OK, out.rv);
932 out.rv = callback3.WaitForResult();
933 ASSERT_EQ(OK, out.rv);
935 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
936 EXPECT_TRUE(response1->headers.get() != NULL);
937 EXPECT_TRUE(response1->was_fetched_via_spdy);
938 out.status_line = response1->headers->GetStatusLine();
939 out.response_info = *response1;
941 trans2->GetResponseInfo();
943 out.rv = ReadTransaction(trans1.get(), &out.response_data);
944 helper.VerifyDataConsumed();
945 EXPECT_EQ(OK, out.rv);
947 EXPECT_EQ(OK, out.rv);
948 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
949 EXPECT_EQ("hello!hello!", out.response_data);
952 TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
953 scoped_ptr<SpdyFrame> req(
954 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
955 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
956 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
957 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
959 scoped_ptr<SpdyFrame> req2(
960 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
961 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
962 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
963 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
965 MockWrite writes[] = {
966 CreateMockWrite(*req),
967 CreateMockWrite(*req2),
969 MockRead reads[] = {
970 CreateMockRead(*resp, 1),
971 CreateMockRead(*body),
972 CreateMockRead(*resp2, 4),
973 CreateMockRead(*body2),
974 CreateMockRead(*fbody),
975 CreateMockRead(*fbody2),
976 MockRead(ASYNC, 0, 0), // EOF
978 OrderedSocketData data(reads, arraysize(reads),
979 writes, arraysize(writes));
981 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
983 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
984 data_placeholder.set_connect_data(never_finishing_connect);
986 BoundNetLog log;
987 TransactionHelperResult out;
988 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
989 BoundNetLog(), GetParam(), NULL);
990 helper.RunPreTestSetup();
991 helper.AddData(&data);
992 // We require placeholder data because two get requests are sent out, so
993 // there needs to be two sets of SSL connection data.
994 helper.AddData(&data_placeholder);
995 scoped_ptr<HttpNetworkTransaction> trans1(
996 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
997 scoped_ptr<HttpNetworkTransaction> trans2(
998 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1000 TestCompletionCallback callback1;
1001 TestCompletionCallback callback2;
1003 HttpRequestInfo httpreq1 = CreateGetRequest();
1004 HttpRequestInfo httpreq2 = CreateGetRequest();
1006 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1007 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1008 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1009 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1011 out.rv = callback1.WaitForResult();
1012 ASSERT_EQ(OK, out.rv);
1013 out.rv = callback2.WaitForResult();
1014 ASSERT_EQ(OK, out.rv);
1016 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1017 EXPECT_TRUE(response1->headers.get() != NULL);
1018 EXPECT_TRUE(response1->was_fetched_via_spdy);
1019 out.status_line = response1->headers->GetStatusLine();
1020 out.response_info = *response1;
1021 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1022 EXPECT_EQ(OK, out.rv);
1023 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1024 EXPECT_EQ("hello!hello!", out.response_data);
1026 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1027 EXPECT_TRUE(response2->headers.get() != NULL);
1028 EXPECT_TRUE(response2->was_fetched_via_spdy);
1029 out.status_line = response2->headers->GetStatusLine();
1030 out.response_info = *response2;
1031 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1032 EXPECT_EQ(OK, out.rv);
1033 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1034 EXPECT_EQ("hello!hello!", out.response_data);
1036 helper.VerifyDataConsumed();
1039 TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
1040 scoped_ptr<SpdyFrame> req(
1041 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1042 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1043 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1044 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
1046 scoped_ptr<SpdyFrame> req2(
1047 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1048 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1049 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1050 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1052 MockWrite writes[] = {
1053 CreateMockWrite(*req),
1054 CreateMockWrite(*req2),
1056 MockRead reads[] = {
1057 CreateMockRead(*resp, 1),
1058 CreateMockRead(*body),
1059 CreateMockRead(*resp2, 4),
1060 CreateMockRead(*body2),
1061 CreateMockRead(*fbody),
1062 CreateMockRead(*fbody2),
1063 MockRead(ASYNC, 0, 0), // EOF
1065 OrderedSocketData preconnect_data(reads, arraysize(reads),
1066 writes, arraysize(writes));
1068 MockConnect never_finishing_connect(ASYNC, ERR_IO_PENDING);
1070 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1071 data_placeholder.set_connect_data(never_finishing_connect);
1073 BoundNetLog log;
1074 TransactionHelperResult out;
1075 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1076 BoundNetLog(), GetParam(), NULL);
1077 helper.RunPreTestSetup();
1078 helper.AddData(&preconnect_data);
1079 // We require placeholder data because 3 connections are attempted (first is
1080 // the preconnect, 2nd and 3rd are the never finished connections.
1081 helper.AddData(&data_placeholder);
1082 helper.AddData(&data_placeholder);
1084 scoped_ptr<HttpNetworkTransaction> trans1(
1085 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1086 scoped_ptr<HttpNetworkTransaction> trans2(
1087 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1089 TestCompletionCallback callback1;
1090 TestCompletionCallback callback2;
1092 HttpRequestInfo httpreq = CreateGetRequest();
1094 // Preconnect the first.
1095 SSLConfig preconnect_ssl_config;
1096 helper.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config);
1097 HttpStreamFactory* http_stream_factory =
1098 helper.session()->http_stream_factory();
1099 helper.session()->GetNextProtos(&preconnect_ssl_config.next_protos);
1101 http_stream_factory->PreconnectStreams(
1102 1, httpreq, DEFAULT_PRIORITY,
1103 preconnect_ssl_config, preconnect_ssl_config);
1105 out.rv = trans1->Start(&httpreq, callback1.callback(), log);
1106 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1107 out.rv = trans2->Start(&httpreq, callback2.callback(), log);
1108 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1110 out.rv = callback1.WaitForResult();
1111 ASSERT_EQ(OK, out.rv);
1112 out.rv = callback2.WaitForResult();
1113 ASSERT_EQ(OK, out.rv);
1115 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1116 EXPECT_TRUE(response1->headers.get() != NULL);
1117 EXPECT_TRUE(response1->was_fetched_via_spdy);
1118 out.status_line = response1->headers->GetStatusLine();
1119 out.response_info = *response1;
1120 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1121 EXPECT_EQ(OK, out.rv);
1122 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1123 EXPECT_EQ("hello!hello!", out.response_data);
1125 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1126 EXPECT_TRUE(response2->headers.get() != NULL);
1127 EXPECT_TRUE(response2->was_fetched_via_spdy);
1128 out.status_line = response2->headers->GetStatusLine();
1129 out.response_info = *response2;
1130 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1131 EXPECT_EQ(OK, out.rv);
1132 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1133 EXPECT_EQ("hello!hello!", out.response_data);
1135 helper.VerifyDataConsumed();
1138 // Similar to ThreeGets above, however this test adds a SETTINGS
1139 // frame. The SETTINGS frame is read during the IO loop waiting on
1140 // the first transaction completion, and sets a maximum concurrent
1141 // stream limit of 1. This means that our IO loop exists after the
1142 // second transaction completes, so we can assert on read_index().
1143 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
1144 // Construct the request.
1145 scoped_ptr<SpdyFrame> req(
1146 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1147 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1148 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1149 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
1151 scoped_ptr<SpdyFrame> req2(
1152 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1153 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1154 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1155 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1157 scoped_ptr<SpdyFrame> req3(
1158 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
1159 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
1160 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
1161 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
1163 SettingsMap settings;
1164 const uint32 max_concurrent_streams = 1;
1165 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1166 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1167 scoped_ptr<SpdyFrame> settings_frame(
1168 spdy_util_.ConstructSpdySettings(settings));
1169 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1171 MockWrite writes[] = {
1172 CreateMockWrite(*req),
1173 CreateMockWrite(*settings_ack, 2),
1174 CreateMockWrite(*req2),
1175 CreateMockWrite(*req3),
1178 MockRead reads[] = {
1179 CreateMockRead(*settings_frame, 1),
1180 CreateMockRead(*resp),
1181 CreateMockRead(*body),
1182 CreateMockRead(*fbody),
1183 CreateMockRead(*resp2, 8),
1184 CreateMockRead(*body2),
1185 CreateMockRead(*fbody2),
1186 CreateMockRead(*resp3, 13),
1187 CreateMockRead(*body3),
1188 CreateMockRead(*fbody3),
1190 MockRead(ASYNC, 0, 0), // EOF
1193 OrderedSocketData data(reads, arraysize(reads),
1194 writes, arraysize(writes));
1195 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1197 BoundNetLog log;
1198 TransactionHelperResult out;
1200 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1201 BoundNetLog(), GetParam(), NULL);
1202 helper.RunPreTestSetup();
1203 helper.AddData(&data);
1204 // We require placeholder data because three get requests are sent out, so
1205 // there needs to be three sets of SSL connection data.
1206 helper.AddData(&data_placeholder);
1207 helper.AddData(&data_placeholder);
1208 scoped_ptr<HttpNetworkTransaction> trans1(
1209 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1210 scoped_ptr<HttpNetworkTransaction> trans2(
1211 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1212 scoped_ptr<HttpNetworkTransaction> trans3(
1213 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1215 TestCompletionCallback callback1;
1216 TestCompletionCallback callback2;
1217 TestCompletionCallback callback3;
1219 HttpRequestInfo httpreq1 = CreateGetRequest();
1220 HttpRequestInfo httpreq2 = CreateGetRequest();
1221 HttpRequestInfo httpreq3 = CreateGetRequest();
1223 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1224 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1225 // Run transaction 1 through quickly to force a read of our SETTINGS
1226 // frame.
1227 out.rv = callback1.WaitForResult();
1228 ASSERT_EQ(OK, out.rv);
1230 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1231 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1232 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1233 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1234 out.rv = callback2.WaitForResult();
1235 ASSERT_EQ(OK, out.rv);
1236 EXPECT_EQ(7U, data.read_index()); // i.e. the third trans was queued
1238 out.rv = callback3.WaitForResult();
1239 ASSERT_EQ(OK, out.rv);
1241 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1242 ASSERT_TRUE(response1 != NULL);
1243 EXPECT_TRUE(response1->headers.get() != NULL);
1244 EXPECT_TRUE(response1->was_fetched_via_spdy);
1245 out.status_line = response1->headers->GetStatusLine();
1246 out.response_info = *response1;
1247 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1248 EXPECT_EQ(OK, out.rv);
1249 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1250 EXPECT_EQ("hello!hello!", out.response_data);
1252 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1253 out.status_line = response2->headers->GetStatusLine();
1254 out.response_info = *response2;
1255 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1256 EXPECT_EQ(OK, out.rv);
1257 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1258 EXPECT_EQ("hello!hello!", out.response_data);
1260 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1261 out.status_line = response3->headers->GetStatusLine();
1262 out.response_info = *response3;
1263 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1264 EXPECT_EQ(OK, out.rv);
1265 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1266 EXPECT_EQ("hello!hello!", out.response_data);
1268 helper.VerifyDataConsumed();
1270 EXPECT_EQ(OK, out.rv);
1273 // Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1274 // a fourth transaction. The third and fourth transactions have
1275 // different data ("hello!" vs "hello!hello!") and because of the
1276 // user specified priority, we expect to see them inverted in
1277 // the response from the server.
1278 TEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
1279 // Construct the request.
1280 scoped_ptr<SpdyFrame> req(
1281 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1282 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1283 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1284 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
1286 scoped_ptr<SpdyFrame> req2(
1287 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1288 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1289 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1290 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1292 scoped_ptr<SpdyFrame> req4(
1293 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, HIGHEST, true));
1294 scoped_ptr<SpdyFrame> resp4(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
1295 scoped_ptr<SpdyFrame> fbody4(spdy_util_.ConstructSpdyBodyFrame(5, true));
1297 scoped_ptr<SpdyFrame> req3(
1298 spdy_util_.ConstructSpdyGet(NULL, 0, false, 7, LOWEST, true));
1299 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 7));
1300 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(7, false));
1301 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(7, true));
1303 SettingsMap settings;
1304 const uint32 max_concurrent_streams = 1;
1305 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1306 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1307 scoped_ptr<SpdyFrame> settings_frame(
1308 spdy_util_.ConstructSpdySettings(settings));
1309 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1311 MockWrite writes[] = { CreateMockWrite(*req),
1312 CreateMockWrite(*settings_ack, 2),
1313 CreateMockWrite(*req2),
1314 CreateMockWrite(*req4),
1315 CreateMockWrite(*req3),
1317 MockRead reads[] = {
1318 CreateMockRead(*settings_frame, 1),
1319 CreateMockRead(*resp),
1320 CreateMockRead(*body),
1321 CreateMockRead(*fbody),
1322 CreateMockRead(*resp2, 8),
1323 CreateMockRead(*body2),
1324 CreateMockRead(*fbody2),
1325 CreateMockRead(*resp4, 14),
1326 CreateMockRead(*fbody4),
1327 CreateMockRead(*resp3, 17),
1328 CreateMockRead(*body3),
1329 CreateMockRead(*fbody3),
1331 MockRead(ASYNC, 0, 0), // EOF
1334 OrderedSocketData data(reads, arraysize(reads),
1335 writes, arraysize(writes));
1336 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1338 BoundNetLog log;
1339 TransactionHelperResult out;
1340 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1341 BoundNetLog(), GetParam(), NULL);
1342 helper.RunPreTestSetup();
1343 helper.AddData(&data);
1344 // We require placeholder data because four get requests are sent out, so
1345 // there needs to be four sets of SSL connection data.
1346 helper.AddData(&data_placeholder);
1347 helper.AddData(&data_placeholder);
1348 helper.AddData(&data_placeholder);
1349 scoped_ptr<HttpNetworkTransaction> trans1(
1350 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1351 scoped_ptr<HttpNetworkTransaction> trans2(
1352 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1353 scoped_ptr<HttpNetworkTransaction> trans3(
1354 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1355 scoped_ptr<HttpNetworkTransaction> trans4(
1356 new HttpNetworkTransaction(HIGHEST, helper.session().get()));
1358 TestCompletionCallback callback1;
1359 TestCompletionCallback callback2;
1360 TestCompletionCallback callback3;
1361 TestCompletionCallback callback4;
1363 HttpRequestInfo httpreq1 = CreateGetRequest();
1364 HttpRequestInfo httpreq2 = CreateGetRequest();
1365 HttpRequestInfo httpreq3 = CreateGetRequest();
1366 HttpRequestInfo httpreq4 = CreateGetRequest();
1368 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1369 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1370 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1371 out.rv = callback1.WaitForResult();
1372 ASSERT_EQ(OK, out.rv);
1374 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1375 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1376 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1377 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1378 out.rv = trans4->Start(&httpreq4, callback4.callback(), log);
1379 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1381 out.rv = callback2.WaitForResult();
1382 ASSERT_EQ(OK, out.rv);
1383 EXPECT_EQ(data.read_index(), 7U); // i.e. the third & fourth trans queued
1385 out.rv = callback3.WaitForResult();
1386 ASSERT_EQ(OK, out.rv);
1388 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1389 EXPECT_TRUE(response1->headers.get() != NULL);
1390 EXPECT_TRUE(response1->was_fetched_via_spdy);
1391 out.status_line = response1->headers->GetStatusLine();
1392 out.response_info = *response1;
1393 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1394 EXPECT_EQ(OK, out.rv);
1395 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1396 EXPECT_EQ("hello!hello!", out.response_data);
1398 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1399 out.status_line = response2->headers->GetStatusLine();
1400 out.response_info = *response2;
1401 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1402 EXPECT_EQ(OK, out.rv);
1403 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1404 EXPECT_EQ("hello!hello!", out.response_data);
1406 // notice: response3 gets two hellos, response4 gets one
1407 // hello, so we know dequeuing priority was respected.
1408 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1409 out.status_line = response3->headers->GetStatusLine();
1410 out.response_info = *response3;
1411 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1412 EXPECT_EQ(OK, out.rv);
1413 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1414 EXPECT_EQ("hello!hello!", out.response_data);
1416 out.rv = callback4.WaitForResult();
1417 EXPECT_EQ(OK, out.rv);
1418 const HttpResponseInfo* response4 = trans4->GetResponseInfo();
1419 out.status_line = response4->headers->GetStatusLine();
1420 out.response_info = *response4;
1421 out.rv = ReadTransaction(trans4.get(), &out.response_data);
1422 EXPECT_EQ(OK, out.rv);
1423 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1424 EXPECT_EQ("hello!", out.response_data);
1425 helper.VerifyDataConsumed();
1426 EXPECT_EQ(OK, out.rv);
1429 // Similar to ThreeGetsMaxConcurrrent above, however, this test
1430 // deletes a session in the middle of the transaction to insure
1431 // that we properly remove pendingcreatestream objects from
1432 // the spdy_session
1433 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
1434 // Construct the request.
1435 scoped_ptr<SpdyFrame> req(
1436 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1437 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1438 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1439 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
1441 scoped_ptr<SpdyFrame> req2(
1442 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1443 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1444 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1445 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1447 SettingsMap settings;
1448 const uint32 max_concurrent_streams = 1;
1449 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1450 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1451 scoped_ptr<SpdyFrame> settings_frame(
1452 spdy_util_.ConstructSpdySettings(settings));
1453 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1455 MockWrite writes[] = {
1456 CreateMockWrite(*req),
1457 CreateMockWrite(*settings_ack, 2),
1458 CreateMockWrite(*req2),
1460 MockRead reads[] = {
1461 CreateMockRead(*settings_frame, 1),
1462 CreateMockRead(*resp),
1463 CreateMockRead(*body),
1464 CreateMockRead(*fbody),
1465 CreateMockRead(*resp2, 8),
1466 CreateMockRead(*body2),
1467 CreateMockRead(*fbody2),
1468 MockRead(ASYNC, 0, 0), // EOF
1471 OrderedSocketData data(reads, arraysize(reads),
1472 writes, arraysize(writes));
1473 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1475 BoundNetLog log;
1476 TransactionHelperResult out;
1477 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1478 BoundNetLog(), GetParam(), NULL);
1479 helper.RunPreTestSetup();
1480 helper.AddData(&data);
1481 // We require placeholder data because three get requests are sent out, so
1482 // there needs to be three sets of SSL connection data.
1483 helper.AddData(&data_placeholder);
1484 helper.AddData(&data_placeholder);
1485 scoped_ptr<HttpNetworkTransaction> trans1(
1486 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1487 scoped_ptr<HttpNetworkTransaction> trans2(
1488 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1489 scoped_ptr<HttpNetworkTransaction> trans3(
1490 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1492 TestCompletionCallback callback1;
1493 TestCompletionCallback callback2;
1494 TestCompletionCallback callback3;
1496 HttpRequestInfo httpreq1 = CreateGetRequest();
1497 HttpRequestInfo httpreq2 = CreateGetRequest();
1498 HttpRequestInfo httpreq3 = CreateGetRequest();
1500 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1501 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1502 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1503 out.rv = callback1.WaitForResult();
1504 ASSERT_EQ(OK, out.rv);
1506 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1507 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1508 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1509 delete trans3.release();
1510 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1511 out.rv = callback2.WaitForResult();
1512 ASSERT_EQ(OK, out.rv);
1514 EXPECT_EQ(8U, data.read_index());
1516 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1517 ASSERT_TRUE(response1 != NULL);
1518 EXPECT_TRUE(response1->headers.get() != NULL);
1519 EXPECT_TRUE(response1->was_fetched_via_spdy);
1520 out.status_line = response1->headers->GetStatusLine();
1521 out.response_info = *response1;
1522 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1523 EXPECT_EQ(OK, out.rv);
1524 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1525 EXPECT_EQ("hello!hello!", out.response_data);
1527 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1528 ASSERT_TRUE(response2 != NULL);
1529 out.status_line = response2->headers->GetStatusLine();
1530 out.response_info = *response2;
1531 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1532 EXPECT_EQ(OK, out.rv);
1533 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1534 EXPECT_EQ("hello!hello!", out.response_data);
1535 helper.VerifyDataConsumed();
1536 EXPECT_EQ(OK, out.rv);
1539 namespace {
1541 // The KillerCallback will delete the transaction on error as part of the
1542 // callback.
1543 class KillerCallback : public TestCompletionCallbackBase {
1544 public:
1545 explicit KillerCallback(HttpNetworkTransaction* transaction)
1546 : transaction_(transaction),
1547 callback_(base::Bind(&KillerCallback::OnComplete,
1548 base::Unretained(this))) {
1551 ~KillerCallback() override {}
1553 const CompletionCallback& callback() const { return callback_; }
1555 private:
1556 void OnComplete(int result) {
1557 if (result < 0)
1558 delete transaction_;
1560 SetResult(result);
1563 HttpNetworkTransaction* transaction_;
1564 CompletionCallback callback_;
1567 } // namespace
1569 // Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1570 // closes the socket while we have a pending transaction waiting for
1571 // a pending stream creation. http://crbug.com/52901
1572 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
1573 // Construct the request.
1574 scoped_ptr<SpdyFrame> req(
1575 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1576 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1577 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1578 scoped_ptr<SpdyFrame> fin_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1580 scoped_ptr<SpdyFrame> req2(
1581 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1582 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1584 SettingsMap settings;
1585 const uint32 max_concurrent_streams = 1;
1586 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1587 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1588 scoped_ptr<SpdyFrame> settings_frame(
1589 spdy_util_.ConstructSpdySettings(settings));
1590 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1592 MockWrite writes[] = {
1593 CreateMockWrite(*req),
1594 CreateMockWrite(*settings_ack, 2),
1595 CreateMockWrite(*req2),
1597 MockRead reads[] = {
1598 CreateMockRead(*settings_frame, 1),
1599 CreateMockRead(*resp),
1600 CreateMockRead(*body),
1601 CreateMockRead(*fin_body),
1602 CreateMockRead(*resp2, 8),
1603 MockRead(ASYNC, ERR_CONNECTION_RESET, 0), // Abort!
1606 OrderedSocketData data(reads, arraysize(reads),
1607 writes, arraysize(writes));
1608 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1610 BoundNetLog log;
1611 TransactionHelperResult out;
1612 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1613 BoundNetLog(), GetParam(), NULL);
1614 helper.RunPreTestSetup();
1615 helper.AddData(&data);
1616 // We require placeholder data because three get requests are sent out, so
1617 // there needs to be three sets of SSL connection data.
1618 helper.AddData(&data_placeholder);
1619 helper.AddData(&data_placeholder);
1620 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session().get());
1621 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session().get());
1622 HttpNetworkTransaction* trans3(
1623 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1625 TestCompletionCallback callback1;
1626 TestCompletionCallback callback2;
1627 KillerCallback callback3(trans3);
1629 HttpRequestInfo httpreq1 = CreateGetRequest();
1630 HttpRequestInfo httpreq2 = CreateGetRequest();
1631 HttpRequestInfo httpreq3 = CreateGetRequest();
1633 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
1634 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1635 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1636 out.rv = callback1.WaitForResult();
1637 ASSERT_EQ(OK, out.rv);
1639 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
1640 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1641 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1642 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1643 out.rv = callback3.WaitForResult();
1644 ASSERT_EQ(ERR_ABORTED, out.rv);
1646 EXPECT_EQ(6U, data.read_index());
1648 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
1649 ASSERT_TRUE(response1 != NULL);
1650 EXPECT_TRUE(response1->headers.get() != NULL);
1651 EXPECT_TRUE(response1->was_fetched_via_spdy);
1652 out.status_line = response1->headers->GetStatusLine();
1653 out.response_info = *response1;
1654 out.rv = ReadTransaction(&trans1, &out.response_data);
1655 EXPECT_EQ(OK, out.rv);
1657 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
1658 ASSERT_TRUE(response2 != NULL);
1659 out.status_line = response2->headers->GetStatusLine();
1660 out.response_info = *response2;
1661 out.rv = ReadTransaction(&trans2, &out.response_data);
1662 EXPECT_EQ(ERR_CONNECTION_RESET, out.rv);
1664 helper.VerifyDataConsumed();
1667 // Test that a simple PUT request works.
1668 TEST_P(SpdyNetworkTransactionTest, Put) {
1669 // Setup the request
1670 HttpRequestInfo request;
1671 request.method = "PUT";
1672 request.url = GURL("http://www.google.com/");
1674 scoped_ptr<SpdyHeaderBlock> put_headers(
1675 spdy_util_.ConstructPutHeaderBlock("http://www.google.com", 0));
1676 scoped_ptr<SpdyFrame> req(
1677 spdy_util_.ConstructSpdySyn(1, *put_headers, LOWEST, false, true));
1678 MockWrite writes[] = {
1679 CreateMockWrite(*req),
1682 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1683 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1684 MockRead reads[] = {
1685 CreateMockRead(*resp),
1686 CreateMockRead(*body),
1687 MockRead(ASYNC, 0, 0) // EOF
1690 DelayedSocketData data(1, reads, arraysize(reads),
1691 writes, arraysize(writes));
1692 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1693 BoundNetLog(), GetParam(), NULL);
1694 helper.RunToCompletion(&data);
1695 TransactionHelperResult out = helper.output();
1697 EXPECT_EQ(OK, out.rv);
1698 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1701 // Test that a simple HEAD request works.
1702 TEST_P(SpdyNetworkTransactionTest, Head) {
1703 // Setup the request
1704 HttpRequestInfo request;
1705 request.method = "HEAD";
1706 request.url = GURL("http://www.google.com/");
1708 scoped_ptr<SpdyHeaderBlock> head_headers(
1709 spdy_util_.ConstructHeadHeaderBlock("http://www.google.com", 0));
1710 scoped_ptr<SpdyFrame> req(
1711 spdy_util_.ConstructSpdySyn(1, *head_headers, LOWEST, false, true));
1712 MockWrite writes[] = {
1713 CreateMockWrite(*req),
1716 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1717 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1718 MockRead reads[] = {
1719 CreateMockRead(*resp),
1720 CreateMockRead(*body),
1721 MockRead(ASYNC, 0, 0) // EOF
1724 DelayedSocketData data(1, reads, arraysize(reads),
1725 writes, arraysize(writes));
1726 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1727 BoundNetLog(), GetParam(), NULL);
1728 helper.RunToCompletion(&data);
1729 TransactionHelperResult out = helper.output();
1731 EXPECT_EQ(OK, out.rv);
1732 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1735 // Test that a simple POST works.
1736 TEST_P(SpdyNetworkTransactionTest, Post) {
1737 scoped_ptr<SpdyFrame> req(
1738 spdy_util_.ConstructSpdyPost(
1739 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
1740 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1741 MockWrite writes[] = {
1742 CreateMockWrite(*req),
1743 CreateMockWrite(*body), // POST upload frame
1746 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1747 MockRead reads[] = {
1748 CreateMockRead(*resp),
1749 CreateMockRead(*body),
1750 MockRead(ASYNC, 0, 0) // EOF
1753 DelayedSocketData data(2, reads, arraysize(reads),
1754 writes, arraysize(writes));
1755 NormalSpdyTransactionHelper helper(CreatePostRequest(), DEFAULT_PRIORITY,
1756 BoundNetLog(), GetParam(), NULL);
1757 helper.RunToCompletion(&data);
1758 TransactionHelperResult out = helper.output();
1759 EXPECT_EQ(OK, out.rv);
1760 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1761 EXPECT_EQ("hello!", out.response_data);
1764 // Test that a POST with a file works.
1765 TEST_P(SpdyNetworkTransactionTest, FilePost) {
1766 scoped_ptr<SpdyFrame> req(
1767 spdy_util_.ConstructSpdyPost(
1768 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
1769 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1770 MockWrite writes[] = {
1771 CreateMockWrite(*req),
1772 CreateMockWrite(*body), // POST upload frame
1775 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1776 MockRead reads[] = {
1777 CreateMockRead(*resp),
1778 CreateMockRead(*body),
1779 MockRead(ASYNC, 0, 0) // EOF
1782 DelayedSocketData data(2, reads, arraysize(reads),
1783 writes, arraysize(writes));
1784 NormalSpdyTransactionHelper helper(CreateFilePostRequest(), DEFAULT_PRIORITY,
1785 BoundNetLog(), GetParam(), NULL);
1786 helper.RunToCompletion(&data);
1787 TransactionHelperResult out = helper.output();
1788 EXPECT_EQ(OK, out.rv);
1789 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1790 EXPECT_EQ("hello!", out.response_data);
1793 // Test that a POST with a unreadable file fails.
1794 TEST_P(SpdyNetworkTransactionTest, UnreadableFilePost) {
1795 MockWrite writes[] = {
1796 MockWrite(ASYNC, 0, 0) // EOF
1798 MockRead reads[] = {
1799 MockRead(ASYNC, 0, 0) // EOF
1802 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
1803 NormalSpdyTransactionHelper helper(CreateUnreadableFilePostRequest(),
1804 DEFAULT_PRIORITY,
1805 BoundNetLog(), GetParam(), NULL);
1806 helper.RunPreTestSetup();
1807 helper.AddData(&data);
1808 helper.RunDefaultTest();
1810 base::RunLoop().RunUntilIdle();
1811 helper.VerifyDataNotConsumed();
1812 EXPECT_EQ(ERR_ACCESS_DENIED, helper.output().rv);
1815 // Test that a complex POST works.
1816 TEST_P(SpdyNetworkTransactionTest, ComplexPost) {
1817 scoped_ptr<SpdyFrame> req(
1818 spdy_util_.ConstructSpdyPost(
1819 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
1820 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1821 MockWrite writes[] = {
1822 CreateMockWrite(*req),
1823 CreateMockWrite(*body), // POST upload frame
1826 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1827 MockRead reads[] = {
1828 CreateMockRead(*resp),
1829 CreateMockRead(*body),
1830 MockRead(ASYNC, 0, 0) // EOF
1833 DelayedSocketData data(2, reads, arraysize(reads),
1834 writes, arraysize(writes));
1835 NormalSpdyTransactionHelper helper(CreateComplexPostRequest(),
1836 DEFAULT_PRIORITY,
1837 BoundNetLog(), GetParam(), NULL);
1838 helper.RunToCompletion(&data);
1839 TransactionHelperResult out = helper.output();
1840 EXPECT_EQ(OK, out.rv);
1841 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1842 EXPECT_EQ("hello!", out.response_data);
1845 // Test that a chunked POST works.
1846 TEST_P(SpdyNetworkTransactionTest, ChunkedPost) {
1847 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1848 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1849 MockWrite writes[] = {
1850 CreateMockWrite(*req),
1851 CreateMockWrite(*body),
1854 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1855 MockRead reads[] = {
1856 CreateMockRead(*resp),
1857 CreateMockRead(*body),
1858 MockRead(ASYNC, 0, 0) // EOF
1861 DelayedSocketData data(2, reads, arraysize(reads),
1862 writes, arraysize(writes));
1863 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
1864 DEFAULT_PRIORITY,
1865 BoundNetLog(), GetParam(), NULL);
1867 // These chunks get merged into a single frame when being sent.
1868 const int kFirstChunkSize = kUploadDataSize/2;
1869 upload_chunked_data_stream()->AppendData(kUploadData, kFirstChunkSize, false);
1870 upload_chunked_data_stream()->AppendData(
1871 kUploadData + kFirstChunkSize, kUploadDataSize - kFirstChunkSize, true);
1873 helper.RunToCompletion(&data);
1874 TransactionHelperResult out = helper.output();
1875 EXPECT_EQ(OK, out.rv);
1876 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1877 EXPECT_EQ(kUploadData, out.response_data);
1880 // Test that a chunked POST works with chunks appended after transaction starts.
1881 TEST_P(SpdyNetworkTransactionTest, DelayedChunkedPost) {
1882 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1883 scoped_ptr<SpdyFrame> chunk1(spdy_util_.ConstructSpdyBodyFrame(1, false));
1884 scoped_ptr<SpdyFrame> chunk2(spdy_util_.ConstructSpdyBodyFrame(1, false));
1885 scoped_ptr<SpdyFrame> chunk3(spdy_util_.ConstructSpdyBodyFrame(1, true));
1886 MockWrite writes[] = {
1887 CreateMockWrite(*req),
1888 CreateMockWrite(*chunk1),
1889 CreateMockWrite(*chunk2),
1890 CreateMockWrite(*chunk3),
1893 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1894 MockRead reads[] = {
1895 CreateMockRead(*resp),
1896 CreateMockRead(*chunk1),
1897 CreateMockRead(*chunk2),
1898 CreateMockRead(*chunk3),
1899 MockRead(ASYNC, 0, 0) // EOF
1902 DelayedSocketData data(4, reads, arraysize(reads),
1903 writes, arraysize(writes));
1904 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
1905 DEFAULT_PRIORITY,
1906 BoundNetLog(), GetParam(), NULL);
1908 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
1910 helper.RunPreTestSetup();
1911 helper.AddData(&data);
1912 ASSERT_TRUE(helper.StartDefaultTest());
1914 base::RunLoop().RunUntilIdle();
1915 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
1916 base::RunLoop().RunUntilIdle();
1917 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true);
1919 helper.FinishDefaultTest();
1920 helper.VerifyDataConsumed();
1922 std::string expected_response;
1923 expected_response += kUploadData;
1924 expected_response += kUploadData;
1925 expected_response += kUploadData;
1927 TransactionHelperResult out = helper.output();
1928 EXPECT_EQ(OK, out.rv);
1929 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1930 EXPECT_EQ(expected_response, out.response_data);
1933 // Test that a POST without any post data works.
1934 TEST_P(SpdyNetworkTransactionTest, NullPost) {
1935 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
1936 // Setup the request
1937 HttpRequestInfo request;
1938 request.method = "POST";
1939 request.url = GURL(kRequestUrl);
1940 // Create an empty UploadData.
1941 request.upload_data_stream = NULL;
1943 // When request.upload_data_stream is NULL for post, content-length is
1944 // expected to be 0.
1945 scoped_ptr<SpdyHeaderBlock> req_block(
1946 spdy_util_.ConstructPostHeaderBlock(kRequestUrl, 0));
1947 scoped_ptr<SpdyFrame> req(
1948 spdy_util_.ConstructSpdySyn(1, *req_block, LOWEST, false, true));
1950 MockWrite writes[] = {
1951 CreateMockWrite(*req),
1954 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1955 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1956 MockRead reads[] = {
1957 CreateMockRead(*resp),
1958 CreateMockRead(*body),
1959 MockRead(ASYNC, 0, 0) // EOF
1962 DelayedSocketData data(1, reads, arraysize(reads),
1963 writes, arraysize(writes));
1965 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1966 BoundNetLog(), GetParam(), NULL);
1967 helper.RunToCompletion(&data);
1968 TransactionHelperResult out = helper.output();
1969 EXPECT_EQ(OK, out.rv);
1970 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1971 EXPECT_EQ("hello!", out.response_data);
1974 // Test that a simple POST works.
1975 TEST_P(SpdyNetworkTransactionTest, EmptyPost) {
1976 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
1977 // Create an empty UploadDataStream.
1978 ScopedVector<UploadElementReader> element_readers;
1979 ElementsUploadDataStream stream(element_readers.Pass(), 0);
1981 // Setup the request
1982 HttpRequestInfo request;
1983 request.method = "POST";
1984 request.url = GURL(kRequestUrl);
1985 request.upload_data_stream = &stream;
1987 const uint64 kContentLength = 0;
1989 scoped_ptr<SpdyHeaderBlock> req_block(
1990 spdy_util_.ConstructPostHeaderBlock(kRequestUrl, kContentLength));
1991 scoped_ptr<SpdyFrame> req(
1992 spdy_util_.ConstructSpdySyn(1, *req_block, LOWEST, false, true));
1994 MockWrite writes[] = {
1995 CreateMockWrite(*req),
1998 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1999 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2000 MockRead reads[] = {
2001 CreateMockRead(*resp),
2002 CreateMockRead(*body),
2003 MockRead(ASYNC, 0, 0) // EOF
2006 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
2008 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
2009 BoundNetLog(), GetParam(), NULL);
2010 helper.RunToCompletion(&data);
2011 TransactionHelperResult out = helper.output();
2012 EXPECT_EQ(OK, out.rv);
2013 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
2014 EXPECT_EQ("hello!", out.response_data);
2017 // While we're doing a post, the server sends the reply before upload completes.
2018 TEST_P(SpdyNetworkTransactionTest, ResponseBeforePostCompletes) {
2019 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
2020 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2021 MockWrite writes[] = {
2022 CreateMockWrite(*req, 0),
2023 CreateMockWrite(*body, 3),
2025 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
2026 MockRead reads[] = {
2027 CreateMockRead(*resp, 1),
2028 CreateMockRead(*body, 2),
2029 MockRead(ASYNC, 0, 4) // EOF
2032 // Write the request headers, and read the complete response
2033 // while still waiting for chunked request data.
2034 DeterministicSocketData data(reads, arraysize(reads),
2035 writes, arraysize(writes));
2036 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
2037 DEFAULT_PRIORITY,
2038 BoundNetLog(), GetParam(), NULL);
2039 helper.SetDeterministic();
2040 helper.RunPreTestSetup();
2041 helper.AddDeterministicData(&data);
2043 ASSERT_TRUE(helper.StartDefaultTest());
2045 // Process the request headers, SYN_REPLY, and response body.
2046 // The request body is still in flight.
2047 data.RunFor(3);
2049 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
2050 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2052 // Finish sending the request body.
2053 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true);
2054 data.RunFor(2);
2056 std::string response_body;
2057 EXPECT_EQ(OK, ReadTransaction(helper.trans(), &response_body));
2058 EXPECT_EQ(kUploadData, response_body);
2059 helper.VerifyDataConsumed();
2062 // The client upon cancellation tries to send a RST_STREAM frame. The mock
2063 // socket causes the TCP write to return zero. This test checks that the client
2064 // tries to queue up the RST_STREAM frame again.
2065 TEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
2066 scoped_ptr<SpdyFrame> req(
2067 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2068 scoped_ptr<SpdyFrame> rst(
2069 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2070 MockWrite writes[] = {
2071 CreateMockWrite(*req.get(), 0, SYNCHRONOUS),
2072 MockWrite(SYNCHRONOUS, 0, 0, 2),
2073 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
2076 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2077 MockRead reads[] = {
2078 CreateMockRead(*resp.get(), 1, ASYNC),
2079 MockRead(ASYNC, 0, 0, 4) // EOF
2082 DeterministicSocketData data(reads, arraysize(reads),
2083 writes, arraysize(writes));
2084 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2085 BoundNetLog(), GetParam(), NULL);
2086 helper.SetDeterministic();
2087 helper.RunPreTestSetup();
2088 helper.AddDeterministicData(&data);
2089 HttpNetworkTransaction* trans = helper.trans();
2091 TestCompletionCallback callback;
2092 int rv = trans->Start(
2093 &CreateGetRequest(), callback.callback(), BoundNetLog());
2094 EXPECT_EQ(ERR_IO_PENDING, rv);
2096 data.SetStop(2);
2097 data.Run();
2098 helper.ResetTrans();
2099 data.SetStop(20);
2100 data.Run();
2102 helper.VerifyDataConsumed();
2105 // Test that the transaction doesn't crash when we don't have a reply.
2106 TEST_P(SpdyNetworkTransactionTest, ResponseWithoutSynReply) {
2107 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2108 MockRead reads[] = {
2109 CreateMockRead(*body),
2110 MockRead(ASYNC, 0, 0) // EOF
2113 DelayedSocketData data(1, reads, arraysize(reads), NULL, 0);
2114 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2115 BoundNetLog(), GetParam(), NULL);
2116 helper.RunToCompletion(&data);
2117 TransactionHelperResult out = helper.output();
2118 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
2121 // Test that the transaction doesn't crash when we get two replies on the same
2122 // stream ID. See http://crbug.com/45639.
2123 TEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
2124 scoped_ptr<SpdyFrame> req(
2125 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2126 scoped_ptr<SpdyFrame> rst(
2127 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
2128 MockWrite writes[] = {
2129 CreateMockWrite(*req),
2130 CreateMockWrite(*rst),
2133 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2134 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2135 MockRead reads[] = {
2136 CreateMockRead(*resp),
2137 CreateMockRead(*resp),
2138 CreateMockRead(*body),
2139 MockRead(ASYNC, 0, 0) // EOF
2142 DelayedSocketData data(1, reads, arraysize(reads),
2143 writes, arraysize(writes));
2145 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2146 BoundNetLog(), GetParam(), NULL);
2147 helper.RunPreTestSetup();
2148 helper.AddData(&data);
2150 HttpNetworkTransaction* trans = helper.trans();
2152 TestCompletionCallback callback;
2153 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2154 EXPECT_EQ(ERR_IO_PENDING, rv);
2155 rv = callback.WaitForResult();
2156 EXPECT_EQ(OK, rv);
2158 const HttpResponseInfo* response = trans->GetResponseInfo();
2159 ASSERT_TRUE(response != NULL);
2160 EXPECT_TRUE(response->headers.get() != NULL);
2161 EXPECT_TRUE(response->was_fetched_via_spdy);
2162 std::string response_data;
2163 rv = ReadTransaction(trans, &response_data);
2164 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
2166 helper.VerifyDataConsumed();
2169 TEST_P(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) {
2170 // Construct the request.
2171 scoped_ptr<SpdyFrame> req(
2172 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2173 scoped_ptr<SpdyFrame> rst(
2174 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
2175 MockWrite writes[] = {
2176 CreateMockWrite(*req),
2177 CreateMockWrite(*rst),
2180 const char* const headers[] = {
2181 "transfer-encoding", "chunked"
2183 scoped_ptr<SpdyFrame> resp(
2184 spdy_util_.ConstructSpdyGetSynReply(headers, 1, 1));
2185 scoped_ptr<SpdyFrame> body(
2186 spdy_util_.ConstructSpdyBodyFrame(1, true));
2187 MockRead reads[] = {
2188 CreateMockRead(*resp),
2189 CreateMockRead(*body),
2190 MockRead(ASYNC, 0, 0) // EOF
2193 DelayedSocketData data(1, reads, arraysize(reads),
2194 writes, arraysize(writes));
2195 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2196 BoundNetLog(), GetParam(), NULL);
2197 helper.RunToCompletion(&data);
2198 TransactionHelperResult out = helper.output();
2199 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
2201 helper.session()->spdy_session_pool()->CloseAllSessions();
2202 helper.VerifyDataConsumed();
2205 TEST_P(SpdyNetworkTransactionTest, ResetPushWithTransferEncoding) {
2206 // Construct the request.
2207 scoped_ptr<SpdyFrame> req(
2208 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2209 scoped_ptr<SpdyFrame> rst(
2210 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
2211 MockWrite writes[] = {
2212 CreateMockWrite(*req),
2213 CreateMockWrite(*rst),
2216 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2217 const char* const headers[] = {
2218 "transfer-encoding", "chunked"
2220 scoped_ptr<SpdyFrame> push(
2221 spdy_util_.ConstructSpdyPush(headers, arraysize(headers) / 2,
2222 2, 1, "http://www.google.com/1"));
2223 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2224 MockRead reads[] = {
2225 CreateMockRead(*resp),
2226 CreateMockRead(*push),
2227 CreateMockRead(*body),
2228 MockRead(ASYNC, 0, 0) // EOF
2231 DelayedSocketData data(1, reads, arraysize(reads),
2232 writes, arraysize(writes));
2233 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2234 BoundNetLog(), GetParam(), NULL);
2235 helper.RunToCompletion(&data);
2236 TransactionHelperResult out = helper.output();
2237 EXPECT_EQ(OK, out.rv);
2238 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
2239 EXPECT_EQ("hello!", out.response_data);
2241 helper.session()->spdy_session_pool()->CloseAllSessions();
2242 helper.VerifyDataConsumed();
2245 TEST_P(SpdyNetworkTransactionTest, CancelledTransaction) {
2246 // Construct the request.
2247 scoped_ptr<SpdyFrame> req(
2248 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2249 MockWrite writes[] = {
2250 CreateMockWrite(*req),
2253 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2254 MockRead reads[] = {
2255 CreateMockRead(*resp),
2256 // This following read isn't used by the test, except during the
2257 // RunUntilIdle() call at the end since the SpdySession survives the
2258 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
2259 // MockRead will do here.
2260 MockRead(ASYNC, 0, 0) // EOF
2263 StaticSocketDataProvider data(reads, arraysize(reads),
2264 writes, arraysize(writes));
2266 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2267 BoundNetLog(), GetParam(), NULL);
2268 helper.RunPreTestSetup();
2269 helper.AddData(&data);
2270 HttpNetworkTransaction* trans = helper.trans();
2272 TestCompletionCallback callback;
2273 int rv = trans->Start(
2274 &CreateGetRequest(), callback.callback(), BoundNetLog());
2275 EXPECT_EQ(ERR_IO_PENDING, rv);
2276 helper.ResetTrans(); // Cancel the transaction.
2278 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
2279 // MockClientSocketFactory) are still alive.
2280 base::RunLoop().RunUntilIdle();
2281 helper.VerifyDataNotConsumed();
2284 // Verify that the client sends a Rst Frame upon cancelling the stream.
2285 TEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
2286 scoped_ptr<SpdyFrame> req(
2287 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2288 scoped_ptr<SpdyFrame> rst(
2289 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2290 MockWrite writes[] = {
2291 CreateMockWrite(*req, 0, SYNCHRONOUS),
2292 CreateMockWrite(*rst, 2, SYNCHRONOUS),
2295 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2296 MockRead reads[] = {
2297 CreateMockRead(*resp, 1, ASYNC),
2298 MockRead(ASYNC, 0, 0, 3) // EOF
2301 DeterministicSocketData data(reads, arraysize(reads),
2302 writes, arraysize(writes));
2304 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2305 BoundNetLog(),
2306 GetParam(), NULL);
2307 helper.SetDeterministic();
2308 helper.RunPreTestSetup();
2309 helper.AddDeterministicData(&data);
2310 HttpNetworkTransaction* trans = helper.trans();
2312 TestCompletionCallback callback;
2314 int rv = trans->Start(
2315 &CreateGetRequest(), callback.callback(), BoundNetLog());
2316 EXPECT_EQ(ERR_IO_PENDING, rv);
2318 data.SetStop(2);
2319 data.Run();
2320 helper.ResetTrans();
2321 data.SetStop(20);
2322 data.Run();
2324 helper.VerifyDataConsumed();
2327 // Verify that the client can correctly deal with the user callback attempting
2328 // to start another transaction on a session that is closing down. See
2329 // http://crbug.com/47455
2330 TEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
2331 scoped_ptr<SpdyFrame> req(
2332 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2333 MockWrite writes[] = { CreateMockWrite(*req) };
2334 MockWrite writes2[] = { CreateMockWrite(*req) };
2336 // The indicated length of this frame is longer than its actual length. When
2337 // the session receives an empty frame after this one, it shuts down the
2338 // session, and calls the read callback with the incomplete data.
2339 const uint8 kGetBodyFrame2[] = {
2340 0x00, 0x00, 0x00, 0x01,
2341 0x01, 0x00, 0x00, 0x07,
2342 'h', 'e', 'l', 'l', 'o', '!',
2345 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2346 MockRead reads[] = {
2347 CreateMockRead(*resp, 2),
2348 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause
2349 MockRead(ASYNC, reinterpret_cast<const char*>(kGetBodyFrame2),
2350 arraysize(kGetBodyFrame2), 4),
2351 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
2352 MockRead(ASYNC, 0, 0, 6), // EOF
2354 MockRead reads2[] = {
2355 CreateMockRead(*resp, 2),
2356 MockRead(ASYNC, 0, 0, 3), // EOF
2359 OrderedSocketData data(reads, arraysize(reads),
2360 writes, arraysize(writes));
2361 DelayedSocketData data2(1, reads2, arraysize(reads2),
2362 writes2, arraysize(writes2));
2364 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2365 BoundNetLog(), GetParam(), NULL);
2366 helper.RunPreTestSetup();
2367 helper.AddData(&data);
2368 helper.AddData(&data2);
2369 HttpNetworkTransaction* trans = helper.trans();
2371 // Start the transaction with basic parameters.
2372 TestCompletionCallback callback;
2373 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2374 EXPECT_EQ(ERR_IO_PENDING, rv);
2375 rv = callback.WaitForResult();
2377 const int kSize = 3000;
2378 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
2379 rv = trans->Read(
2380 buf.get(),
2381 kSize,
2382 base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback,
2383 helper.session()));
2384 // This forces an err_IO_pending, which sets the callback.
2385 data.CompleteRead();
2386 // This finishes the read.
2387 data.CompleteRead();
2388 helper.VerifyDataConsumed();
2391 // Verify that the client can correctly deal with the user callback deleting the
2392 // transaction. Failures will usually be valgrind errors. See
2393 // http://crbug.com/46925
2394 TEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
2395 scoped_ptr<SpdyFrame> req(
2396 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2397 MockWrite writes[] = { CreateMockWrite(*req) };
2399 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2400 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2401 MockRead reads[] = {
2402 CreateMockRead(*resp.get(), 2),
2403 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause
2404 CreateMockRead(*body.get(), 4),
2405 MockRead(ASYNC, 0, 0, 5), // EOF
2408 OrderedSocketData data(reads, arraysize(reads),
2409 writes, arraysize(writes));
2411 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2412 BoundNetLog(), GetParam(), NULL);
2413 helper.RunPreTestSetup();
2414 helper.AddData(&data);
2415 HttpNetworkTransaction* trans = helper.trans();
2417 // Start the transaction with basic parameters.
2418 TestCompletionCallback callback;
2419 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2420 EXPECT_EQ(ERR_IO_PENDING, rv);
2421 rv = callback.WaitForResult();
2423 // Setup a user callback which will delete the session, and clear out the
2424 // memory holding the stream object. Note that the callback deletes trans.
2425 const int kSize = 3000;
2426 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
2427 rv = trans->Read(
2428 buf.get(),
2429 kSize,
2430 base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback,
2431 base::Unretained(&helper)));
2432 ASSERT_EQ(ERR_IO_PENDING, rv);
2433 data.CompleteRead();
2435 // Finish running rest of tasks.
2436 base::RunLoop().RunUntilIdle();
2437 helper.VerifyDataConsumed();
2440 // Send a spdy request to www.google.com that gets redirected to www.foo.com.
2441 TEST_P(SpdyNetworkTransactionTest, RedirectGetRequest) {
2442 scoped_ptr<SpdyHeaderBlock> headers(
2443 spdy_util_.ConstructGetHeaderBlock("http://www.google.com/"));
2444 (*headers)["user-agent"] = "";
2445 (*headers)["accept-encoding"] = "gzip, deflate";
2446 scoped_ptr<SpdyHeaderBlock> headers2(
2447 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2448 (*headers2)["user-agent"] = "";
2449 (*headers2)["accept-encoding"] = "gzip, deflate";
2451 // Setup writes/reads to www.google.com
2452 scoped_ptr<SpdyFrame> req(
2453 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
2454 scoped_ptr<SpdyFrame> req2(
2455 spdy_util_.ConstructSpdySyn(1, *headers2, LOWEST, false, true));
2456 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReplyRedirect(1));
2457 MockWrite writes[] = {
2458 CreateMockWrite(*req, 1),
2460 MockRead reads[] = {
2461 CreateMockRead(*resp, 2),
2462 MockRead(ASYNC, 0, 0, 3) // EOF
2465 // Setup writes/reads to www.foo.com
2466 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2467 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
2468 MockWrite writes2[] = {
2469 CreateMockWrite(*req2, 1),
2471 MockRead reads2[] = {
2472 CreateMockRead(*resp2, 2),
2473 CreateMockRead(*body2, 3),
2474 MockRead(ASYNC, 0, 0, 4) // EOF
2476 OrderedSocketData data(reads, arraysize(reads),
2477 writes, arraysize(writes));
2478 OrderedSocketData data2(reads2, arraysize(reads2),
2479 writes2, arraysize(writes2));
2481 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2482 TestDelegate d;
2484 SpdyURLRequestContext spdy_url_request_context(
2485 GetParam().protocol,
2486 false /* force_spdy_over_ssl*/,
2487 true /* force_spdy_always */);
2488 scoped_ptr<URLRequest> r(
2489 spdy_url_request_context.CreateRequest(GURL("http://www.google.com/"),
2490 DEFAULT_PRIORITY,
2492 NULL));
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(net::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(
2584 spdy_url_request_context.CreateRequest(GURL("http://www.google.com/"),
2585 DEFAULT_PRIORITY,
2587 NULL));
2588 spdy_url_request_context.socket_factory().
2589 AddSocketDataProvider(&data);
2591 r->Start();
2592 base::RunLoop().Run();
2594 EXPECT_EQ(0, d.received_redirect_count());
2595 std::string contents("hello!");
2596 EXPECT_EQ(contents, d.data_received());
2598 scoped_ptr<URLRequest> r2(
2599 spdy_url_request_context.CreateRequest(
2600 GURL("http://www.google.com/foo.dat"),
2601 DEFAULT_PRIORITY,
2602 &d2,
2603 NULL));
2604 spdy_url_request_context.socket_factory().
2605 AddSocketDataProvider(&data2);
2607 d2.set_quit_on_redirect(true);
2608 r2->Start();
2609 base::RunLoop().Run();
2610 EXPECT_EQ(1, d2.received_redirect_count());
2612 r2->FollowDeferredRedirect();
2613 base::RunLoop().Run();
2614 EXPECT_EQ(1, d2.response_started_count());
2615 EXPECT_FALSE(d2.received_data_before_response());
2616 EXPECT_EQ(net::URLRequestStatus::SUCCESS, r2->status().status());
2617 std::string contents2("hello!");
2618 EXPECT_EQ(contents2, d2.data_received());
2620 data.CompleteRead();
2621 data2.CompleteRead();
2622 EXPECT_TRUE(data.at_read_eof());
2623 EXPECT_TRUE(data.at_write_eof());
2624 EXPECT_TRUE(data2.at_read_eof());
2625 EXPECT_TRUE(data2.at_write_eof());
2628 TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
2629 scoped_ptr<SpdyFrame> stream1_syn(
2630 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2631 scoped_ptr<SpdyFrame> stream1_body(
2632 spdy_util_.ConstructSpdyBodyFrame(1, true));
2633 MockWrite writes[] = {
2634 CreateMockWrite(*stream1_syn, 1),
2637 scoped_ptr<SpdyFrame>
2638 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2639 scoped_ptr<SpdyFrame>
2640 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2644 "http://www.google.com/foo.dat"));
2645 const char kPushedData[] = "pushed";
2646 scoped_ptr<SpdyFrame> stream2_body(
2647 spdy_util_.ConstructSpdyBodyFrame(
2648 2, kPushedData, strlen(kPushedData), true));
2649 MockRead reads[] = {
2650 CreateMockRead(*stream1_reply, 2),
2651 CreateMockRead(*stream2_syn, 3),
2652 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2653 CreateMockRead(*stream2_body, 5),
2654 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2657 HttpResponseInfo response;
2658 HttpResponseInfo response2;
2659 std::string expected_push_result("pushed");
2660 OrderedSocketData data(reads, arraysize(reads),
2661 writes, arraysize(writes));
2662 RunServerPushTest(&data,
2663 &response,
2664 &response2,
2665 expected_push_result);
2667 // Verify the SYN_REPLY.
2668 EXPECT_TRUE(response.headers.get() != NULL);
2669 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2671 // Verify the pushed stream.
2672 EXPECT_TRUE(response2.headers.get() != NULL);
2673 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2676 TEST_P(SpdyNetworkTransactionTest, ServerPushBeforeSynReply) {
2677 scoped_ptr<SpdyFrame> stream1_syn(
2678 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2679 scoped_ptr<SpdyFrame> stream1_body(
2680 spdy_util_.ConstructSpdyBodyFrame(1, true));
2681 MockWrite writes[] = {
2682 CreateMockWrite(*stream1_syn, 1),
2685 scoped_ptr<SpdyFrame>
2686 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2687 scoped_ptr<SpdyFrame>
2688 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2692 "http://www.google.com/foo.dat"));
2693 const char kPushedData[] = "pushed";
2694 scoped_ptr<SpdyFrame> stream2_body(
2695 spdy_util_.ConstructSpdyBodyFrame(
2696 2, kPushedData, strlen(kPushedData), true));
2697 MockRead reads[] = {
2698 CreateMockRead(*stream2_syn, 2),
2699 CreateMockRead(*stream1_reply, 3),
2700 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2701 CreateMockRead(*stream2_body, 5),
2702 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2705 HttpResponseInfo response;
2706 HttpResponseInfo response2;
2707 std::string expected_push_result("pushed");
2708 OrderedSocketData data(reads, arraysize(reads),
2709 writes, arraysize(writes));
2710 RunServerPushTest(&data,
2711 &response,
2712 &response2,
2713 expected_push_result);
2715 // Verify the SYN_REPLY.
2716 EXPECT_TRUE(response.headers.get() != NULL);
2717 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2719 // Verify the pushed stream.
2720 EXPECT_TRUE(response2.headers.get() != NULL);
2721 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2724 TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
2725 scoped_ptr<SpdyFrame> stream1_syn(
2726 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2727 MockWrite writes[] = { CreateMockWrite(*stream1_syn, 1), };
2729 scoped_ptr<SpdyFrame>
2730 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2731 scoped_ptr<SpdyFrame>
2732 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2736 "http://www.google.com/foo.dat"));
2737 const char kPushedData[] = "pushed";
2738 scoped_ptr<SpdyFrame> stream2_body(
2739 spdy_util_.ConstructSpdyBodyFrame(
2740 2, kPushedData, strlen(kPushedData), true));
2741 scoped_ptr<SpdyFrame>
2742 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2743 MockRead reads[] = {
2744 CreateMockRead(*stream1_reply, 2),
2745 CreateMockRead(*stream2_syn, 3),
2746 CreateMockRead(*stream2_body, 4),
2747 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
2748 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2751 HttpResponseInfo response;
2752 HttpResponseInfo response2;
2753 std::string expected_push_result("pushed");
2754 OrderedSocketData data(reads, arraysize(reads),
2755 writes, arraysize(writes));
2756 RunServerPushTest(&data,
2757 &response,
2758 &response2,
2759 expected_push_result);
2761 // Verify the SYN_REPLY.
2762 EXPECT_TRUE(response.headers.get() != NULL);
2763 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2765 // Verify the pushed stream.
2766 EXPECT_TRUE(response2.headers.get() != NULL);
2767 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2770 TEST_P(SpdyNetworkTransactionTest, ServerPushServerAborted) {
2771 scoped_ptr<SpdyFrame> stream1_syn(
2772 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2773 scoped_ptr<SpdyFrame> stream1_body(
2774 spdy_util_.ConstructSpdyBodyFrame(1, true));
2775 MockWrite writes[] = {
2776 CreateMockWrite(*stream1_syn, 1),
2779 scoped_ptr<SpdyFrame>
2780 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2781 scoped_ptr<SpdyFrame>
2782 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2786 "http://www.google.com/foo.dat"));
2787 scoped_ptr<SpdyFrame> stream2_rst(
2788 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
2789 MockRead reads[] = {
2790 CreateMockRead(*stream1_reply, 2),
2791 CreateMockRead(*stream2_syn, 3),
2792 CreateMockRead(*stream2_rst, 4),
2793 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
2794 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2797 OrderedSocketData data(reads, arraysize(reads),
2798 writes, arraysize(writes));
2799 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2800 BoundNetLog(), GetParam(), NULL);
2802 helper.RunPreTestSetup();
2803 helper.AddData(&data);
2805 HttpNetworkTransaction* trans = helper.trans();
2807 // Start the transaction with basic parameters.
2808 TestCompletionCallback callback;
2809 int rv = trans->Start(
2810 &CreateGetRequest(), callback.callback(), BoundNetLog());
2811 EXPECT_EQ(ERR_IO_PENDING, rv);
2812 rv = callback.WaitForResult();
2813 EXPECT_EQ(OK, rv);
2815 // Verify that we consumed all test data.
2816 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
2817 << data.read_count()
2818 << " Read index: "
2819 << data.read_index();
2820 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
2821 << data.write_count()
2822 << " Write index: "
2823 << data.write_index();
2825 // Verify the SYN_REPLY.
2826 HttpResponseInfo response = *trans->GetResponseInfo();
2827 EXPECT_TRUE(response.headers.get() != NULL);
2828 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2831 // Verify that we don't leak streams and that we properly send a reset
2832 // if the server pushes the same stream twice.
2833 TEST_P(SpdyNetworkTransactionTest, ServerPushDuplicate) {
2834 scoped_ptr<SpdyFrame> stream1_syn(
2835 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2836 scoped_ptr<SpdyFrame> stream1_body(
2837 spdy_util_.ConstructSpdyBodyFrame(1, true));
2838 scoped_ptr<SpdyFrame> stream3_rst(
2839 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR));
2840 MockWrite writes[] = {
2841 CreateMockWrite(*stream1_syn, 1),
2842 CreateMockWrite(*stream3_rst, 5),
2845 scoped_ptr<SpdyFrame>
2846 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2847 scoped_ptr<SpdyFrame>
2848 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2852 "http://www.google.com/foo.dat"));
2853 const char kPushedData[] = "pushed";
2854 scoped_ptr<SpdyFrame> stream2_body(
2855 spdy_util_.ConstructSpdyBodyFrame(
2856 2, kPushedData, strlen(kPushedData), true));
2857 scoped_ptr<SpdyFrame>
2858 stream3_syn(spdy_util_.ConstructSpdyPush(NULL,
2862 "http://www.google.com/foo.dat"));
2863 MockRead reads[] = {
2864 CreateMockRead(*stream1_reply, 2),
2865 CreateMockRead(*stream2_syn, 3),
2866 CreateMockRead(*stream3_syn, 4),
2867 CreateMockRead(*stream1_body, 6, SYNCHRONOUS),
2868 CreateMockRead(*stream2_body, 7),
2869 MockRead(ASYNC, ERR_IO_PENDING, 8), // Force a pause
2872 HttpResponseInfo response;
2873 HttpResponseInfo response2;
2874 std::string expected_push_result("pushed");
2875 OrderedSocketData data(reads, arraysize(reads),
2876 writes, arraysize(writes));
2877 RunServerPushTest(&data,
2878 &response,
2879 &response2,
2880 expected_push_result);
2882 // Verify the SYN_REPLY.
2883 EXPECT_TRUE(response.headers.get() != NULL);
2884 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2886 // Verify the pushed stream.
2887 EXPECT_TRUE(response2.headers.get() != NULL);
2888 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2891 TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
2892 scoped_ptr<SpdyFrame> stream1_syn(
2893 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2894 scoped_ptr<SpdyFrame> stream1_body(
2895 spdy_util_.ConstructSpdyBodyFrame(1, true));
2896 MockWrite writes[] = {
2897 CreateMockWrite(*stream1_syn, 1),
2900 scoped_ptr<SpdyFrame>
2901 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2902 scoped_ptr<SpdyFrame>
2903 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2907 "http://www.google.com/foo.dat"));
2908 static const char kPushedData[] = "pushed my darling hello my baby";
2909 scoped_ptr<SpdyFrame> stream2_body_base(
2910 spdy_util_.ConstructSpdyBodyFrame(
2911 2, kPushedData, strlen(kPushedData), true));
2912 const size_t kChunkSize = strlen(kPushedData) / 4;
2913 scoped_ptr<SpdyFrame> stream2_body1(
2914 new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
2915 scoped_ptr<SpdyFrame> stream2_body2(
2916 new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
2917 scoped_ptr<SpdyFrame> stream2_body3(
2918 new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
2919 kChunkSize, false));
2920 scoped_ptr<SpdyFrame> stream2_body4(
2921 new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
2922 stream2_body_base->size() - 3 * kChunkSize, false));
2923 MockRead reads[] = {
2924 CreateMockRead(*stream1_reply, 2),
2925 CreateMockRead(*stream2_syn, 3),
2926 CreateMockRead(*stream2_body1, 4),
2927 CreateMockRead(*stream2_body2, 5),
2928 CreateMockRead(*stream2_body3, 6),
2929 CreateMockRead(*stream2_body4, 7),
2930 CreateMockRead(*stream1_body, 8, SYNCHRONOUS),
2931 MockRead(ASYNC, ERR_IO_PENDING, 9), // Force a pause
2934 HttpResponseInfo response;
2935 HttpResponseInfo response2;
2936 std::string expected_push_result("pushed my darling hello my baby");
2937 OrderedSocketData data(reads, arraysize(reads),
2938 writes, arraysize(writes));
2939 RunServerPushTest(&data, &response, &response2, kPushedData);
2941 // Verify the SYN_REPLY.
2942 EXPECT_TRUE(response.headers.get() != NULL);
2943 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2945 // Verify the pushed stream.
2946 EXPECT_TRUE(response2.headers.get() != NULL);
2947 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2950 TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
2951 scoped_ptr<SpdyFrame> stream1_syn(
2952 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2953 scoped_ptr<SpdyFrame> stream1_body(
2954 spdy_util_.ConstructSpdyBodyFrame(1, true));
2955 MockWrite writes[] = {
2956 CreateMockWrite(*stream1_syn, 1),
2959 scoped_ptr<SpdyFrame>
2960 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2961 scoped_ptr<SpdyFrame>
2962 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2966 "http://www.google.com/foo.dat"));
2967 static const char kPushedData[] = "pushed my darling hello my baby";
2968 scoped_ptr<SpdyFrame> stream2_body_base(
2969 spdy_util_.ConstructSpdyBodyFrame(
2970 2, kPushedData, strlen(kPushedData), true));
2971 const size_t kChunkSize = strlen(kPushedData) / 4;
2972 scoped_ptr<SpdyFrame> stream2_body1(
2973 new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
2974 scoped_ptr<SpdyFrame> stream2_body2(
2975 new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
2976 scoped_ptr<SpdyFrame> stream2_body3(
2977 new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
2978 kChunkSize, false));
2979 scoped_ptr<SpdyFrame> stream2_body4(
2980 new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
2981 stream2_body_base->size() - 3 * kChunkSize, false));
2982 MockRead reads[] = {
2983 CreateMockRead(*stream1_reply, 2),
2984 CreateMockRead(*stream2_syn, 3),
2985 CreateMockRead(*stream2_body1, 4),
2986 CreateMockRead(*stream2_body2, 5),
2987 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2988 CreateMockRead(*stream2_body3, 7),
2989 CreateMockRead(*stream2_body4, 8),
2990 CreateMockRead(*stream1_body.get(), 9, SYNCHRONOUS),
2991 MockRead(ASYNC, ERR_IO_PENDING, 10) // Force a pause.
2994 HttpResponseInfo response;
2995 HttpResponseInfo response2;
2996 OrderedSocketData data(reads, arraysize(reads),
2997 writes, arraysize(writes));
2998 RunServerPushTest(&data, &response, &response2, kPushedData);
3000 // Verify the SYN_REPLY.
3001 EXPECT_TRUE(response.headers.get() != NULL);
3002 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3004 // Verify the pushed stream.
3005 EXPECT_TRUE(response2.headers.get() != NULL);
3006 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
3009 TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
3010 if (spdy_util_.spdy_version() == SPDY4) {
3011 // PUSH_PROMISE with stream id 0 is connection-level error.
3012 // TODO(baranovich): Test session going away.
3013 return;
3016 scoped_ptr<SpdyFrame> stream1_syn(
3017 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3018 scoped_ptr<SpdyFrame> stream1_body(
3019 spdy_util_.ConstructSpdyBodyFrame(1, true));
3020 scoped_ptr<SpdyFrame> stream2_rst(
3021 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
3022 MockWrite writes[] = {
3023 CreateMockWrite(*stream1_syn, 1),
3024 CreateMockWrite(*stream2_rst, 4),
3027 scoped_ptr<SpdyFrame>
3028 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3029 scoped_ptr<SpdyFrame>
3030 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
3034 "http://www.google.com/foo.dat"));
3035 MockRead reads[] = {
3036 CreateMockRead(*stream1_reply, 2),
3037 CreateMockRead(*stream2_syn, 3),
3038 CreateMockRead(*stream1_body, 4),
3039 MockRead(ASYNC, ERR_IO_PENDING, 5) // Force a pause
3042 OrderedSocketData data(reads, arraysize(reads),
3043 writes, arraysize(writes));
3044 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3045 BoundNetLog(), GetParam(), NULL);
3047 helper.RunPreTestSetup();
3048 helper.AddData(&data);
3050 HttpNetworkTransaction* trans = helper.trans();
3052 // Start the transaction with basic parameters.
3053 TestCompletionCallback callback;
3054 int rv = trans->Start(
3055 &CreateGetRequest(), callback.callback(), BoundNetLog());
3056 EXPECT_EQ(ERR_IO_PENDING, rv);
3057 rv = callback.WaitForResult();
3058 EXPECT_EQ(OK, rv);
3060 // Verify that we consumed all test data.
3061 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3062 << data.read_count()
3063 << " Read index: "
3064 << data.read_index();
3065 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3066 << data.write_count()
3067 << " Write index: "
3068 << data.write_index();
3070 // Verify the SYN_REPLY.
3071 HttpResponseInfo response = *trans->GetResponseInfo();
3072 EXPECT_TRUE(response.headers.get() != NULL);
3073 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3076 TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
3077 scoped_ptr<SpdyFrame> stream1_syn(
3078 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3079 scoped_ptr<SpdyFrame> stream1_body(
3080 spdy_util_.ConstructSpdyBodyFrame(1, true));
3081 scoped_ptr<SpdyFrame> stream2_rst(
3082 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM));
3083 MockWrite writes[] = {
3084 CreateMockWrite(*stream1_syn, 1),
3085 CreateMockWrite(*stream2_rst, 4),
3088 scoped_ptr<SpdyFrame>
3089 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3090 scoped_ptr<SpdyFrame>
3091 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
3095 "http://www.google.com/foo.dat"));
3096 MockRead reads[] = {
3097 CreateMockRead(*stream1_reply, 2),
3098 CreateMockRead(*stream2_syn, 3),
3099 CreateMockRead(*stream1_body, 4),
3100 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
3103 OrderedSocketData data(reads, arraysize(reads),
3104 writes, arraysize(writes));
3105 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3106 BoundNetLog(), GetParam(), NULL);
3108 helper.RunPreTestSetup();
3109 helper.AddData(&data);
3111 HttpNetworkTransaction* trans = helper.trans();
3113 // Start the transaction with basic parameters.
3114 TestCompletionCallback callback;
3115 int rv = trans->Start(
3116 &CreateGetRequest(), callback.callback(), BoundNetLog());
3117 EXPECT_EQ(ERR_IO_PENDING, rv);
3118 rv = callback.WaitForResult();
3119 EXPECT_EQ(OK, rv);
3121 // Verify that we consumed all test data.
3122 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3123 << data.read_count()
3124 << " Read index: "
3125 << data.read_index();
3126 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3127 << data.write_count()
3128 << " Write index: "
3129 << data.write_index();
3131 // Verify the SYN_REPLY.
3132 HttpResponseInfo response = *trans->GetResponseInfo();
3133 EXPECT_TRUE(response.headers.get() != NULL);
3134 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3137 TEST_P(SpdyNetworkTransactionTest, ServerPushNoURL) {
3138 scoped_ptr<SpdyFrame> stream1_syn(
3139 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3140 scoped_ptr<SpdyFrame> stream1_body(
3141 spdy_util_.ConstructSpdyBodyFrame(1, true));
3142 scoped_ptr<SpdyFrame> stream2_rst(
3143 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
3144 MockWrite writes[] = {
3145 CreateMockWrite(*stream1_syn, 1),
3146 CreateMockWrite(*stream2_rst, 4),
3149 scoped_ptr<SpdyFrame>
3150 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3151 scoped_ptr<SpdyHeaderBlock> incomplete_headers(new SpdyHeaderBlock());
3152 (*incomplete_headers)["hello"] = "bye";
3153 (*incomplete_headers)[spdy_util_.GetStatusKey()] = "200 OK";
3154 (*incomplete_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
3155 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
3156 incomplete_headers.Pass(), 2, 1));
3157 MockRead reads[] = {
3158 CreateMockRead(*stream1_reply, 2),
3159 CreateMockRead(*stream2_syn, 3),
3160 CreateMockRead(*stream1_body, 4),
3161 MockRead(ASYNC, ERR_IO_PENDING, 5) // Force a pause
3164 OrderedSocketData data(reads, arraysize(reads),
3165 writes, arraysize(writes));
3166 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3167 BoundNetLog(), GetParam(), NULL);
3169 helper.RunPreTestSetup();
3170 helper.AddData(&data);
3172 HttpNetworkTransaction* trans = helper.trans();
3174 // Start the transaction with basic parameters.
3175 TestCompletionCallback callback;
3176 int rv = trans->Start(
3177 &CreateGetRequest(), callback.callback(), BoundNetLog());
3178 EXPECT_EQ(ERR_IO_PENDING, rv);
3179 rv = callback.WaitForResult();
3180 EXPECT_EQ(OK, rv);
3181 // Verify that we consumed all test data.
3182 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3183 << data.read_count()
3184 << " Read index: "
3185 << data.read_index();
3186 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3187 << data.write_count()
3188 << " Write index: "
3189 << data.write_index();
3191 // Verify the SYN_REPLY.
3192 HttpResponseInfo response = *trans->GetResponseInfo();
3193 EXPECT_TRUE(response.headers.get() != NULL);
3194 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3197 // Verify that various SynReply headers parse correctly through the
3198 // HTTP layer.
3199 TEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) {
3200 struct SynReplyHeadersTests {
3201 int num_headers;
3202 const char* extra_headers[5];
3203 SpdyHeaderBlock expected_headers;
3204 } test_cases[] = {
3205 // This uses a multi-valued cookie header.
3206 { 2,
3207 { "cookie", "val1",
3208 "cookie", "val2", // will get appended separated by NULL
3209 NULL
3212 // This is the minimalist set of headers.
3213 { 0,
3214 { NULL },
3216 // Headers with a comma separated list.
3217 { 1,
3218 { "cookie", "val1,val2",
3219 NULL
3224 test_cases[0].expected_headers["cookie"] = "val1";
3225 test_cases[0].expected_headers["cookie"] += '\0';
3226 test_cases[0].expected_headers["cookie"] += "val2";
3227 test_cases[0].expected_headers["hello"] = "bye";
3228 test_cases[0].expected_headers["status"] = "200";
3230 test_cases[1].expected_headers["hello"] = "bye";
3231 test_cases[1].expected_headers["status"] = "200";
3233 test_cases[2].expected_headers["cookie"] = "val1,val2";
3234 test_cases[2].expected_headers["hello"] = "bye";
3235 test_cases[2].expected_headers["status"] = "200";
3237 if (spdy_util_.spdy_version() < SPDY4) {
3238 // SPDY4/HTTP2 eliminates use of the :version header.
3239 test_cases[0].expected_headers["version"] = "HTTP/1.1";
3240 test_cases[1].expected_headers["version"] = "HTTP/1.1";
3241 test_cases[2].expected_headers["version"] = "HTTP/1.1";
3244 for (size_t i = 0; i < arraysize(test_cases); ++i) {
3245 scoped_ptr<SpdyFrame> req(
3246 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3247 MockWrite writes[] = { CreateMockWrite(*req) };
3249 scoped_ptr<SpdyFrame> resp(
3250 spdy_util_.ConstructSpdyGetSynReply(test_cases[i].extra_headers,
3251 test_cases[i].num_headers,
3252 1));
3253 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3254 MockRead reads[] = {
3255 CreateMockRead(*resp),
3256 CreateMockRead(*body),
3257 MockRead(ASYNC, 0, 0) // EOF
3260 DelayedSocketData data(1, reads, arraysize(reads),
3261 writes, arraysize(writes));
3262 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3263 BoundNetLog(), GetParam(), NULL);
3264 helper.RunToCompletion(&data);
3265 TransactionHelperResult out = helper.output();
3267 EXPECT_EQ(OK, out.rv);
3268 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3269 EXPECT_EQ("hello!", out.response_data);
3271 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3272 EXPECT_TRUE(headers.get() != NULL);
3273 void* iter = NULL;
3274 std::string name, value;
3275 SpdyHeaderBlock header_block;
3276 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3277 if (header_block[name].empty()) {
3278 header_block[name] = value;
3279 } else {
3280 header_block[name] += '\0';
3281 header_block[name] += value;
3284 EXPECT_EQ(test_cases[i].expected_headers, header_block);
3288 // Verify that various SynReply headers parse vary fields correctly
3289 // through the HTTP layer, and the response matches the request.
3290 TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) {
3291 // Modify the following data to change/add test cases:
3292 struct SynReplyTests {
3293 bool vary_matches;
3294 int num_headers[2];
3295 const char* extra_headers[2][16];
3296 } test_cases[] = {
3297 // Test the case of a multi-valued cookie. When the value is delimited
3298 // with NUL characters, it needs to be unfolded into multiple headers.
3300 true,
3301 { 1, 4 },
3302 { { "cookie", "val1,val2",
3303 NULL
3305 { "vary", "cookie",
3306 spdy_util_.GetStatusKey(), "200",
3307 spdy_util_.GetPathKey(), "/index.php",
3308 spdy_util_.GetVersionKey(), "HTTP/1.1",
3309 NULL
3312 }, { // Multiple vary fields.
3313 true,
3314 { 2, 5 },
3315 { { "friend", "barney",
3316 "enemy", "snaggletooth",
3317 NULL
3319 { "vary", "friend",
3320 "vary", "enemy",
3321 spdy_util_.GetStatusKey(), "200",
3322 spdy_util_.GetPathKey(), "/index.php",
3323 spdy_util_.GetVersionKey(), "HTTP/1.1",
3324 NULL
3327 }, { // Test a '*' vary field.
3328 false,
3329 { 1, 4 },
3330 { { "cookie", "val1,val2",
3331 NULL
3333 { "vary", "*",
3334 spdy_util_.GetStatusKey(), "200",
3335 spdy_util_.GetPathKey(), "/index.php",
3336 spdy_util_.GetVersionKey(), "HTTP/1.1",
3337 NULL
3340 }, { // Multiple comma-separated vary fields.
3341 true,
3342 { 2, 4 },
3343 { { "friend", "barney",
3344 "enemy", "snaggletooth",
3345 NULL
3347 { "vary", "friend,enemy",
3348 spdy_util_.GetStatusKey(), "200",
3349 spdy_util_.GetPathKey(), "/index.php",
3350 spdy_util_.GetVersionKey(), "HTTP/1.1",
3351 NULL
3357 for (size_t i = 0; i < arraysize(test_cases); ++i) {
3358 // Construct the request.
3359 scoped_ptr<SpdyFrame> frame_req(
3360 spdy_util_.ConstructSpdyGet(test_cases[i].extra_headers[0],
3361 test_cases[i].num_headers[0],
3362 false, 1, LOWEST, true));
3364 MockWrite writes[] = {
3365 CreateMockWrite(*frame_req),
3368 // Construct the reply.
3369 SpdyHeaderBlock reply_headers;
3370 AppendToHeaderBlock(test_cases[i].extra_headers[1],
3371 test_cases[i].num_headers[1],
3372 &reply_headers);
3373 scoped_ptr<SpdyFrame> frame_reply(
3374 spdy_util_.ConstructSpdyReply(1, reply_headers));
3376 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3377 MockRead reads[] = {
3378 CreateMockRead(*frame_reply),
3379 CreateMockRead(*body),
3380 MockRead(ASYNC, 0, 0) // EOF
3383 // Attach the headers to the request.
3384 int header_count = test_cases[i].num_headers[0];
3386 HttpRequestInfo request = CreateGetRequest();
3387 for (int ct = 0; ct < header_count; ct++) {
3388 const char* header_key = test_cases[i].extra_headers[0][ct * 2];
3389 const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1];
3390 request.extra_headers.SetHeader(header_key, header_value);
3393 DelayedSocketData data(1, reads, arraysize(reads),
3394 writes, arraysize(writes));
3395 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
3396 BoundNetLog(), GetParam(), NULL);
3397 helper.RunToCompletion(&data);
3398 TransactionHelperResult out = helper.output();
3400 EXPECT_EQ(OK, out.rv) << i;
3401 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line) << i;
3402 EXPECT_EQ("hello!", out.response_data) << i;
3404 // Test the response information.
3405 EXPECT_TRUE(out.response_info.response_time >
3406 out.response_info.request_time) << i;
3407 base::TimeDelta test_delay = out.response_info.response_time -
3408 out.response_info.request_time;
3409 base::TimeDelta min_expected_delay;
3410 min_expected_delay.FromMilliseconds(10);
3411 EXPECT_GT(test_delay.InMillisecondsF(),
3412 min_expected_delay.InMillisecondsF()) << i;
3413 EXPECT_EQ(out.response_info.vary_data.is_valid(),
3414 test_cases[i].vary_matches) << i;
3416 // Check the headers.
3417 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3418 ASSERT_TRUE(headers.get() != NULL) << i;
3419 void* iter = NULL;
3420 std::string name, value, lines;
3421 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3422 lines.append(name);
3423 lines.append(": ");
3424 lines.append(value);
3425 lines.append("\n");
3428 // Construct the expected header reply string.
3429 std::string expected_reply =
3430 spdy_util_.ConstructSpdyReplyString(reply_headers);
3431 EXPECT_EQ(expected_reply, lines) << i;
3435 // Verify that we don't crash on invalid SynReply responses.
3436 TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) {
3437 struct InvalidSynReplyTests {
3438 int num_headers;
3439 const char* headers[10];
3440 } test_cases[] = {
3441 // SYN_REPLY missing status header
3442 { 4,
3443 { "cookie", "val1",
3444 "cookie", "val2",
3445 spdy_util_.GetPathKey(), "/index.php",
3446 spdy_util_.GetVersionKey(), "HTTP/1.1",
3447 NULL
3450 // SYN_REPLY missing version header
3451 { 2,
3452 { "status", "200",
3453 spdy_util_.GetPathKey(), "/index.php",
3454 NULL
3457 // SYN_REPLY with no headers
3458 { 0, { NULL }, },
3461 for (size_t i = 0; i < arraysize(test_cases); ++i) {
3462 scoped_ptr<SpdyFrame> req(
3463 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3464 scoped_ptr<SpdyFrame> rst(
3465 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
3466 MockWrite writes[] = {
3467 CreateMockWrite(*req),
3468 CreateMockWrite(*rst),
3471 // Construct the reply.
3472 SpdyHeaderBlock reply_headers;
3473 AppendToHeaderBlock(
3474 test_cases[i].headers, test_cases[i].num_headers, &reply_headers);
3475 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyReply(1, reply_headers));
3476 MockRead reads[] = {
3477 CreateMockRead(*resp),
3478 MockRead(ASYNC, 0, 0) // EOF
3481 DelayedSocketData data(1, reads, arraysize(reads),
3482 writes, arraysize(writes));
3483 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3484 BoundNetLog(), GetParam(), NULL);
3485 helper.RunToCompletion(&data);
3486 TransactionHelperResult out = helper.output();
3487 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3491 // Verify that we don't crash on some corrupt frames.
3492 // TODO(jgraettinger): SPDY4 and up treats a header decompression failure as a
3493 // connection error. I'd like to backport this behavior to SPDY3 as well.
3494 TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
3495 if (spdy_util_.spdy_version() >= SPDY4) {
3496 return;
3498 // This is the length field that's too short.
3499 scoped_ptr<SpdyFrame> syn_reply_wrong_length(
3500 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3501 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3502 size_t right_size =
3503 (spdy_util_.spdy_version() < SPDY4) ?
3504 syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize() :
3505 syn_reply_wrong_length->size();
3506 size_t wrong_size = right_size - 4;
3507 test::SetFrameLength(syn_reply_wrong_length.get(),
3508 wrong_size,
3509 spdy_util_.spdy_version());
3511 struct SynReplyTests {
3512 const SpdyFrame* syn_reply;
3513 } test_cases[] = {
3514 { syn_reply_wrong_length.get(), },
3517 for (size_t i = 0; i < arraysize(test_cases); ++i) {
3518 scoped_ptr<SpdyFrame> req(
3519 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3520 scoped_ptr<SpdyFrame> rst(
3521 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
3522 MockWrite writes[] = {
3523 CreateMockWrite(*req),
3524 CreateMockWrite(*rst),
3527 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3528 MockRead reads[] = {
3529 MockRead(ASYNC, test_cases[i].syn_reply->data(), wrong_size),
3530 CreateMockRead(*body),
3531 MockRead(ASYNC, 0, 0) // EOF
3534 DelayedSocketData data(1, reads, arraysize(reads),
3535 writes, arraysize(writes));
3536 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3537 BoundNetLog(), GetParam(), NULL);
3538 helper.RunToCompletion(&data);
3539 TransactionHelperResult out = helper.output();
3540 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3544 // SPDY4 treats a header decompression failure as a connection-level error.
3545 TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionErrorSpdy4) {
3546 if (spdy_util_.spdy_version() < SPDY4) {
3547 return;
3549 // This is the length field that's too short.
3550 scoped_ptr<SpdyFrame> syn_reply_wrong_length(
3551 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3552 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3553 size_t right_size =
3554 syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize();
3555 size_t wrong_size = right_size - 4;
3556 test::SetFrameLength(syn_reply_wrong_length.get(),
3557 wrong_size,
3558 spdy_util_.spdy_version());
3560 scoped_ptr<SpdyFrame> req(
3561 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3562 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3563 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3564 MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*goaway)};
3566 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3567 MockRead reads[] = {
3568 MockRead(ASYNC, syn_reply_wrong_length->data(),
3569 syn_reply_wrong_length->size() - 4),
3572 DelayedSocketData data(1, reads, arraysize(reads),
3573 writes, arraysize(writes));
3574 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3575 BoundNetLog(), GetParam(), NULL);
3576 helper.RunToCompletion(&data);
3577 TransactionHelperResult out = helper.output();
3578 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
3581 TEST_P(SpdyNetworkTransactionTest, GoAwayOnDecompressionFailure) {
3582 if (GetParam().protocol < kProtoSPDY4MinimumVersion) {
3583 // Decompression failures are a stream error in SPDY3 and above.
3584 return;
3586 scoped_ptr<SpdyFrame> req(
3587 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3588 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3589 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3590 MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*goaway)};
3592 // Read HEADERS with corrupted payload.
3593 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3594 memset(resp->data() + 12, 0xff, resp->size() - 12);
3595 MockRead reads[] = {CreateMockRead(*resp)};
3597 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
3598 NormalSpdyTransactionHelper helper(
3599 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
3600 helper.RunToCompletion(&data);
3601 TransactionHelperResult out = helper.output();
3602 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
3605 TEST_P(SpdyNetworkTransactionTest, GoAwayOnFrameSizeError) {
3606 scoped_ptr<SpdyFrame> req(
3607 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3608 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3609 0, GOAWAY_PROTOCOL_ERROR, "Framer error: 1 (INVALID_CONTROL_FRAME)."));
3610 MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*goaway)};
3612 // Read WINDOW_UPDATE with incorrectly-sized payload.
3613 // TODO(jgraettinger): SpdyFramer signals this as an INVALID_CONTROL_FRAME,
3614 // which is mapped to a protocol error, and not a frame size error.
3615 scoped_ptr<SpdyFrame> bad_window_update(
3616 spdy_util_.ConstructSpdyWindowUpdate(1, 1));
3617 test::SetFrameLength(bad_window_update.get(),
3618 bad_window_update->size() - 1,
3619 spdy_util_.spdy_version());
3620 MockRead reads[] = {CreateMockRead(*bad_window_update)};
3622 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
3623 NormalSpdyTransactionHelper helper(
3624 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
3625 helper.RunToCompletion(&data);
3626 TransactionHelperResult out = helper.output();
3627 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3630 // Test that we shutdown correctly on write errors.
3631 TEST_P(SpdyNetworkTransactionTest, WriteError) {
3632 scoped_ptr<SpdyFrame> req(
3633 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3634 MockWrite writes[] = {
3635 // We'll write 10 bytes successfully
3636 MockWrite(ASYNC, req->data(), 10, 0),
3637 // Followed by ERROR!
3638 MockWrite(ASYNC, ERR_FAILED, 1),
3639 // Session drains and attempts to write a GOAWAY: Another ERROR!
3640 MockWrite(ASYNC, ERR_FAILED, 2),
3643 MockRead reads[] = {
3644 MockRead(ASYNC, 0, 3) // EOF
3647 DeterministicSocketData data(reads, arraysize(reads),
3648 writes, arraysize(writes));
3650 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3651 BoundNetLog(), GetParam(), NULL);
3652 helper.SetDeterministic();
3653 helper.RunPreTestSetup();
3654 helper.AddDeterministicData(&data);
3655 EXPECT_TRUE(helper.StartDefaultTest());
3656 data.RunFor(2);
3657 helper.FinishDefaultTest();
3658 EXPECT_TRUE(data.at_write_eof());
3659 EXPECT_TRUE(!data.at_read_eof());
3660 TransactionHelperResult out = helper.output();
3661 EXPECT_EQ(ERR_FAILED, out.rv);
3664 // Test that partial writes work.
3665 TEST_P(SpdyNetworkTransactionTest, PartialWrite) {
3666 // Chop the SYN_STREAM frame into 5 chunks.
3667 scoped_ptr<SpdyFrame> req(
3668 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3669 const int kChunks = 5;
3670 scoped_ptr<MockWrite[]> writes(ChopWriteFrame(*req.get(), kChunks));
3672 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3673 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3674 MockRead reads[] = {
3675 CreateMockRead(*resp),
3676 CreateMockRead(*body),
3677 MockRead(ASYNC, 0, 0) // EOF
3680 DelayedSocketData data(kChunks, reads, arraysize(reads),
3681 writes.get(), kChunks);
3682 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3683 BoundNetLog(), GetParam(), NULL);
3684 helper.RunToCompletion(&data);
3685 TransactionHelperResult out = helper.output();
3686 EXPECT_EQ(OK, out.rv);
3687 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3688 EXPECT_EQ("hello!", out.response_data);
3691 // In this test, we enable compression, but get a uncompressed SynReply from
3692 // the server. Verify that teardown is all clean.
3693 TEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) {
3694 if (spdy_util_.spdy_version() >= SPDY4) {
3695 // HPACK doesn't use deflate compression.
3696 return;
3698 scoped_ptr<SpdyFrame> compressed(
3699 spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, LOWEST, true));
3700 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3701 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3702 MockWrite writes[] = {CreateMockWrite(*compressed), CreateMockWrite(*goaway)};
3704 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3705 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3706 MockRead reads[] = {
3707 CreateMockRead(*resp),
3710 DelayedSocketData data(1, reads, arraysize(reads),
3711 writes, arraysize(writes));
3712 SpdySessionDependencies* session_deps =
3713 CreateSpdySessionDependencies(GetParam());
3714 session_deps->enable_compression = true;
3715 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3716 BoundNetLog(), GetParam(), session_deps);
3717 helper.RunToCompletion(&data);
3718 TransactionHelperResult out = helper.output();
3719 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
3720 data.Reset();
3723 // Test that the NetLog contains good data for a simple GET request.
3724 TEST_P(SpdyNetworkTransactionTest, NetLog) {
3725 static const char* const kExtraHeaders[] = {
3726 "user-agent", "Chrome",
3728 scoped_ptr<SpdyFrame> req(
3729 spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, false, 1, LOWEST, true));
3730 MockWrite writes[] = { CreateMockWrite(*req) };
3732 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3733 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3734 MockRead reads[] = {
3735 CreateMockRead(*resp),
3736 CreateMockRead(*body),
3737 MockRead(ASYNC, 0, 0) // EOF
3740 CapturingBoundNetLog log;
3742 DelayedSocketData data(1, reads, arraysize(reads),
3743 writes, arraysize(writes));
3744 NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(),
3745 DEFAULT_PRIORITY,
3746 log.bound(), GetParam(), NULL);
3747 helper.RunToCompletion(&data);
3748 TransactionHelperResult out = helper.output();
3749 EXPECT_EQ(OK, out.rv);
3750 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3751 EXPECT_EQ("hello!", out.response_data);
3753 // Check that the NetLog was filled reasonably.
3754 // This test is intentionally non-specific about the exact ordering of the
3755 // log; instead we just check to make sure that certain events exist, and that
3756 // they are in the right order.
3757 net::CapturingNetLog::CapturedEntryList entries;
3758 log.GetEntries(&entries);
3760 EXPECT_LT(0u, entries.size());
3761 int pos = 0;
3762 pos = net::ExpectLogContainsSomewhere(entries, 0,
3763 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3764 net::NetLog::PHASE_BEGIN);
3765 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3766 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3767 net::NetLog::PHASE_END);
3768 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3769 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3770 net::NetLog::PHASE_BEGIN);
3771 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3772 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3773 net::NetLog::PHASE_END);
3774 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3775 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3776 net::NetLog::PHASE_BEGIN);
3777 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3778 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3779 net::NetLog::PHASE_END);
3781 // Check that we logged all the headers correctly
3782 pos = net::ExpectLogContainsSomewhere(
3783 entries, 0,
3784 net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM,
3785 net::NetLog::PHASE_NONE);
3787 base::ListValue* header_list;
3788 ASSERT_TRUE(entries[pos].params.get());
3789 ASSERT_TRUE(entries[pos].params->GetList("headers", &header_list));
3791 std::vector<std::string> expected;
3792 expected.push_back(std::string(spdy_util_.GetHostKey()) + ": www.google.com");
3793 expected.push_back(std::string(spdy_util_.GetPathKey()) + ": /");
3794 expected.push_back(std::string(spdy_util_.GetSchemeKey()) + ": http");
3795 expected.push_back(std::string(spdy_util_.GetMethodKey()) + ": GET");
3796 expected.push_back("user-agent: Chrome");
3797 if (spdy_util_.spdy_version() < SPDY4) {
3798 // SPDY4/HTTP2 eliminates use of the :version header.
3799 expected.push_back(std::string(spdy_util_.GetVersionKey()) + ": HTTP/1.1");
3801 EXPECT_EQ(expected.size(), header_list->GetSize());
3802 for (std::vector<std::string>::const_iterator it = expected.begin();
3803 it != expected.end();
3804 ++it) {
3805 base::StringValue header(*it);
3806 EXPECT_NE(header_list->end(), header_list->Find(header)) <<
3807 "Header not found: " << *it;
3811 // Since we buffer the IO from the stream to the renderer, this test verifies
3812 // that when we read out the maximum amount of data (e.g. we received 50 bytes
3813 // on the network, but issued a Read for only 5 of those bytes) that the data
3814 // flow still works correctly.
3815 TEST_P(SpdyNetworkTransactionTest, BufferFull) {
3816 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3818 scoped_ptr<SpdyFrame> req(
3819 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3820 MockWrite writes[] = { CreateMockWrite(*req) };
3822 // 2 data frames in a single read.
3823 scoped_ptr<SpdyFrame> data_frame_1(
3824 framer.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE));
3825 scoped_ptr<SpdyFrame> data_frame_2(
3826 framer.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE));
3827 const SpdyFrame* data_frames[2] = {
3828 data_frame_1.get(),
3829 data_frame_2.get(),
3831 char combined_data_frames[100];
3832 int combined_data_frames_len =
3833 CombineFrames(data_frames, arraysize(data_frames),
3834 combined_data_frames, arraysize(combined_data_frames));
3835 scoped_ptr<SpdyFrame> last_frame(
3836 framer.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN));
3838 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3839 MockRead reads[] = {
3840 CreateMockRead(*resp),
3841 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3842 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
3843 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3844 CreateMockRead(*last_frame),
3845 MockRead(ASYNC, 0, 0) // EOF
3848 DelayedSocketData data(1, reads, arraysize(reads),
3849 writes, arraysize(writes));
3851 TestCompletionCallback callback;
3853 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3854 BoundNetLog(), GetParam(), NULL);
3855 helper.RunPreTestSetup();
3856 helper.AddData(&data);
3857 HttpNetworkTransaction* trans = helper.trans();
3858 int rv = trans->Start(
3859 &CreateGetRequest(), callback.callback(), BoundNetLog());
3860 EXPECT_EQ(ERR_IO_PENDING, rv);
3862 TransactionHelperResult out = helper.output();
3863 out.rv = callback.WaitForResult();
3864 EXPECT_EQ(out.rv, OK);
3866 const HttpResponseInfo* response = trans->GetResponseInfo();
3867 EXPECT_TRUE(response->headers.get() != NULL);
3868 EXPECT_TRUE(response->was_fetched_via_spdy);
3869 out.status_line = response->headers->GetStatusLine();
3870 out.response_info = *response; // Make a copy so we can verify.
3872 // Read Data
3873 TestCompletionCallback read_callback;
3875 std::string content;
3876 do {
3877 // Read small chunks at a time.
3878 const int kSmallReadSize = 3;
3879 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3880 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
3881 if (rv == net::ERR_IO_PENDING) {
3882 data.CompleteRead();
3883 rv = read_callback.WaitForResult();
3885 if (rv > 0) {
3886 content.append(buf->data(), rv);
3887 } else if (rv < 0) {
3888 NOTREACHED();
3890 } while (rv > 0);
3892 out.response_data.swap(content);
3894 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3895 // MockClientSocketFactory) are still alive.
3896 base::RunLoop().RunUntilIdle();
3898 // Verify that we consumed all test data.
3899 helper.VerifyDataConsumed();
3901 EXPECT_EQ(OK, out.rv);
3902 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3903 EXPECT_EQ("goodbye world", out.response_data);
3906 // Verify that basic buffering works; when multiple data frames arrive
3907 // at the same time, ensure that we don't notify a read completion for
3908 // each data frame individually.
3909 TEST_P(SpdyNetworkTransactionTest, Buffering) {
3910 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3912 scoped_ptr<SpdyFrame> req(
3913 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3914 MockWrite writes[] = { CreateMockWrite(*req) };
3916 // 4 data frames in a single read.
3917 scoped_ptr<SpdyFrame> data_frame(
3918 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
3919 scoped_ptr<SpdyFrame> data_frame_fin(
3920 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
3921 const SpdyFrame* data_frames[4] = {
3922 data_frame.get(),
3923 data_frame.get(),
3924 data_frame.get(),
3925 data_frame_fin.get()
3927 char combined_data_frames[100];
3928 int combined_data_frames_len =
3929 CombineFrames(data_frames, arraysize(data_frames),
3930 combined_data_frames, arraysize(combined_data_frames));
3932 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3933 MockRead reads[] = {
3934 CreateMockRead(*resp),
3935 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3936 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
3937 MockRead(ASYNC, 0, 0) // EOF
3940 DelayedSocketData data(1, reads, arraysize(reads),
3941 writes, arraysize(writes));
3943 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3944 BoundNetLog(), GetParam(), NULL);
3945 helper.RunPreTestSetup();
3946 helper.AddData(&data);
3947 HttpNetworkTransaction* trans = helper.trans();
3949 TestCompletionCallback callback;
3950 int rv = trans->Start(
3951 &CreateGetRequest(), callback.callback(), BoundNetLog());
3952 EXPECT_EQ(ERR_IO_PENDING, rv);
3954 TransactionHelperResult out = helper.output();
3955 out.rv = callback.WaitForResult();
3956 EXPECT_EQ(out.rv, OK);
3958 const HttpResponseInfo* response = trans->GetResponseInfo();
3959 EXPECT_TRUE(response->headers.get() != NULL);
3960 EXPECT_TRUE(response->was_fetched_via_spdy);
3961 out.status_line = response->headers->GetStatusLine();
3962 out.response_info = *response; // Make a copy so we can verify.
3964 // Read Data
3965 TestCompletionCallback read_callback;
3967 std::string content;
3968 int reads_completed = 0;
3969 do {
3970 // Read small chunks at a time.
3971 const int kSmallReadSize = 14;
3972 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3973 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
3974 if (rv == net::ERR_IO_PENDING) {
3975 data.CompleteRead();
3976 rv = read_callback.WaitForResult();
3978 if (rv > 0) {
3979 EXPECT_EQ(kSmallReadSize, rv);
3980 content.append(buf->data(), rv);
3981 } else if (rv < 0) {
3982 FAIL() << "Unexpected read error: " << rv;
3984 reads_completed++;
3985 } while (rv > 0);
3987 EXPECT_EQ(3, reads_completed); // Reads are: 14 bytes, 14 bytes, 0 bytes.
3989 out.response_data.swap(content);
3991 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3992 // MockClientSocketFactory) are still alive.
3993 base::RunLoop().RunUntilIdle();
3995 // Verify that we consumed all test data.
3996 helper.VerifyDataConsumed();
3998 EXPECT_EQ(OK, out.rv);
3999 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4000 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
4003 // Verify the case where we buffer data but read it after it has been buffered.
4004 TEST_P(SpdyNetworkTransactionTest, BufferedAll) {
4005 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4007 scoped_ptr<SpdyFrame> req(
4008 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4009 MockWrite writes[] = { CreateMockWrite(*req) };
4011 // 5 data frames in a single read.
4012 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4013 scoped_ptr<SpdyFrame> data_frame(
4014 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4015 scoped_ptr<SpdyFrame> data_frame_fin(
4016 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
4017 const SpdyFrame* frames[5] = {reply.get(), data_frame.get(), data_frame.get(),
4018 data_frame.get(), data_frame_fin.get()};
4019 char combined_frames[200];
4020 int combined_frames_len =
4021 CombineFrames(frames, arraysize(frames),
4022 combined_frames, arraysize(combined_frames));
4024 MockRead reads[] = {
4025 MockRead(ASYNC, combined_frames, combined_frames_len),
4026 MockRead(ASYNC, 0, 0) // EOF
4029 DelayedSocketData data(1, reads, arraysize(reads),
4030 writes, arraysize(writes));
4032 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4033 BoundNetLog(), GetParam(), NULL);
4034 helper.RunPreTestSetup();
4035 helper.AddData(&data);
4036 HttpNetworkTransaction* trans = helper.trans();
4038 TestCompletionCallback callback;
4039 int rv = trans->Start(
4040 &CreateGetRequest(), callback.callback(), BoundNetLog());
4041 EXPECT_EQ(ERR_IO_PENDING, rv);
4043 TransactionHelperResult out = helper.output();
4044 out.rv = callback.WaitForResult();
4045 EXPECT_EQ(out.rv, OK);
4047 const HttpResponseInfo* response = trans->GetResponseInfo();
4048 EXPECT_TRUE(response->headers.get() != NULL);
4049 EXPECT_TRUE(response->was_fetched_via_spdy);
4050 out.status_line = response->headers->GetStatusLine();
4051 out.response_info = *response; // Make a copy so we can verify.
4053 // Read Data
4054 TestCompletionCallback read_callback;
4056 std::string content;
4057 int reads_completed = 0;
4058 do {
4059 // Read small chunks at a time.
4060 const int kSmallReadSize = 14;
4061 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4062 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
4063 if (rv > 0) {
4064 EXPECT_EQ(kSmallReadSize, rv);
4065 content.append(buf->data(), rv);
4066 } else if (rv < 0) {
4067 FAIL() << "Unexpected read error: " << rv;
4069 reads_completed++;
4070 } while (rv > 0);
4072 EXPECT_EQ(3, reads_completed);
4074 out.response_data.swap(content);
4076 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4077 // MockClientSocketFactory) are still alive.
4078 base::RunLoop().RunUntilIdle();
4080 // Verify that we consumed all test data.
4081 helper.VerifyDataConsumed();
4083 EXPECT_EQ(OK, out.rv);
4084 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4085 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
4088 // Verify the case where we buffer data and close the connection.
4089 TEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
4090 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4092 scoped_ptr<SpdyFrame> req(
4093 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4094 MockWrite writes[] = { CreateMockWrite(*req) };
4096 // All data frames in a single read.
4097 // NOTE: We don't FIN the stream.
4098 scoped_ptr<SpdyFrame> data_frame(
4099 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4100 const SpdyFrame* data_frames[4] = {
4101 data_frame.get(),
4102 data_frame.get(),
4103 data_frame.get(),
4104 data_frame.get()
4106 char combined_data_frames[100];
4107 int combined_data_frames_len =
4108 CombineFrames(data_frames, arraysize(data_frames),
4109 combined_data_frames, arraysize(combined_data_frames));
4110 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4111 MockRead reads[] = {
4112 CreateMockRead(*resp),
4113 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait
4114 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
4115 MockRead(ASYNC, 0, 0) // EOF
4118 DelayedSocketData data(1, reads, arraysize(reads),
4119 writes, arraysize(writes));
4121 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4122 BoundNetLog(), GetParam(), NULL);
4123 helper.RunPreTestSetup();
4124 helper.AddData(&data);
4125 HttpNetworkTransaction* trans = helper.trans();
4127 TestCompletionCallback callback;
4129 int rv = trans->Start(
4130 &CreateGetRequest(), callback.callback(), BoundNetLog());
4131 EXPECT_EQ(ERR_IO_PENDING, rv);
4133 TransactionHelperResult out = helper.output();
4134 out.rv = callback.WaitForResult();
4135 EXPECT_EQ(out.rv, OK);
4137 const HttpResponseInfo* response = trans->GetResponseInfo();
4138 EXPECT_TRUE(response->headers.get() != NULL);
4139 EXPECT_TRUE(response->was_fetched_via_spdy);
4140 out.status_line = response->headers->GetStatusLine();
4141 out.response_info = *response; // Make a copy so we can verify.
4143 // Read Data
4144 TestCompletionCallback read_callback;
4146 std::string content;
4147 int reads_completed = 0;
4148 do {
4149 // Read small chunks at a time.
4150 const int kSmallReadSize = 14;
4151 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4152 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
4153 if (rv == net::ERR_IO_PENDING) {
4154 data.CompleteRead();
4155 rv = read_callback.WaitForResult();
4157 if (rv > 0) {
4158 content.append(buf->data(), rv);
4159 } else if (rv < 0) {
4160 // This test intentionally closes the connection, and will get an error.
4161 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
4162 break;
4164 reads_completed++;
4165 } while (rv > 0);
4167 EXPECT_EQ(0, reads_completed);
4169 out.response_data.swap(content);
4171 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4172 // MockClientSocketFactory) are still alive.
4173 base::RunLoop().RunUntilIdle();
4175 // Verify that we consumed all test data.
4176 helper.VerifyDataConsumed();
4179 // Verify the case where we buffer data and cancel the transaction.
4180 TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) {
4181 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4183 scoped_ptr<SpdyFrame> req(
4184 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4185 scoped_ptr<SpdyFrame> rst(
4186 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
4187 MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*rst)};
4189 // NOTE: We don't FIN the stream.
4190 scoped_ptr<SpdyFrame> data_frame(
4191 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4193 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4194 MockRead reads[] = {
4195 CreateMockRead(*resp),
4196 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait
4197 CreateMockRead(*data_frame),
4198 MockRead(ASYNC, 0, 0) // EOF
4201 DelayedSocketData data(1, reads, arraysize(reads),
4202 writes, arraysize(writes));
4204 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4205 BoundNetLog(), GetParam(), NULL);
4206 helper.RunPreTestSetup();
4207 helper.AddData(&data);
4208 HttpNetworkTransaction* trans = helper.trans();
4209 TestCompletionCallback callback;
4211 int rv = trans->Start(
4212 &CreateGetRequest(), callback.callback(), BoundNetLog());
4213 EXPECT_EQ(ERR_IO_PENDING, rv);
4215 TransactionHelperResult out = helper.output();
4216 out.rv = callback.WaitForResult();
4217 EXPECT_EQ(out.rv, OK);
4219 const HttpResponseInfo* response = trans->GetResponseInfo();
4220 EXPECT_TRUE(response->headers.get() != NULL);
4221 EXPECT_TRUE(response->was_fetched_via_spdy);
4222 out.status_line = response->headers->GetStatusLine();
4223 out.response_info = *response; // Make a copy so we can verify.
4225 // Read Data
4226 TestCompletionCallback read_callback;
4228 const int kReadSize = 256;
4229 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kReadSize));
4230 rv = trans->Read(buf.get(), kReadSize, read_callback.callback());
4231 ASSERT_EQ(net::ERR_IO_PENDING, rv) << "Unexpected read: " << rv;
4233 // Complete the read now, which causes buffering to start.
4234 data.CompleteRead();
4235 // Destroy the transaction, causing the stream to get cancelled
4236 // and orphaning the buffered IO task.
4237 helper.ResetTrans();
4239 // Flush the MessageLoop; this will cause the buffered IO task
4240 // to run for the final time.
4241 base::RunLoop().RunUntilIdle();
4243 // Verify that we consumed all test data.
4244 helper.VerifyDataConsumed();
4247 // Test that if the server requests persistence of settings, that we save
4248 // the settings in the HttpServerProperties.
4249 TEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
4250 if (spdy_util_.spdy_version() >= SPDY4) {
4251 // SPDY4 doesn't support settings persistence.
4252 return;
4254 static const SpdyHeaderInfo kSynReplyInfo = {
4255 SYN_REPLY, // Syn Reply
4256 1, // Stream ID
4257 0, // Associated Stream ID
4258 ConvertRequestPriorityToSpdyPriority(
4259 LOWEST, spdy_util_.spdy_version()),
4260 kSpdyCredentialSlotUnused,
4261 CONTROL_FLAG_NONE, // Control Flags
4262 false, // Compressed
4263 RST_STREAM_INVALID, // Status
4264 NULL, // Data
4265 0, // Data Length
4266 DATA_FLAG_NONE // Data Flags
4269 BoundNetLog net_log;
4270 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4271 net_log, GetParam(), NULL);
4272 helper.RunPreTestSetup();
4274 // Verify that no settings exist initially.
4275 HostPortPair host_port_pair("www.google.com", helper.port());
4276 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4277 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4278 host_port_pair).empty());
4280 // Construct the request.
4281 scoped_ptr<SpdyFrame> req(
4282 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4283 MockWrite writes[] = { CreateMockWrite(*req) };
4285 // Construct the reply.
4286 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4287 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4288 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
4289 scoped_ptr<SpdyFrame> reply(
4290 spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
4292 const SpdySettingsIds kSampleId1 = SETTINGS_UPLOAD_BANDWIDTH;
4293 unsigned int kSampleValue1 = 0x0a0a0a0a;
4294 const SpdySettingsIds kSampleId2 = SETTINGS_DOWNLOAD_BANDWIDTH;
4295 unsigned int kSampleValue2 = 0x0b0b0b0b;
4296 const SpdySettingsIds kSampleId3 = SETTINGS_ROUND_TRIP_TIME;
4297 unsigned int kSampleValue3 = 0x0c0c0c0c;
4298 scoped_ptr<SpdyFrame> settings_frame;
4300 // Construct the SETTINGS frame.
4301 SettingsMap settings;
4302 // First add a persisted setting.
4303 settings[kSampleId1] =
4304 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue1);
4305 // Next add a non-persisted setting.
4306 settings[kSampleId2] =
4307 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kSampleValue2);
4308 // Next add another persisted setting.
4309 settings[kSampleId3] =
4310 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue3);
4311 settings_frame.reset(spdy_util_.ConstructSpdySettings(settings));
4314 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4315 MockRead reads[] = {
4316 CreateMockRead(*reply),
4317 CreateMockRead(*body),
4318 CreateMockRead(*settings_frame),
4319 MockRead(ASYNC, 0, 0) // EOF
4322 DelayedSocketData data(1, reads, arraysize(reads),
4323 writes, arraysize(writes));
4324 helper.AddData(&data);
4325 helper.RunDefaultTest();
4326 helper.VerifyDataConsumed();
4327 TransactionHelperResult out = helper.output();
4328 EXPECT_EQ(OK, out.rv);
4329 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4330 EXPECT_EQ("hello!", out.response_data);
4333 // Verify we had two persisted settings.
4334 const SettingsMap& settings_map =
4335 spdy_session_pool->http_server_properties()->GetSpdySettings(
4336 host_port_pair);
4337 ASSERT_EQ(2u, settings_map.size());
4339 // Verify the first persisted setting.
4340 SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4341 EXPECT_TRUE(it1 != settings_map.end());
4342 SettingsFlagsAndValue flags_and_value1 = it1->second;
4343 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4344 EXPECT_EQ(kSampleValue1, flags_and_value1.second);
4346 // Verify the second persisted setting.
4347 SettingsMap::const_iterator it3 = settings_map.find(kSampleId3);
4348 EXPECT_TRUE(it3 != settings_map.end());
4349 SettingsFlagsAndValue flags_and_value3 = it3->second;
4350 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value3.first);
4351 EXPECT_EQ(kSampleValue3, flags_and_value3.second);
4355 // Test that when there are settings saved that they are sent back to the
4356 // server upon session establishment.
4357 TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) {
4358 if (spdy_util_.spdy_version() >= SPDY4) {
4359 // SPDY4 doesn't support settings persistence.
4360 return;
4362 static const SpdyHeaderInfo kSynReplyInfo = {
4363 SYN_REPLY, // Syn Reply
4364 1, // Stream ID
4365 0, // Associated Stream ID
4366 ConvertRequestPriorityToSpdyPriority(
4367 LOWEST, spdy_util_.spdy_version()),
4368 kSpdyCredentialSlotUnused,
4369 CONTROL_FLAG_NONE, // Control Flags
4370 false, // Compressed
4371 RST_STREAM_INVALID, // Status
4372 NULL, // Data
4373 0, // Data Length
4374 DATA_FLAG_NONE // Data Flags
4377 BoundNetLog net_log;
4378 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4379 net_log, GetParam(), NULL);
4380 helper.RunPreTestSetup();
4382 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4384 SpdySessionPoolPeer pool_peer(spdy_session_pool);
4385 pool_peer.SetEnableSendingInitialData(true);
4387 // Verify that no settings exist initially.
4388 HostPortPair host_port_pair("www.google.com", helper.port());
4389 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4390 host_port_pair).empty());
4392 const SpdySettingsIds kSampleId1 = SETTINGS_MAX_CONCURRENT_STREAMS;
4393 unsigned int kSampleValue1 = 0x0a0a0a0a;
4394 const SpdySettingsIds kSampleId2 = SETTINGS_INITIAL_WINDOW_SIZE;
4395 unsigned int kSampleValue2 = 0x0c0c0c0c;
4397 // First add a persisted setting.
4398 spdy_session_pool->http_server_properties()->SetSpdySetting(
4399 host_port_pair,
4400 kSampleId1,
4401 SETTINGS_FLAG_PLEASE_PERSIST,
4402 kSampleValue1);
4404 // Next add another persisted setting.
4405 spdy_session_pool->http_server_properties()->SetSpdySetting(
4406 host_port_pair,
4407 kSampleId2,
4408 SETTINGS_FLAG_PLEASE_PERSIST,
4409 kSampleValue2);
4411 EXPECT_EQ(2u, spdy_session_pool->http_server_properties()->GetSpdySettings(
4412 host_port_pair).size());
4414 // Construct the initial SETTINGS frame.
4415 SettingsMap initial_settings;
4416 initial_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4417 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
4418 scoped_ptr<SpdyFrame> initial_settings_frame(
4419 spdy_util_.ConstructSpdySettings(initial_settings));
4421 // Construct the initial window update.
4422 scoped_ptr<SpdyFrame> initial_window_update(
4423 spdy_util_.ConstructSpdyWindowUpdate(
4424 kSessionFlowControlStreamId,
4425 kDefaultInitialRecvWindowSize -
4426 SpdySession::GetInitialWindowSize(GetParam().protocol)));
4428 // Construct the persisted SETTINGS frame.
4429 const SettingsMap& settings =
4430 spdy_session_pool->http_server_properties()->GetSpdySettings(
4431 host_port_pair);
4432 scoped_ptr<SpdyFrame> settings_frame(
4433 spdy_util_.ConstructSpdySettings(settings));
4435 // Construct the request.
4436 scoped_ptr<SpdyFrame> req(
4437 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4439 std::vector<MockWrite> writes;
4440 if ((GetParam().protocol >= kProtoSPDY4MinimumVersion) &&
4441 (GetParam().protocol <= kProtoSPDY4MaximumVersion)) {
4442 writes.push_back(
4443 MockWrite(ASYNC,
4444 kHttp2ConnectionHeaderPrefix,
4445 kHttp2ConnectionHeaderPrefixSize));
4447 writes.push_back(CreateMockWrite(*initial_settings_frame));
4448 if (GetParam().protocol >= kProtoSPDY31) {
4449 writes.push_back(CreateMockWrite(*initial_window_update));
4451 writes.push_back(CreateMockWrite(*settings_frame));
4452 writes.push_back(CreateMockWrite(*req));
4454 // Construct the reply.
4455 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4456 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4457 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
4458 scoped_ptr<SpdyFrame> reply(
4459 spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
4461 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4462 MockRead reads[] = {
4463 CreateMockRead(*reply),
4464 CreateMockRead(*body),
4465 MockRead(ASYNC, 0, 0) // EOF
4468 DelayedSocketData data(2, reads, arraysize(reads),
4469 vector_as_array(&writes), writes.size());
4470 helper.AddData(&data);
4471 helper.RunDefaultTest();
4472 helper.VerifyDataConsumed();
4473 TransactionHelperResult out = helper.output();
4474 EXPECT_EQ(OK, out.rv);
4475 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4476 EXPECT_EQ("hello!", out.response_data);
4479 // Verify we had two persisted settings.
4480 const SettingsMap& settings_map =
4481 spdy_session_pool->http_server_properties()->GetSpdySettings(
4482 host_port_pair);
4483 ASSERT_EQ(2u, settings_map.size());
4485 // Verify the first persisted setting.
4486 SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4487 EXPECT_TRUE(it1 != settings_map.end());
4488 SettingsFlagsAndValue flags_and_value1 = it1->second;
4489 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4490 EXPECT_EQ(kSampleValue1, flags_and_value1.second);
4492 // Verify the second persisted setting.
4493 SettingsMap::const_iterator it2 = settings_map.find(kSampleId2);
4494 EXPECT_TRUE(it2 != settings_map.end());
4495 SettingsFlagsAndValue flags_and_value2 = it2->second;
4496 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value2.first);
4497 EXPECT_EQ(kSampleValue2, flags_and_value2.second);
4501 TEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
4502 scoped_ptr<SpdyFrame> req(
4503 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4504 MockWrite writes[] = { CreateMockWrite(*req) };
4506 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway());
4507 MockRead reads[] = {
4508 CreateMockRead(*go_away),
4511 DelayedSocketData data(1, reads, arraysize(reads),
4512 writes, arraysize(writes));
4513 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4514 BoundNetLog(), GetParam(), NULL);
4515 helper.AddData(&data);
4516 helper.RunToCompletion(&data);
4517 TransactionHelperResult out = helper.output();
4518 EXPECT_EQ(ERR_ABORTED, out.rv);
4521 TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) {
4522 scoped_ptr<SpdyFrame> req(
4523 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4524 MockWrite writes[] = { CreateMockWrite(*req) };
4526 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4527 MockRead reads[] = {
4528 CreateMockRead(*resp),
4529 MockRead(SYNCHRONOUS, 0, 0) // EOF
4532 DelayedSocketData data(1, reads, arraysize(reads),
4533 writes, arraysize(writes));
4534 BoundNetLog log;
4535 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4536 log, GetParam(), NULL);
4537 helper.RunPreTestSetup();
4538 helper.AddData(&data);
4539 HttpNetworkTransaction* trans = helper.trans();
4541 TestCompletionCallback callback;
4542 TransactionHelperResult out;
4543 out.rv = trans->Start(&CreateGetRequest(), callback.callback(), log);
4545 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4546 out.rv = callback.WaitForResult();
4547 EXPECT_EQ(out.rv, OK);
4549 const HttpResponseInfo* response = trans->GetResponseInfo();
4550 EXPECT_TRUE(response->headers.get() != NULL);
4551 EXPECT_TRUE(response->was_fetched_via_spdy);
4552 out.rv = ReadTransaction(trans, &out.response_data);
4553 EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv);
4555 // Verify that we consumed all test data.
4556 helper.VerifyDataConsumed();
4559 // HTTP_1_1_REQUIRED results in ERR_HTTP_1_1_REQUIRED.
4560 TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredError) {
4561 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4562 if (spdy_util_.spdy_version() < SPDY4)
4563 return;
4565 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4566 BoundNetLog(), GetParam(), nullptr);
4568 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway(
4569 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
4570 MockRead reads[] = {
4571 CreateMockRead(*go_away),
4573 DelayedSocketData data(0, reads, arraysize(reads), nullptr, 0);
4575 helper.RunToCompletion(&data);
4576 TransactionHelperResult out = helper.output();
4577 EXPECT_EQ(ERR_HTTP_1_1_REQUIRED, out.rv);
4580 // Retry with HTTP/1.1 when receiving HTTP_1_1_REQUIRED. Note that no actual
4581 // protocol negotiation happens, instead this test forces protocols for both
4582 // sockets.
4583 TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredRetry) {
4584 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4585 if (spdy_util_.spdy_version() < SPDY4)
4586 return;
4587 // HTTP_1_1_REQUIRED implementation relies on the assumption that HTTP/2 is
4588 // only spoken over SSL.
4589 if (GetParam().ssl_type != SPDYSSL)
4590 return;
4592 HttpRequestInfo request;
4593 request.method = "GET";
4594 request.url = GURL("https://www.google.com/");
4595 scoped_ptr<SpdySessionDependencies> session_deps(
4596 CreateSpdySessionDependencies(GetParam()));
4597 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
4598 session_deps->force_spdy_over_ssl = false;
4599 session_deps->force_spdy_always = false;
4600 session_deps->next_protos = SpdyNextProtos();
4601 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
4602 GetParam(), session_deps.release());
4604 // First socket: HTTP/2 request rejected with HTTP_1_1_REQUIRED.
4605 const char* url = "https://www.google.com/";
4606 scoped_ptr<SpdyHeaderBlock> headers(spdy_util_.ConstructGetHeaderBlock(url));
4607 scoped_ptr<SpdyFrame> req(
4608 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
4609 MockWrite writes0[] = {CreateMockWrite(*req)};
4610 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway(
4611 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
4612 MockRead reads0[] = {CreateMockRead(*go_away)};
4613 DelayedSocketData data0(1, reads0, arraysize(reads0), writes0,
4614 arraysize(writes0));
4616 scoped_ptr<SSLSocketDataProvider> ssl_provider0(
4617 new SSLSocketDataProvider(ASYNC, OK));
4618 // Expect HTTP/2 protocols too in SSLConfig.
4619 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4620 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY31);
4621 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY4_14);
4622 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY4_15);
4623 // Force SPDY.
4624 ssl_provider0->SetNextProto(GetParam().protocol);
4625 helper.AddDataWithSSLSocketDataProvider(&data0, ssl_provider0.Pass());
4627 // Second socket: falling back to HTTP/1.1.
4628 MockWrite writes1[] = {MockWrite(
4629 "GET / HTTP/1.1\r\n"
4630 "Host: www.google.com\r\n"
4631 "Connection: keep-alive\r\n\r\n")};
4632 MockRead reads1[] = {MockRead(
4633 "HTTP/1.1 200 OK\r\n"
4634 "Content-Length: 5\r\n\r\n"
4635 "hello")};
4636 DelayedSocketData data1(1, reads1, arraysize(reads1), writes1,
4637 arraysize(writes1));
4639 scoped_ptr<SSLSocketDataProvider> ssl_provider1(
4640 new SSLSocketDataProvider(ASYNC, OK));
4641 // Expect only HTTP/1.1 protocol in SSLConfig.
4642 ssl_provider1->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4643 // Force HTTP/1.1.
4644 ssl_provider1->SetNextProto(kProtoHTTP11);
4645 helper.AddDataWithSSLSocketDataProvider(&data1, ssl_provider1.Pass());
4647 base::WeakPtr<HttpServerProperties> http_server_properties =
4648 helper.session()->spdy_session_pool()->http_server_properties();
4649 const HostPortPair host_port_pair = HostPortPair::FromURL(GURL(url));
4650 EXPECT_FALSE(http_server_properties->RequiresHTTP11(host_port_pair));
4652 helper.RunPreTestSetup();
4653 helper.StartDefaultTest();
4654 helper.FinishDefaultTestWithoutVerification();
4655 helper.VerifyDataConsumed();
4656 EXPECT_TRUE(http_server_properties->RequiresHTTP11(host_port_pair));
4658 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
4659 ASSERT_TRUE(response != nullptr);
4660 ASSERT_TRUE(response->headers.get() != nullptr);
4661 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4662 EXPECT_FALSE(response->was_fetched_via_spdy);
4663 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1, response->connection_info);
4664 EXPECT_TRUE(response->was_npn_negotiated);
4665 EXPECT_TRUE(request.url.SchemeIs("https"));
4666 EXPECT_EQ("127.0.0.1", response->socket_address.host());
4667 EXPECT_EQ(443, response->socket_address.port());
4668 std::string response_data;
4669 ASSERT_EQ(OK, ReadTransaction(helper.trans(), &response_data));
4670 EXPECT_EQ("hello", response_data);
4673 // Retry with HTTP/1.1 to the proxy when receiving HTTP_1_1_REQUIRED from the
4674 // proxy. Note that no actual protocol negotiation happens, instead this test
4675 // forces protocols for both sockets.
4676 TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredProxyRetry) {
4677 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4678 if (spdy_util_.spdy_version() < SPDY4)
4679 return;
4680 // HTTP_1_1_REQUIRED implementation relies on the assumption that HTTP/2 is
4681 // only spoken over SSL.
4682 if (GetParam().ssl_type != SPDYSSL)
4683 return;
4685 HttpRequestInfo request;
4686 request.method = "GET";
4687 request.url = GURL("https://www.google.com/");
4688 scoped_ptr<SpdySessionDependencies> session_deps(
4689 CreateSpdySessionDependencies(
4690 GetParam(),
4691 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70")));
4692 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
4693 session_deps->force_spdy_over_ssl = false;
4694 session_deps->force_spdy_always = false;
4695 session_deps->next_protos = SpdyNextProtos();
4696 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
4697 GetParam(), session_deps.release());
4699 // First socket: HTTP/2 CONNECT rejected with HTTP_1_1_REQUIRED.
4700 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(
4701 nullptr, 0, 1, LOWEST, HostPortPair("www.google.com", 443)));
4702 MockWrite writes0[] = {CreateMockWrite(*req)};
4703 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway(
4704 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
4705 MockRead reads0[] = {CreateMockRead(*go_away)};
4706 DelayedSocketData data0(1, reads0, arraysize(reads0), writes0,
4707 arraysize(writes0));
4709 scoped_ptr<SSLSocketDataProvider> ssl_provider0(
4710 new SSLSocketDataProvider(ASYNC, OK));
4711 // Expect HTTP/2 protocols too in SSLConfig.
4712 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4713 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY31);
4714 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY4_14);
4715 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY4_15);
4716 // Force SPDY.
4717 ssl_provider0->SetNextProto(GetParam().protocol);
4718 helper.AddDataWithSSLSocketDataProvider(&data0, ssl_provider0.Pass());
4720 // Second socket: retry using HTTP/1.1.
4721 MockWrite writes1[] = {
4722 MockWrite(ASYNC, 1,
4723 "CONNECT www.google.com:443 HTTP/1.1\r\n"
4724 "Host: www.google.com\r\n"
4725 "Proxy-Connection: keep-alive\r\n\r\n"),
4726 MockWrite(ASYNC, 3,
4727 "GET / HTTP/1.1\r\n"
4728 "Host: www.google.com\r\n"
4729 "Connection: keep-alive\r\n\r\n"),
4732 MockRead reads1[] = {
4733 MockRead(ASYNC, 2, "HTTP/1.1 200 OK\r\n\r\n"),
4734 MockRead(ASYNC, 4,
4735 "HTTP/1.1 200 OK\r\n"
4736 "Content-Length: 5\r\n\r\n"
4737 "hello"),
4739 DelayedSocketData data1(1, reads1, arraysize(reads1), writes1,
4740 arraysize(writes1));
4742 scoped_ptr<SSLSocketDataProvider> ssl_provider1(
4743 new SSLSocketDataProvider(ASYNC, OK));
4744 // Expect only HTTP/1.1 protocol in SSLConfig.
4745 ssl_provider1->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4746 // Force HTTP/1.1.
4747 ssl_provider1->SetNextProto(kProtoHTTP11);
4748 helper.AddDataWithSSLSocketDataProvider(&data1, ssl_provider1.Pass());
4750 // A third socket is needed for the tunnelled connection.
4751 scoped_ptr<SSLSocketDataProvider> ssl_provider2(
4752 new SSLSocketDataProvider(ASYNC, OK));
4753 helper.session_deps()->socket_factory->AddSSLSocketDataProvider(
4754 ssl_provider2.get());
4756 base::WeakPtr<HttpServerProperties> http_server_properties =
4757 helper.session()->spdy_session_pool()->http_server_properties();
4758 const HostPortPair proxy_host_port_pair = HostPortPair("myproxy", 70);
4759 EXPECT_FALSE(http_server_properties->RequiresHTTP11(proxy_host_port_pair));
4761 helper.RunPreTestSetup();
4762 helper.StartDefaultTest();
4763 helper.FinishDefaultTestWithoutVerification();
4764 helper.VerifyDataConsumed();
4765 EXPECT_TRUE(http_server_properties->RequiresHTTP11(proxy_host_port_pair));
4767 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
4768 ASSERT_TRUE(response != nullptr);
4769 ASSERT_TRUE(response->headers.get() != nullptr);
4770 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4771 EXPECT_FALSE(response->was_fetched_via_spdy);
4772 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1, response->connection_info);
4773 EXPECT_FALSE(response->was_npn_negotiated);
4774 EXPECT_TRUE(request.url.SchemeIs("https"));
4775 EXPECT_EQ("127.0.0.1", response->socket_address.host());
4776 EXPECT_EQ(70, response->socket_address.port());
4777 std::string response_data;
4778 ASSERT_EQ(OK, ReadTransaction(helper.trans(), &response_data));
4779 EXPECT_EQ("hello", response_data);
4782 // Test to make sure we can correctly connect through a proxy.
4783 TEST_P(SpdyNetworkTransactionTest, ProxyConnect) {
4784 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4785 BoundNetLog(), GetParam(), NULL);
4786 helper.session_deps().reset(CreateSpdySessionDependencies(
4787 GetParam(),
4788 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
4789 helper.SetSession(make_scoped_refptr(
4790 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
4791 helper.RunPreTestSetup();
4792 HttpNetworkTransaction* trans = helper.trans();
4794 const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4795 "Host: www.google.com\r\n"
4796 "Proxy-Connection: keep-alive\r\n\r\n"};
4797 const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4798 "Host: www.google.com\r\n"
4799 "Proxy-Connection: keep-alive\r\n\r\n"};
4800 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4801 scoped_ptr<SpdyFrame> req(
4802 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4803 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4804 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4806 MockWrite writes_SPDYNPN[] = {
4807 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4808 CreateMockWrite(*req, 2),
4810 MockRead reads_SPDYNPN[] = {
4811 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4812 CreateMockRead(*resp, 3),
4813 CreateMockRead(*body.get(), 4),
4814 MockRead(ASYNC, 0, 0, 5),
4817 MockWrite writes_SPDYSSL[] = {
4818 MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0),
4819 CreateMockWrite(*req, 2),
4821 MockRead reads_SPDYSSL[] = {
4822 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4823 CreateMockRead(*resp, 3),
4824 CreateMockRead(*body.get(), 4),
4825 MockRead(ASYNC, 0, 0, 5),
4828 MockWrite writes_SPDYNOSSL[] = {
4829 CreateMockWrite(*req, 0),
4832 MockRead reads_SPDYNOSSL[] = {
4833 CreateMockRead(*resp, 1),
4834 CreateMockRead(*body.get(), 2),
4835 MockRead(ASYNC, 0, 0, 3),
4838 scoped_ptr<OrderedSocketData> data;
4839 switch (GetParam().ssl_type) {
4840 case SPDYNOSSL:
4841 data.reset(new OrderedSocketData(reads_SPDYNOSSL,
4842 arraysize(reads_SPDYNOSSL),
4843 writes_SPDYNOSSL,
4844 arraysize(writes_SPDYNOSSL)));
4845 break;
4846 case SPDYSSL:
4847 data.reset(new OrderedSocketData(reads_SPDYSSL,
4848 arraysize(reads_SPDYSSL),
4849 writes_SPDYSSL,
4850 arraysize(writes_SPDYSSL)));
4851 break;
4852 case SPDYNPN:
4853 data.reset(new OrderedSocketData(reads_SPDYNPN,
4854 arraysize(reads_SPDYNPN),
4855 writes_SPDYNPN,
4856 arraysize(writes_SPDYNPN)));
4857 break;
4858 default:
4859 NOTREACHED();
4862 helper.AddData(data.get());
4863 TestCompletionCallback callback;
4865 int rv = trans->Start(
4866 &CreateGetRequest(), callback.callback(), BoundNetLog());
4867 EXPECT_EQ(ERR_IO_PENDING, rv);
4869 rv = callback.WaitForResult();
4870 EXPECT_EQ(0, rv);
4872 // Verify the SYN_REPLY.
4873 HttpResponseInfo response = *trans->GetResponseInfo();
4874 EXPECT_TRUE(response.headers.get() != NULL);
4875 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
4877 std::string response_data;
4878 ASSERT_EQ(OK, ReadTransaction(trans, &response_data));
4879 EXPECT_EQ("hello!", response_data);
4880 helper.VerifyDataConsumed();
4883 // Test to make sure we can correctly connect through a proxy to www.google.com,
4884 // if there already exists a direct spdy connection to www.google.com. See
4885 // http://crbug.com/49874
4886 TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
4887 // When setting up the first transaction, we store the SpdySessionPool so that
4888 // we can use the same pool in the second transaction.
4889 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4890 BoundNetLog(), GetParam(), NULL);
4892 // Use a proxy service which returns a proxy fallback list from DIRECT to
4893 // myproxy:70. For this test there will be no fallback, so it is equivalent
4894 // to simply DIRECT. The reason for appending the second proxy is to verify
4895 // that the session pool key used does is just "DIRECT".
4896 helper.session_deps().reset(CreateSpdySessionDependencies(
4897 GetParam(),
4898 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
4899 helper.SetSession(make_scoped_refptr(
4900 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
4902 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4903 helper.RunPreTestSetup();
4905 // Construct and send a simple GET request.
4906 scoped_ptr<SpdyFrame> req(
4907 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4908 MockWrite writes[] = {
4909 CreateMockWrite(*req, 1),
4912 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4913 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4914 MockRead reads[] = {
4915 CreateMockRead(*resp, 2),
4916 CreateMockRead(*body, 3),
4917 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause
4918 MockRead(ASYNC, 0, 5) // EOF
4920 OrderedSocketData data(reads, arraysize(reads),
4921 writes, arraysize(writes));
4922 helper.AddData(&data);
4923 HttpNetworkTransaction* trans = helper.trans();
4925 TestCompletionCallback callback;
4926 TransactionHelperResult out;
4927 out.rv = trans->Start(
4928 &CreateGetRequest(), callback.callback(), BoundNetLog());
4930 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4931 out.rv = callback.WaitForResult();
4932 EXPECT_EQ(out.rv, OK);
4934 const HttpResponseInfo* response = trans->GetResponseInfo();
4935 EXPECT_TRUE(response->headers.get() != NULL);
4936 EXPECT_TRUE(response->was_fetched_via_spdy);
4937 out.rv = ReadTransaction(trans, &out.response_data);
4938 EXPECT_EQ(OK, out.rv);
4939 out.status_line = response->headers->GetStatusLine();
4940 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4941 EXPECT_EQ("hello!", out.response_data);
4943 // Check that the SpdySession is still in the SpdySessionPool.
4944 HostPortPair host_port_pair("www.google.com", helper.port());
4945 SpdySessionKey session_pool_key_direct(
4946 host_port_pair, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
4947 EXPECT_TRUE(HasSpdySession(spdy_session_pool, session_pool_key_direct));
4948 SpdySessionKey session_pool_key_proxy(
4949 host_port_pair,
4950 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP),
4951 PRIVACY_MODE_DISABLED);
4952 EXPECT_FALSE(HasSpdySession(spdy_session_pool, session_pool_key_proxy));
4954 // Set up data for the proxy connection.
4955 const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4956 "Host: www.google.com\r\n"
4957 "Proxy-Connection: keep-alive\r\n\r\n"};
4958 const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4959 "Host: www.google.com\r\n"
4960 "Proxy-Connection: keep-alive\r\n\r\n"};
4961 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4962 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyGet(
4963 "http://www.google.com/foo.dat", false, 1, LOWEST));
4964 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4965 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
4967 MockWrite writes_SPDYNPN[] = {
4968 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4969 CreateMockWrite(*req2, 2),
4971 MockRead reads_SPDYNPN[] = {
4972 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4973 CreateMockRead(*resp2, 3),
4974 CreateMockRead(*body2, 4),
4975 MockRead(ASYNC, 0, 5) // EOF
4978 MockWrite writes_SPDYNOSSL[] = {
4979 CreateMockWrite(*req2, 0),
4981 MockRead reads_SPDYNOSSL[] = {
4982 CreateMockRead(*resp2, 1),
4983 CreateMockRead(*body2, 2),
4984 MockRead(ASYNC, 0, 3) // EOF
4987 MockWrite writes_SPDYSSL[] = {
4988 MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0),
4989 CreateMockWrite(*req2, 2),
4991 MockRead reads_SPDYSSL[] = {
4992 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4993 CreateMockRead(*resp2, 3),
4994 CreateMockRead(*body2, 4),
4995 MockRead(ASYNC, 0, 0, 5),
4998 scoped_ptr<OrderedSocketData> data_proxy;
4999 switch (GetParam().ssl_type) {
5000 case SPDYNPN:
5001 data_proxy.reset(new OrderedSocketData(reads_SPDYNPN,
5002 arraysize(reads_SPDYNPN),
5003 writes_SPDYNPN,
5004 arraysize(writes_SPDYNPN)));
5005 break;
5006 case SPDYNOSSL:
5007 data_proxy.reset(new OrderedSocketData(reads_SPDYNOSSL,
5008 arraysize(reads_SPDYNOSSL),
5009 writes_SPDYNOSSL,
5010 arraysize(writes_SPDYNOSSL)));
5011 break;
5012 case SPDYSSL:
5013 data_proxy.reset(new OrderedSocketData(reads_SPDYSSL,
5014 arraysize(reads_SPDYSSL),
5015 writes_SPDYSSL,
5016 arraysize(writes_SPDYSSL)));
5017 break;
5018 default:
5019 NOTREACHED();
5022 // Create another request to www.google.com, but this time through a proxy.
5023 HttpRequestInfo request_proxy;
5024 request_proxy.method = "GET";
5025 request_proxy.url = GURL("http://www.google.com/foo.dat");
5026 request_proxy.load_flags = 0;
5027 scoped_ptr<SpdySessionDependencies> ssd_proxy(
5028 CreateSpdySessionDependencies(GetParam()));
5029 // Ensure that this transaction uses the same SpdySessionPool.
5030 scoped_refptr<HttpNetworkSession> session_proxy(
5031 SpdySessionDependencies::SpdyCreateSession(ssd_proxy.get()));
5032 NormalSpdyTransactionHelper helper_proxy(request_proxy, DEFAULT_PRIORITY,
5033 BoundNetLog(), GetParam(), NULL);
5034 HttpNetworkSessionPeer session_peer(session_proxy);
5035 scoped_ptr<net::ProxyService> proxy_service(
5036 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
5037 session_peer.SetProxyService(proxy_service.get());
5038 helper_proxy.session_deps().swap(ssd_proxy);
5039 helper_proxy.SetSession(session_proxy);
5040 helper_proxy.RunPreTestSetup();
5041 helper_proxy.AddData(data_proxy.get());
5043 HttpNetworkTransaction* trans_proxy = helper_proxy.trans();
5044 TestCompletionCallback callback_proxy;
5045 int rv = trans_proxy->Start(
5046 &request_proxy, callback_proxy.callback(), BoundNetLog());
5047 EXPECT_EQ(ERR_IO_PENDING, rv);
5048 rv = callback_proxy.WaitForResult();
5049 EXPECT_EQ(0, rv);
5051 HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo();
5052 EXPECT_TRUE(response_proxy.headers.get() != NULL);
5053 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy.headers->GetStatusLine());
5055 std::string response_data;
5056 ASSERT_EQ(OK, ReadTransaction(trans_proxy, &response_data));
5057 EXPECT_EQ("hello!", response_data);
5059 data.CompleteRead();
5060 helper_proxy.VerifyDataConsumed();
5063 // When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
5064 // on a new connection, if the connection was previously known to be good.
5065 // This can happen when a server reboots without saying goodbye, or when
5066 // we're behind a NAT that masked the RST.
5067 TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
5068 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5069 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
5070 MockRead reads[] = {
5071 CreateMockRead(*resp),
5072 CreateMockRead(*body),
5073 MockRead(ASYNC, ERR_IO_PENDING),
5074 MockRead(ASYNC, ERR_CONNECTION_RESET),
5077 MockRead reads2[] = {
5078 CreateMockRead(*resp),
5079 CreateMockRead(*body),
5080 MockRead(ASYNC, 0, 0) // EOF
5083 // This test has a couple of variants.
5084 enum {
5085 // Induce the RST while waiting for our transaction to send.
5086 VARIANT_RST_DURING_SEND_COMPLETION,
5087 // Induce the RST while waiting for our transaction to read.
5088 // In this case, the send completed - everything copied into the SNDBUF.
5089 VARIANT_RST_DURING_READ_COMPLETION
5092 for (int variant = VARIANT_RST_DURING_SEND_COMPLETION;
5093 variant <= VARIANT_RST_DURING_READ_COMPLETION;
5094 ++variant) {
5095 DelayedSocketData data1(1, reads, arraysize(reads), NULL, 0);
5097 DelayedSocketData data2(1, reads2, arraysize(reads2), NULL, 0);
5099 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5100 BoundNetLog(), GetParam(), NULL);
5101 helper.AddData(&data1);
5102 helper.AddData(&data2);
5103 helper.RunPreTestSetup();
5105 for (int i = 0; i < 2; ++i) {
5106 scoped_ptr<HttpNetworkTransaction> trans(
5107 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5109 TestCompletionCallback callback;
5110 int rv = trans->Start(
5111 &helper.request(), callback.callback(), BoundNetLog());
5112 EXPECT_EQ(ERR_IO_PENDING, rv);
5113 // On the second transaction, we trigger the RST.
5114 if (i == 1) {
5115 if (variant == VARIANT_RST_DURING_READ_COMPLETION) {
5116 // Writes to the socket complete asynchronously on SPDY by running
5117 // through the message loop. Complete the write here.
5118 base::RunLoop().RunUntilIdle();
5121 // Now schedule the ERR_CONNECTION_RESET.
5122 EXPECT_EQ(3u, data1.read_index());
5123 data1.CompleteRead();
5124 EXPECT_EQ(4u, data1.read_index());
5126 rv = callback.WaitForResult();
5127 EXPECT_EQ(OK, rv);
5129 const HttpResponseInfo* response = trans->GetResponseInfo();
5130 ASSERT_TRUE(response != NULL);
5131 EXPECT_TRUE(response->headers.get() != NULL);
5132 EXPECT_TRUE(response->was_fetched_via_spdy);
5133 std::string response_data;
5134 rv = ReadTransaction(trans.get(), &response_data);
5135 EXPECT_EQ(OK, rv);
5136 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5137 EXPECT_EQ("hello!", response_data);
5140 helper.VerifyDataConsumed();
5144 // Test that turning SPDY on and off works properly.
5145 TEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) {
5146 HttpStreamFactory::set_spdy_enabled(true);
5147 scoped_ptr<SpdyFrame> req(
5148 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5149 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
5151 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5152 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
5153 MockRead spdy_reads[] = {
5154 CreateMockRead(*resp),
5155 CreateMockRead(*body),
5156 MockRead(ASYNC, 0, 0) // EOF
5159 DelayedSocketData data(1, spdy_reads, arraysize(spdy_reads),
5160 spdy_writes, arraysize(spdy_writes));
5161 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5162 BoundNetLog(), GetParam(), NULL);
5163 helper.RunToCompletion(&data);
5164 TransactionHelperResult out = helper.output();
5165 EXPECT_EQ(OK, out.rv);
5166 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
5167 EXPECT_EQ("hello!", out.response_data);
5169 net::HttpStreamFactory::set_spdy_enabled(false);
5170 MockRead http_reads[] = {
5171 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5172 MockRead("hello from http"),
5173 MockRead(SYNCHRONOUS, OK),
5175 DelayedSocketData data2(1, http_reads, arraysize(http_reads), NULL, 0);
5176 NormalSpdyTransactionHelper helper2(CreateGetRequest(), DEFAULT_PRIORITY,
5177 BoundNetLog(), GetParam(), NULL);
5178 helper2.SetSpdyDisabled();
5179 helper2.RunToCompletion(&data2);
5180 TransactionHelperResult out2 = helper2.output();
5181 EXPECT_EQ(OK, out2.rv);
5182 EXPECT_EQ("HTTP/1.1 200 OK", out2.status_line);
5183 EXPECT_EQ("hello from http", out2.response_data);
5185 net::HttpStreamFactory::set_spdy_enabled(true);
5188 // Tests that Basic authentication works over SPDY
5189 TEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) {
5190 net::HttpStreamFactory::set_spdy_enabled(true);
5192 // The first request will be a bare GET, the second request will be a
5193 // GET with an Authorization header.
5194 scoped_ptr<SpdyFrame> req_get(
5195 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5196 const char* const kExtraAuthorizationHeaders[] = {
5197 "authorization", "Basic Zm9vOmJhcg=="
5199 scoped_ptr<SpdyFrame> req_get_authorization(
5200 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
5201 arraysize(kExtraAuthorizationHeaders) / 2,
5202 false, 3, LOWEST, true));
5203 MockWrite spdy_writes[] = {
5204 CreateMockWrite(*req_get, 1),
5205 CreateMockWrite(*req_get_authorization, 4),
5208 // The first response is a 401 authentication challenge, and the second
5209 // response will be a 200 response since the second request includes a valid
5210 // Authorization header.
5211 const char* const kExtraAuthenticationHeaders[] = {
5212 "www-authenticate",
5213 "Basic realm=\"MyRealm\""
5215 scoped_ptr<SpdyFrame> resp_authentication(
5216 spdy_util_.ConstructSpdySynReplyError(
5217 "401 Authentication Required",
5218 kExtraAuthenticationHeaders,
5219 arraysize(kExtraAuthenticationHeaders) / 2,
5220 1));
5221 scoped_ptr<SpdyFrame> body_authentication(
5222 spdy_util_.ConstructSpdyBodyFrame(1, true));
5223 scoped_ptr<SpdyFrame> resp_data(
5224 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5225 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
5226 MockRead spdy_reads[] = {
5227 CreateMockRead(*resp_authentication, 2),
5228 CreateMockRead(*body_authentication, 3),
5229 CreateMockRead(*resp_data, 5),
5230 CreateMockRead(*body_data, 6),
5231 MockRead(ASYNC, 0, 7),
5234 OrderedSocketData data(spdy_reads, arraysize(spdy_reads),
5235 spdy_writes, arraysize(spdy_writes));
5236 HttpRequestInfo request(CreateGetRequest());
5237 BoundNetLog net_log;
5238 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5239 net_log, GetParam(), NULL);
5241 helper.RunPreTestSetup();
5242 helper.AddData(&data);
5243 HttpNetworkTransaction* trans = helper.trans();
5244 TestCompletionCallback callback;
5245 const int rv_start = trans->Start(&request, callback.callback(), net_log);
5246 EXPECT_EQ(ERR_IO_PENDING, rv_start);
5247 const int rv_start_complete = callback.WaitForResult();
5248 EXPECT_EQ(OK, rv_start_complete);
5250 // Make sure the response has an auth challenge.
5251 const HttpResponseInfo* const response_start = trans->GetResponseInfo();
5252 ASSERT_TRUE(response_start != NULL);
5253 ASSERT_TRUE(response_start->headers.get() != NULL);
5254 EXPECT_EQ(401, response_start->headers->response_code());
5255 EXPECT_TRUE(response_start->was_fetched_via_spdy);
5256 AuthChallengeInfo* auth_challenge = response_start->auth_challenge.get();
5257 ASSERT_TRUE(auth_challenge != NULL);
5258 EXPECT_FALSE(auth_challenge->is_proxy);
5259 EXPECT_EQ("basic", auth_challenge->scheme);
5260 EXPECT_EQ("MyRealm", auth_challenge->realm);
5262 // Restart with a username/password.
5263 AuthCredentials credentials(base::ASCIIToUTF16("foo"),
5264 base::ASCIIToUTF16("bar"));
5265 TestCompletionCallback callback_restart;
5266 const int rv_restart = trans->RestartWithAuth(
5267 credentials, callback_restart.callback());
5268 EXPECT_EQ(ERR_IO_PENDING, rv_restart);
5269 const int rv_restart_complete = callback_restart.WaitForResult();
5270 EXPECT_EQ(OK, rv_restart_complete);
5271 // TODO(cbentzel): This is actually the same response object as before, but
5272 // data has changed.
5273 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
5274 ASSERT_TRUE(response_restart != NULL);
5275 ASSERT_TRUE(response_restart->headers.get() != NULL);
5276 EXPECT_EQ(200, response_restart->headers->response_code());
5277 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
5280 TEST_P(SpdyNetworkTransactionTest, ServerPushWithHeaders) {
5281 scoped_ptr<SpdyFrame> stream1_syn(
5282 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5283 scoped_ptr<SpdyFrame> stream1_body(
5284 spdy_util_.ConstructSpdyBodyFrame(1, true));
5285 MockWrite writes[] = {
5286 CreateMockWrite(*stream1_syn, 1),
5289 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5290 spdy_util_.AddUrlToHeaderBlock(
5291 "http://www.google.com/foo.dat", initial_headers.get());
5292 scoped_ptr<SpdyFrame> stream2_syn(
5293 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
5295 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5296 (*late_headers)["hello"] = "bye";
5297 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5298 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5299 scoped_ptr<SpdyFrame> stream2_headers(
5300 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5301 false,
5303 LOWEST,
5304 HEADERS,
5305 CONTROL_FLAG_NONE,
5306 0));
5308 scoped_ptr<SpdyFrame>
5309 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5310 const char kPushedData[] = "pushed";
5311 scoped_ptr<SpdyFrame> stream2_body(
5312 spdy_util_.ConstructSpdyBodyFrame(
5313 2, kPushedData, strlen(kPushedData), true));
5314 MockRead reads[] = {
5315 CreateMockRead(*stream1_reply, 2),
5316 CreateMockRead(*stream2_syn, 3),
5317 CreateMockRead(*stream2_headers, 4),
5318 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
5319 CreateMockRead(*stream2_body, 5),
5320 MockRead(ASYNC, ERR_IO_PENDING, 7), // Force a pause
5323 HttpResponseInfo response;
5324 HttpResponseInfo response2;
5325 std::string expected_push_result("pushed");
5326 OrderedSocketData data(reads, arraysize(reads),
5327 writes, arraysize(writes));
5328 RunServerPushTest(&data,
5329 &response,
5330 &response2,
5331 expected_push_result);
5333 // Verify the SYN_REPLY.
5334 EXPECT_TRUE(response.headers.get() != NULL);
5335 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5337 // Verify the pushed stream.
5338 EXPECT_TRUE(response2.headers.get() != NULL);
5339 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5342 TEST_P(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
5343 // We push a stream and attempt to claim it before the headers come down.
5344 scoped_ptr<SpdyFrame> stream1_syn(
5345 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5346 scoped_ptr<SpdyFrame> stream1_body(
5347 spdy_util_.ConstructSpdyBodyFrame(1, true));
5348 MockWrite writes[] = {
5349 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5352 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5353 spdy_util_.AddUrlToHeaderBlock(
5354 "http://www.google.com/foo.dat", initial_headers.get());
5355 scoped_ptr<SpdyFrame> stream2_syn(
5356 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
5358 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5359 (*late_headers)["hello"] = "bye";
5360 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5361 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5362 scoped_ptr<SpdyFrame> stream2_headers(
5363 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5364 false,
5366 LOWEST,
5367 HEADERS,
5368 CONTROL_FLAG_NONE,
5369 0));
5371 scoped_ptr<SpdyFrame>
5372 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5373 const char kPushedData[] = "pushed";
5374 scoped_ptr<SpdyFrame> stream2_body(
5375 spdy_util_.ConstructSpdyBodyFrame(
5376 2, kPushedData, strlen(kPushedData), true));
5377 MockRead reads[] = {
5378 CreateMockRead(*stream1_reply, 1),
5379 CreateMockRead(*stream2_syn, 2),
5380 CreateMockRead(*stream1_body, 3),
5381 CreateMockRead(*stream2_headers, 4),
5382 CreateMockRead(*stream2_body, 5),
5383 MockRead(ASYNC, 0, 6), // EOF
5386 HttpResponseInfo response;
5387 HttpResponseInfo response2;
5388 std::string expected_push_result("pushed");
5389 DeterministicSocketData data(reads, arraysize(reads),
5390 writes, arraysize(writes));
5392 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5393 BoundNetLog(), GetParam(), NULL);
5394 helper.SetDeterministic();
5395 helper.AddDeterministicData(&data);
5396 helper.RunPreTestSetup();
5398 HttpNetworkTransaction* trans = helper.trans();
5400 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5401 // and the body of the primary stream, but before we've received the HEADERS
5402 // for the pushed stream.
5403 data.SetStop(3);
5405 // Start the transaction.
5406 TestCompletionCallback callback;
5407 int rv = trans->Start(
5408 &CreateGetRequest(), callback.callback(), BoundNetLog());
5409 EXPECT_EQ(ERR_IO_PENDING, rv);
5410 data.Run();
5411 rv = callback.WaitForResult();
5412 EXPECT_EQ(0, rv);
5414 // Request the pushed path. At this point, we've received the push, but the
5415 // headers are not yet complete.
5416 scoped_ptr<HttpNetworkTransaction> trans2(
5417 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5418 rv = trans2->Start(
5419 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5420 EXPECT_EQ(ERR_IO_PENDING, rv);
5421 data.RunFor(3);
5422 base::RunLoop().RunUntilIdle();
5424 // Read the server push body.
5425 std::string result2;
5426 ReadResult(trans2.get(), &data, &result2);
5427 // Read the response body.
5428 std::string result;
5429 ReadResult(trans, &data, &result);
5431 // Verify that the received push data is same as the expected push data.
5432 EXPECT_EQ(result2.compare(expected_push_result), 0)
5433 << "Received data: "
5434 << result2
5435 << "||||| Expected data: "
5436 << expected_push_result;
5438 // Verify the SYN_REPLY.
5439 // Copy the response info, because trans goes away.
5440 response = *trans->GetResponseInfo();
5441 response2 = *trans2->GetResponseInfo();
5443 VerifyStreamsClosed(helper);
5445 // Verify the SYN_REPLY.
5446 EXPECT_TRUE(response.headers.get() != NULL);
5447 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5449 // Verify the pushed stream.
5450 EXPECT_TRUE(response2.headers.get() != NULL);
5451 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5453 // Read the final EOF (which will close the session)
5454 data.RunFor(1);
5456 // Verify that we consumed all test data.
5457 EXPECT_TRUE(data.at_read_eof());
5458 EXPECT_TRUE(data.at_write_eof());
5461 // TODO(baranovich): HTTP 2 does not allow multiple HEADERS frames
5462 TEST_P(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) {
5463 // We push a stream and attempt to claim it before the headers come down.
5464 scoped_ptr<SpdyFrame> stream1_syn(
5465 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5466 scoped_ptr<SpdyFrame> stream1_body(
5467 spdy_util_.ConstructSpdyBodyFrame(1, true));
5468 MockWrite writes[] = {
5469 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5472 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5473 if (spdy_util_.spdy_version() < SPDY4) {
5474 // In SPDY4 PUSH_PROMISE headers won't show up in the response headers.
5475 (*initial_headers)["alpha"] = "beta";
5477 spdy_util_.AddUrlToHeaderBlock(
5478 "http://www.google.com/foo.dat", initial_headers.get());
5479 scoped_ptr<SpdyFrame> stream2_syn(
5480 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
5482 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5483 (*middle_headers)["hello"] = "bye";
5484 scoped_ptr<SpdyFrame> stream2_headers1(
5485 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(),
5486 false,
5488 LOWEST,
5489 HEADERS,
5490 CONTROL_FLAG_NONE,
5491 0));
5493 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5494 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5495 if (spdy_util_.spdy_version() < SPDY4) {
5496 // SPDY4/HTTP2 eliminates use of the :version header.
5497 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5499 scoped_ptr<SpdyFrame> stream2_headers2(
5500 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5501 false,
5503 LOWEST,
5504 HEADERS,
5505 CONTROL_FLAG_NONE,
5506 0));
5508 scoped_ptr<SpdyFrame>
5509 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5510 const char kPushedData[] = "pushed";
5511 scoped_ptr<SpdyFrame> stream2_body(
5512 spdy_util_.ConstructSpdyBodyFrame(
5513 2, kPushedData, strlen(kPushedData), true));
5514 MockRead reads[] = {
5515 CreateMockRead(*stream1_reply, 1),
5516 CreateMockRead(*stream2_syn, 2),
5517 CreateMockRead(*stream1_body, 3),
5518 CreateMockRead(*stream2_headers1, 4),
5519 CreateMockRead(*stream2_headers2, 5),
5520 CreateMockRead(*stream2_body, 6),
5521 MockRead(ASYNC, 0, 7), // EOF
5524 HttpResponseInfo response;
5525 HttpResponseInfo response2;
5526 std::string expected_push_result("pushed");
5527 DeterministicSocketData data(reads, arraysize(reads),
5528 writes, arraysize(writes));
5530 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5531 BoundNetLog(), GetParam(), NULL);
5532 helper.SetDeterministic();
5533 helper.AddDeterministicData(&data);
5534 helper.RunPreTestSetup();
5536 HttpNetworkTransaction* trans = helper.trans();
5538 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5539 // the first HEADERS frame, and the body of the primary stream, but before
5540 // we've received the final HEADERS for the pushed stream.
5541 data.SetStop(4);
5543 // Start the transaction.
5544 TestCompletionCallback callback;
5545 int rv = trans->Start(
5546 &CreateGetRequest(), callback.callback(), BoundNetLog());
5547 EXPECT_EQ(ERR_IO_PENDING, rv);
5548 data.Run();
5549 rv = callback.WaitForResult();
5550 EXPECT_EQ(0, rv);
5552 // Request the pushed path. At this point, we've received the push, but the
5553 // headers are not yet complete.
5554 scoped_ptr<HttpNetworkTransaction> trans2(
5555 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5556 rv = trans2->Start(
5557 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5558 EXPECT_EQ(ERR_IO_PENDING, rv);
5559 data.RunFor(3);
5560 base::RunLoop().RunUntilIdle();
5562 // Read the server push body.
5563 std::string result2;
5564 ReadResult(trans2.get(), &data, &result2);
5565 // Read the response body.
5566 std::string result;
5567 ReadResult(trans, &data, &result);
5569 // Verify that the received push data is same as the expected push data.
5570 EXPECT_EQ(expected_push_result, result2);
5572 // Verify the SYN_REPLY.
5573 // Copy the response info, because trans goes away.
5574 response = *trans->GetResponseInfo();
5575 response2 = *trans2->GetResponseInfo();
5577 VerifyStreamsClosed(helper);
5579 // Verify the SYN_REPLY.
5580 EXPECT_TRUE(response.headers.get() != NULL);
5581 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5583 // Verify the pushed stream.
5584 EXPECT_TRUE(response2.headers.get() != NULL);
5585 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5587 // Verify we got all the headers from all header blocks.
5588 if (spdy_util_.spdy_version() < SPDY4)
5589 EXPECT_TRUE(response2.headers->HasHeaderValue("alpha", "beta"));
5590 EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye"));
5591 EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200"));
5593 // Read the final EOF (which will close the session)
5594 data.RunFor(1);
5596 // Verify that we consumed all test data.
5597 EXPECT_TRUE(data.at_read_eof());
5598 EXPECT_TRUE(data.at_write_eof());
5601 TEST_P(SpdyNetworkTransactionTest, ServerPushWithNoStatusHeaderFrames) {
5602 // We push a stream and attempt to claim it before the headers come down.
5603 scoped_ptr<SpdyFrame> stream1_syn(
5604 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5605 scoped_ptr<SpdyFrame> stream1_body(
5606 spdy_util_.ConstructSpdyBodyFrame(1, true));
5607 MockWrite writes[] = {
5608 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5611 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5612 spdy_util_.AddUrlToHeaderBlock(
5613 "http://www.google.com/foo.dat", initial_headers.get());
5614 scoped_ptr<SpdyFrame> stream2_syn(
5615 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
5617 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5618 (*middle_headers)["hello"] = "bye";
5619 scoped_ptr<SpdyFrame> stream2_headers1(
5620 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(),
5621 false,
5623 LOWEST,
5624 HEADERS,
5625 CONTROL_FLAG_NONE,
5626 0));
5628 scoped_ptr<SpdyFrame>
5629 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5630 const char kPushedData[] = "pushed";
5631 scoped_ptr<SpdyFrame> stream2_body(
5632 spdy_util_.ConstructSpdyBodyFrame(
5633 2, kPushedData, strlen(kPushedData), true));
5634 MockRead reads[] = {
5635 CreateMockRead(*stream1_reply, 1),
5636 CreateMockRead(*stream2_syn, 2),
5637 CreateMockRead(*stream1_body, 3),
5638 CreateMockRead(*stream2_headers1, 4),
5639 CreateMockRead(*stream2_body, 5),
5640 MockRead(ASYNC, 0, 6), // EOF
5643 DeterministicSocketData data(reads, arraysize(reads),
5644 writes, arraysize(writes));
5646 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5647 BoundNetLog(), GetParam(), NULL);
5648 helper.SetDeterministic();
5649 helper.AddDeterministicData(&data);
5650 helper.RunPreTestSetup();
5652 HttpNetworkTransaction* trans = helper.trans();
5654 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5655 // the first HEADERS frame, and the body of the primary stream, but before
5656 // we've received the final HEADERS for the pushed stream.
5657 data.SetStop(4);
5659 // Start the transaction.
5660 TestCompletionCallback callback;
5661 int rv = trans->Start(
5662 &CreateGetRequest(), callback.callback(), BoundNetLog());
5663 EXPECT_EQ(ERR_IO_PENDING, rv);
5664 data.Run();
5665 rv = callback.WaitForResult();
5666 EXPECT_EQ(0, rv);
5668 // Request the pushed path. At this point, we've received the push, but the
5669 // headers are not yet complete.
5670 scoped_ptr<HttpNetworkTransaction> trans2(
5671 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5672 rv = trans2->Start(
5673 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5674 EXPECT_EQ(ERR_IO_PENDING, rv);
5675 data.RunFor(2);
5676 base::RunLoop().RunUntilIdle();
5678 // Read the server push body.
5679 std::string result2;
5680 ReadResult(trans2.get(), &data, &result2);
5681 // Read the response body.
5682 std::string result;
5683 ReadResult(trans, &data, &result);
5684 EXPECT_EQ("hello!", result);
5686 // Verify that we haven't received any push data.
5687 EXPECT_EQ("", result2);
5689 // Verify the SYN_REPLY.
5690 // Copy the response info, because trans goes away.
5691 HttpResponseInfo response = *trans->GetResponseInfo();
5692 ASSERT_TRUE(trans2->GetResponseInfo() == NULL);
5694 VerifyStreamsClosed(helper);
5696 // Verify the SYN_REPLY.
5697 EXPECT_TRUE(response.headers.get() != NULL);
5698 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5700 // Read the final EOF (which will close the session).
5701 data.RunFor(1);
5703 // Verify that we consumed all test data.
5704 EXPECT_TRUE(data.at_read_eof());
5705 EXPECT_TRUE(data.at_write_eof());
5708 TEST_P(SpdyNetworkTransactionTest, SynReplyWithHeaders) {
5709 scoped_ptr<SpdyFrame> req(
5710 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5711 scoped_ptr<SpdyFrame> rst(
5712 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
5713 MockWrite writes[] = {
5714 CreateMockWrite(*req), CreateMockWrite(*rst),
5717 scoped_ptr<SpdyFrame> stream1_reply(
5718 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5720 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5721 (*late_headers)["hello"] = "bye";
5722 scoped_ptr<SpdyFrame> stream1_headers(
5723 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5724 false,
5726 LOWEST,
5727 HEADERS,
5728 CONTROL_FLAG_NONE,
5729 0));
5730 scoped_ptr<SpdyFrame> stream1_body(
5731 spdy_util_.ConstructSpdyBodyFrame(1, true));
5732 MockRead reads[] = {
5733 CreateMockRead(*stream1_reply),
5734 CreateMockRead(*stream1_headers),
5735 CreateMockRead(*stream1_body),
5736 MockRead(ASYNC, 0, 0) // EOF
5739 DelayedSocketData data(1, reads, arraysize(reads),
5740 writes, arraysize(writes));
5741 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5742 BoundNetLog(), GetParam(), NULL);
5743 helper.RunToCompletion(&data);
5744 TransactionHelperResult out = helper.output();
5745 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
5748 TEST_P(SpdyNetworkTransactionTest, SynReplyWithLateHeaders) {
5749 scoped_ptr<SpdyFrame> req(
5750 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5751 scoped_ptr<SpdyFrame> rst(
5752 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
5753 MockWrite writes[] = {
5754 CreateMockWrite(*req),
5755 CreateMockWrite(*rst),
5758 scoped_ptr<SpdyFrame> stream1_reply(
5759 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5761 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5762 (*late_headers)["hello"] = "bye";
5763 scoped_ptr<SpdyFrame> stream1_headers(
5764 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5765 false,
5767 LOWEST,
5768 HEADERS,
5769 CONTROL_FLAG_NONE,
5770 0));
5771 scoped_ptr<SpdyFrame> stream1_body(
5772 spdy_util_.ConstructSpdyBodyFrame(1, false));
5773 scoped_ptr<SpdyFrame> stream1_body2(
5774 spdy_util_.ConstructSpdyBodyFrame(1, true));
5775 MockRead reads[] = {
5776 CreateMockRead(*stream1_reply),
5777 CreateMockRead(*stream1_body),
5778 CreateMockRead(*stream1_headers),
5779 CreateMockRead(*stream1_body2),
5780 MockRead(ASYNC, 0, 0) // EOF
5783 DelayedSocketData data(1, reads, arraysize(reads),
5784 writes, arraysize(writes));
5785 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5786 BoundNetLog(), GetParam(), NULL);
5787 helper.RunToCompletion(&data);
5788 TransactionHelperResult out = helper.output();
5789 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
5792 TEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
5793 // In this test we want to verify that we can't accidentally push content
5794 // which can't be pushed by this content server.
5795 // This test assumes that:
5796 // - if we're requesting http://www.foo.com/barbaz
5797 // - the browser has made a connection to "www.foo.com".
5799 // A list of the URL to fetch, followed by the URL being pushed.
5800 static const char* const kTestCases[] = {
5801 "http://www.google.com/foo.html",
5802 "http://www.google.com:81/foo.js", // Bad port
5804 "http://www.google.com/foo.html",
5805 "https://www.google.com/foo.js", // Bad protocol
5807 "http://www.google.com/foo.html",
5808 "ftp://www.google.com/foo.js", // Invalid Protocol
5810 "http://www.google.com/foo.html",
5811 "http://blat.www.google.com/foo.js", // Cross subdomain
5813 "http://www.google.com/foo.html",
5814 "http://www.foo.com/foo.js", // Cross domain
5817 for (size_t index = 0; index < arraysize(kTestCases); index += 2) {
5818 const char* url_to_fetch = kTestCases[index];
5819 const char* url_to_push = kTestCases[index + 1];
5821 scoped_ptr<SpdyFrame> stream1_syn(
5822 spdy_util_.ConstructSpdyGet(url_to_fetch, false, 1, LOWEST));
5823 scoped_ptr<SpdyFrame> stream1_body(
5824 spdy_util_.ConstructSpdyBodyFrame(1, true));
5825 scoped_ptr<SpdyFrame> push_rst(
5826 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
5827 MockWrite writes[] = {
5828 CreateMockWrite(*stream1_syn, 1),
5829 CreateMockWrite(*push_rst, 4),
5832 scoped_ptr<SpdyFrame>
5833 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5834 scoped_ptr<SpdyFrame>
5835 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
5839 url_to_push));
5840 const char kPushedData[] = "pushed";
5841 scoped_ptr<SpdyFrame> stream2_body(
5842 spdy_util_.ConstructSpdyBodyFrame(
5843 2, kPushedData, strlen(kPushedData), true));
5844 scoped_ptr<SpdyFrame> rst(
5845 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
5847 MockRead reads[] = {
5848 CreateMockRead(*stream1_reply, 2),
5849 CreateMockRead(*stream2_syn, 3),
5850 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
5851 CreateMockRead(*stream2_body, 6),
5852 MockRead(ASYNC, ERR_IO_PENDING, 7), // Force a pause
5855 HttpResponseInfo response;
5856 OrderedSocketData data(reads, arraysize(reads),
5857 writes, arraysize(writes));
5859 HttpRequestInfo request;
5860 request.method = "GET";
5861 request.url = GURL(url_to_fetch);
5862 request.load_flags = 0;
5864 // Enable cross-origin push. Since we are not using a proxy, this should
5865 // not actually enable cross-origin SPDY push.
5866 scoped_ptr<SpdySessionDependencies> session_deps(
5867 CreateSpdySessionDependencies(GetParam()));
5868 session_deps->trusted_spdy_proxy = "123.45.67.89:8080";
5869 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5870 BoundNetLog(), GetParam(),
5871 session_deps.release());
5872 helper.RunPreTestSetup();
5873 helper.AddData(&data);
5875 HttpNetworkTransaction* trans = helper.trans();
5877 // Start the transaction with basic parameters.
5878 TestCompletionCallback callback;
5880 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5881 EXPECT_EQ(ERR_IO_PENDING, rv);
5882 rv = callback.WaitForResult();
5884 // Read the response body.
5885 std::string result;
5886 ReadResult(trans, &data, &result);
5888 // Verify that we consumed all test data.
5889 EXPECT_TRUE(data.at_read_eof());
5890 EXPECT_TRUE(data.at_write_eof());
5892 // Verify the SYN_REPLY.
5893 // Copy the response info, because trans goes away.
5894 response = *trans->GetResponseInfo();
5896 VerifyStreamsClosed(helper);
5898 // Verify the SYN_REPLY.
5899 EXPECT_TRUE(response.headers.get() != NULL);
5900 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5904 TEST_P(SpdyNetworkTransactionTest, RetryAfterRefused) {
5905 // Construct the request.
5906 scoped_ptr<SpdyFrame> req(
5907 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5908 scoped_ptr<SpdyFrame> req2(
5909 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
5910 MockWrite writes[] = {
5911 CreateMockWrite(*req, 1),
5912 CreateMockWrite(*req2, 3),
5915 scoped_ptr<SpdyFrame> refused(
5916 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
5917 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5918 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(3, true));
5919 MockRead reads[] = {
5920 CreateMockRead(*refused, 2),
5921 CreateMockRead(*resp, 4),
5922 CreateMockRead(*body, 5),
5923 MockRead(ASYNC, 0, 6) // EOF
5926 OrderedSocketData data(reads, arraysize(reads),
5927 writes, arraysize(writes));
5928 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5929 BoundNetLog(), GetParam(), NULL);
5931 helper.RunPreTestSetup();
5932 helper.AddData(&data);
5934 HttpNetworkTransaction* trans = helper.trans();
5936 // Start the transaction with basic parameters.
5937 TestCompletionCallback callback;
5938 int rv = trans->Start(
5939 &CreateGetRequest(), callback.callback(), BoundNetLog());
5940 EXPECT_EQ(ERR_IO_PENDING, rv);
5941 rv = callback.WaitForResult();
5942 EXPECT_EQ(OK, rv);
5944 // Verify that we consumed all test data.
5945 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
5946 << data.read_count()
5947 << " Read index: "
5948 << data.read_index();
5949 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
5950 << data.write_count()
5951 << " Write index: "
5952 << data.write_index();
5954 // Verify the SYN_REPLY.
5955 HttpResponseInfo response = *trans->GetResponseInfo();
5956 EXPECT_TRUE(response.headers.get() != NULL);
5957 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5960 TEST_P(SpdyNetworkTransactionTest, OutOfOrderSynStream) {
5961 // This first request will start to establish the SpdySession.
5962 // Then we will start the second (MEDIUM priority) and then third
5963 // (HIGHEST priority) request in such a way that the third will actually
5964 // start before the second, causing the second to be numbered differently
5965 // than the order they were created.
5966 scoped_ptr<SpdyFrame> req1(
5967 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5968 scoped_ptr<SpdyFrame> req2(
5969 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, HIGHEST, true));
5970 scoped_ptr<SpdyFrame> req3(
5971 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, MEDIUM, true));
5972 MockWrite writes[] = {
5973 CreateMockWrite(*req1, 0),
5974 CreateMockWrite(*req2, 3),
5975 CreateMockWrite(*req3, 4),
5978 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5979 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
5980 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5981 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
5982 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
5983 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
5984 MockRead reads[] = {
5985 CreateMockRead(*resp1, 1),
5986 CreateMockRead(*body1, 2),
5987 CreateMockRead(*resp2, 5),
5988 CreateMockRead(*body2, 6),
5989 CreateMockRead(*resp3, 7),
5990 CreateMockRead(*body3, 8),
5991 MockRead(ASYNC, 0, 9) // EOF
5994 DeterministicSocketData data(reads, arraysize(reads),
5995 writes, arraysize(writes));
5996 NormalSpdyTransactionHelper helper(CreateGetRequest(), LOWEST,
5997 BoundNetLog(), GetParam(), NULL);
5998 helper.SetDeterministic();
5999 helper.RunPreTestSetup();
6000 helper.AddDeterministicData(&data);
6002 // Start the first transaction to set up the SpdySession
6003 HttpNetworkTransaction* trans = helper.trans();
6004 TestCompletionCallback callback;
6005 HttpRequestInfo info1 = CreateGetRequest();
6006 int rv = trans->Start(&info1, callback.callback(), BoundNetLog());
6007 EXPECT_EQ(ERR_IO_PENDING, rv);
6009 // Run the message loop, but do not allow the write to complete.
6010 // This leaves the SpdySession with a write pending, which prevents
6011 // SpdySession from attempting subsequent writes until this write completes.
6012 base::RunLoop().RunUntilIdle();
6014 // Now, start both new transactions
6015 HttpRequestInfo info2 = CreateGetRequest();
6016 TestCompletionCallback callback2;
6017 scoped_ptr<HttpNetworkTransaction> trans2(
6018 new HttpNetworkTransaction(MEDIUM, helper.session().get()));
6019 rv = trans2->Start(&info2, callback2.callback(), BoundNetLog());
6020 EXPECT_EQ(ERR_IO_PENDING, rv);
6021 base::RunLoop().RunUntilIdle();
6023 HttpRequestInfo info3 = CreateGetRequest();
6024 TestCompletionCallback callback3;
6025 scoped_ptr<HttpNetworkTransaction> trans3(
6026 new HttpNetworkTransaction(HIGHEST, helper.session().get()));
6027 rv = trans3->Start(&info3, callback3.callback(), BoundNetLog());
6028 EXPECT_EQ(ERR_IO_PENDING, rv);
6029 base::RunLoop().RunUntilIdle();
6031 // We now have two SYN_STREAM frames queued up which will be
6032 // dequeued only once the first write completes, which we
6033 // now allow to happen.
6034 data.RunFor(2);
6035 EXPECT_EQ(OK, callback.WaitForResult());
6037 // And now we can allow everything else to run to completion.
6038 data.SetStop(10);
6039 data.Run();
6040 EXPECT_EQ(OK, callback2.WaitForResult());
6041 EXPECT_EQ(OK, callback3.WaitForResult());
6043 helper.VerifyDataConsumed();
6046 // The tests below are only for SPDY/3 and above.
6048 // Test that sent data frames and received WINDOW_UPDATE frames change
6049 // the send_window_size_ correctly.
6051 // WINDOW_UPDATE is different than most other frames in that it can arrive
6052 // while the client is still sending the request body. In order to enforce
6053 // this scenario, we feed a couple of dummy frames and give a delay of 0 to
6054 // socket data provider, so that initial read that is done as soon as the
6055 // stream is created, succeeds and schedules another read. This way reads
6056 // and writes are interleaved; after doing a full frame write, SpdyStream
6057 // will break out of DoLoop and will read and process a WINDOW_UPDATE.
6058 // Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
6059 // since request has not been completely written, therefore we feed
6060 // enough number of WINDOW_UPDATEs to finish the first read and cause a
6061 // write, leading to a complete write of request body; after that we send
6062 // a reply with a body, to cause a graceful shutdown.
6064 // TODO(agayev): develop a socket data provider where both, reads and
6065 // writes are ordered so that writing tests like these are easy and rewrite
6066 // all these tests using it. Right now we are working around the
6067 // limitations as described above and it's not deterministic, tests may
6068 // fail under specific circumstances.
6069 TEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) {
6070 static int kFrameCount = 2;
6071 scoped_ptr<std::string> content(
6072 new std::string(kMaxSpdyFrameChunkSize, 'a'));
6073 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6074 kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
6075 scoped_ptr<SpdyFrame> body(
6076 spdy_util_.ConstructSpdyBodyFrame(
6077 1, content->c_str(), content->size(), false));
6078 scoped_ptr<SpdyFrame> body_end(
6079 spdy_util_.ConstructSpdyBodyFrame(
6080 1, content->c_str(), content->size(), true));
6082 MockWrite writes[] = {
6083 CreateMockWrite(*req, 0),
6084 CreateMockWrite(*body, 1),
6085 CreateMockWrite(*body_end, 2),
6088 static const int32 kDeltaWindowSize = 0xff;
6089 static const int kDeltaCount = 4;
6090 scoped_ptr<SpdyFrame> window_update(
6091 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
6092 scoped_ptr<SpdyFrame> window_update_dummy(
6093 spdy_util_.ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
6094 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6095 MockRead reads[] = {
6096 CreateMockRead(*window_update_dummy, 3),
6097 CreateMockRead(*window_update_dummy, 4),
6098 CreateMockRead(*window_update_dummy, 5),
6099 CreateMockRead(*window_update, 6), // Four updates, therefore window
6100 CreateMockRead(*window_update, 7), // size should increase by
6101 CreateMockRead(*window_update, 8), // kDeltaWindowSize * 4
6102 CreateMockRead(*window_update, 9),
6103 CreateMockRead(*resp, 10),
6104 CreateMockRead(*body_end, 11),
6105 MockRead(ASYNC, 0, 0, 12) // EOF
6108 DeterministicSocketData data(reads, arraysize(reads),
6109 writes, arraysize(writes));
6111 ScopedVector<UploadElementReader> element_readers;
6112 for (int i = 0; i < kFrameCount; ++i) {
6113 element_readers.push_back(
6114 new UploadBytesElementReader(content->c_str(), content->size()));
6116 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
6118 // Setup the request
6119 HttpRequestInfo request;
6120 request.method = "POST";
6121 request.url = GURL(kDefaultURL);
6122 request.upload_data_stream = &upload_data_stream;
6124 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6125 BoundNetLog(), GetParam(), NULL);
6126 helper.SetDeterministic();
6127 helper.AddDeterministicData(&data);
6128 helper.RunPreTestSetup();
6130 HttpNetworkTransaction* trans = helper.trans();
6132 TestCompletionCallback callback;
6133 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6135 EXPECT_EQ(ERR_IO_PENDING, rv);
6137 data.RunFor(11);
6139 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6140 ASSERT_TRUE(stream != NULL);
6141 ASSERT_TRUE(stream->stream() != NULL);
6142 EXPECT_EQ(
6143 static_cast<int>(SpdySession::GetInitialWindowSize(GetParam().protocol)) +
6144 kDeltaWindowSize * kDeltaCount - kMaxSpdyFrameChunkSize * kFrameCount,
6145 stream->stream()->send_window_size());
6147 data.RunFor(1);
6149 rv = callback.WaitForResult();
6150 EXPECT_EQ(OK, rv);
6152 helper.VerifyDataConsumed();
6155 // Test that received data frames and sent WINDOW_UPDATE frames change
6156 // the recv_window_size_ correctly.
6157 TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) {
6158 const int32 initial_window_size =
6159 SpdySession::GetInitialWindowSize(GetParam().protocol);
6160 // Amount of body required to trigger a sent window update.
6161 const size_t kTargetSize = initial_window_size / 2 + 1;
6163 scoped_ptr<SpdyFrame> req(
6164 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
6165 scoped_ptr<SpdyFrame> session_window_update(
6166 spdy_util_.ConstructSpdyWindowUpdate(0, kTargetSize));
6167 scoped_ptr<SpdyFrame> window_update(
6168 spdy_util_.ConstructSpdyWindowUpdate(1, kTargetSize));
6170 std::vector<MockWrite> writes;
6171 writes.push_back(CreateMockWrite(*req));
6172 if (GetParam().protocol >= kProtoSPDY31)
6173 writes.push_back(CreateMockWrite(*session_window_update));
6174 writes.push_back(CreateMockWrite(*window_update));
6176 std::vector<MockRead> reads;
6177 scoped_ptr<SpdyFrame> resp(
6178 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6179 reads.push_back(CreateMockRead(*resp));
6181 ScopedVector<SpdyFrame> body_frames;
6182 const std::string body_data(4096, 'x');
6183 for (size_t remaining = kTargetSize; remaining != 0;) {
6184 size_t frame_size = std::min(remaining, body_data.size());
6185 body_frames.push_back(spdy_util_.ConstructSpdyBodyFrame(
6186 1, body_data.data(), frame_size, false));
6187 reads.push_back(CreateMockRead(*body_frames.back()));
6188 remaining -= frame_size;
6190 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, 0)); // Yield.
6192 DelayedSocketData data(1, vector_as_array(&reads), reads.size(),
6193 vector_as_array(&writes), writes.size());
6195 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
6196 BoundNetLog(), GetParam(), NULL);
6197 helper.AddData(&data);
6198 helper.RunPreTestSetup();
6199 HttpNetworkTransaction* trans = helper.trans();
6201 TestCompletionCallback callback;
6202 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6204 EXPECT_EQ(ERR_IO_PENDING, rv);
6205 rv = callback.WaitForResult();
6206 EXPECT_EQ(OK, rv);
6208 SpdyHttpStream* stream =
6209 static_cast<SpdyHttpStream*>(trans->stream_.get());
6210 ASSERT_TRUE(stream != NULL);
6211 ASSERT_TRUE(stream->stream() != NULL);
6213 // All data has been read, but not consumed. The window reflects this.
6214 EXPECT_EQ(static_cast<int>(initial_window_size - kTargetSize),
6215 stream->stream()->recv_window_size());
6217 const HttpResponseInfo* response = trans->GetResponseInfo();
6218 ASSERT_TRUE(response != NULL);
6219 ASSERT_TRUE(response->headers.get() != NULL);
6220 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6221 EXPECT_TRUE(response->was_fetched_via_spdy);
6223 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
6224 // size increased to default.
6225 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kTargetSize));
6226 EXPECT_EQ(static_cast<int>(kTargetSize),
6227 trans->Read(buf.get(), kTargetSize, CompletionCallback()));
6228 EXPECT_EQ(static_cast<int>(initial_window_size),
6229 stream->stream()->recv_window_size());
6230 EXPECT_THAT(base::StringPiece(buf->data(), kTargetSize), Each(Eq('x')));
6232 // Allow scheduled WINDOW_UPDATE frames to write.
6233 base::RunLoop().RunUntilIdle();
6234 helper.VerifyDataConsumed();
6237 // Test that WINDOW_UPDATE frame causing overflow is handled correctly.
6238 TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
6239 // Number of full frames we hope to write (but will not, used to
6240 // set content-length header correctly)
6241 static int kFrameCount = 3;
6243 scoped_ptr<std::string> content(
6244 new std::string(kMaxSpdyFrameChunkSize, 'a'));
6245 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6246 kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
6247 scoped_ptr<SpdyFrame> body(
6248 spdy_util_.ConstructSpdyBodyFrame(
6249 1, content->c_str(), content->size(), false));
6250 scoped_ptr<SpdyFrame> rst(
6251 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
6253 // We're not going to write a data frame with FIN, we'll receive a bad
6254 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
6255 MockWrite writes[] = {
6256 CreateMockWrite(*req, 0),
6257 CreateMockWrite(*body, 2),
6258 CreateMockWrite(*rst, 3),
6261 static const int32 kDeltaWindowSize = 0x7fffffff; // cause an overflow
6262 scoped_ptr<SpdyFrame> window_update(
6263 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
6264 MockRead reads[] = {
6265 CreateMockRead(*window_update, 1),
6266 MockRead(ASYNC, 0, 4) // EOF
6269 DeterministicSocketData data(reads, arraysize(reads),
6270 writes, arraysize(writes));
6272 ScopedVector<UploadElementReader> element_readers;
6273 for (int i = 0; i < kFrameCount; ++i) {
6274 element_readers.push_back(
6275 new UploadBytesElementReader(content->c_str(), content->size()));
6277 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
6279 // Setup the request
6280 HttpRequestInfo request;
6281 request.method = "POST";
6282 request.url = GURL("http://www.google.com/");
6283 request.upload_data_stream = &upload_data_stream;
6285 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6286 BoundNetLog(), GetParam(), NULL);
6287 helper.SetDeterministic();
6288 helper.RunPreTestSetup();
6289 helper.AddDeterministicData(&data);
6290 HttpNetworkTransaction* trans = helper.trans();
6292 TestCompletionCallback callback;
6293 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6294 ASSERT_EQ(ERR_IO_PENDING, rv);
6296 data.RunFor(5);
6297 ASSERT_TRUE(callback.have_result());
6298 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, callback.WaitForResult());
6299 helper.VerifyDataConsumed();
6302 // Test that after hitting a send window size of 0, the write process
6303 // stalls and upon receiving WINDOW_UPDATE frame write resumes.
6305 // This test constructs a POST request followed by enough data frames
6306 // containing 'a' that would make the window size 0, followed by another
6307 // data frame containing default content (which is "hello!") and this frame
6308 // also contains a FIN flag. DelayedSocketData is used to enforce all
6309 // writes go through before a read could happen. However, the last frame
6310 // ("hello!") is not supposed to go through since by the time its turn
6311 // arrives, window size is 0. At this point MessageLoop::Run() called via
6312 // callback would block. Therefore we call MessageLoop::RunUntilIdle()
6313 // which returns after performing all possible writes. We use DCHECKS to
6314 // ensure that last data frame is still there and stream has stalled.
6315 // After that, next read is artifically enforced, which causes a
6316 // WINDOW_UPDATE to be read and I/O process resumes.
6317 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) {
6318 const int32 initial_window_size =
6319 SpdySession::GetInitialWindowSize(GetParam().protocol);
6320 // Number of frames we need to send to zero out the window size: data
6321 // frames plus SYN_STREAM plus the last data frame; also we need another
6322 // data frame that we will send once the WINDOW_UPDATE is received,
6323 // therefore +3.
6324 size_t num_writes = initial_window_size / kMaxSpdyFrameChunkSize + 3;
6326 // Calculate last frame's size; 0 size data frame is legal.
6327 size_t last_frame_size = initial_window_size % kMaxSpdyFrameChunkSize;
6329 // Construct content for a data frame of maximum size.
6330 std::string content(kMaxSpdyFrameChunkSize, 'a');
6332 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6333 kRequestUrl, 1, initial_window_size + kUploadDataSize, LOWEST, NULL, 0));
6335 // Full frames.
6336 scoped_ptr<SpdyFrame> body1(
6337 spdy_util_.ConstructSpdyBodyFrame(
6338 1, content.c_str(), content.size(), false));
6340 // Last frame to zero out the window size.
6341 scoped_ptr<SpdyFrame> body2(
6342 spdy_util_.ConstructSpdyBodyFrame(
6343 1, content.c_str(), last_frame_size, false));
6345 // Data frame to be sent once WINDOW_UPDATE frame is received.
6346 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6348 // Fill in mock writes.
6349 scoped_ptr<MockWrite[]> writes(new MockWrite[num_writes]);
6350 size_t i = 0;
6351 writes[i] = CreateMockWrite(*req);
6352 for (i = 1; i < num_writes - 2; i++)
6353 writes[i] = CreateMockWrite(*body1);
6354 writes[i++] = CreateMockWrite(*body2);
6355 writes[i] = CreateMockWrite(*body3);
6357 // Construct read frame, give enough space to upload the rest of the
6358 // data.
6359 scoped_ptr<SpdyFrame> session_window_update(
6360 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6361 scoped_ptr<SpdyFrame> window_update(
6362 spdy_util_.ConstructSpdyWindowUpdate(1, kUploadDataSize));
6363 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6364 MockRead reads[] = {
6365 CreateMockRead(*session_window_update),
6366 CreateMockRead(*session_window_update),
6367 CreateMockRead(*window_update),
6368 CreateMockRead(*window_update),
6369 CreateMockRead(*reply),
6370 CreateMockRead(*body2),
6371 CreateMockRead(*body3),
6372 MockRead(ASYNC, 0, 0) // EOF
6375 // Skip the session window updates unless we're using SPDY/3.1 and
6376 // above.
6377 size_t read_offset = (GetParam().protocol >= kProtoSPDY31) ? 0 : 2;
6378 size_t num_reads = arraysize(reads) - read_offset;
6380 // Force all writes to happen before any read, last write will not
6381 // actually queue a frame, due to window size being 0.
6382 DelayedSocketData data(num_writes, reads + read_offset, num_reads,
6383 writes.get(), num_writes);
6385 ScopedVector<UploadElementReader> element_readers;
6386 std::string upload_data_string(initial_window_size, 'a');
6387 upload_data_string.append(kUploadData, kUploadDataSize);
6388 element_readers.push_back(new UploadBytesElementReader(
6389 upload_data_string.c_str(), upload_data_string.size()));
6390 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
6392 HttpRequestInfo request;
6393 request.method = "POST";
6394 request.url = GURL("http://www.google.com/");
6395 request.upload_data_stream = &upload_data_stream;
6396 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6397 BoundNetLog(), GetParam(), NULL);
6398 helper.AddData(&data);
6399 helper.RunPreTestSetup();
6401 HttpNetworkTransaction* trans = helper.trans();
6403 TestCompletionCallback callback;
6404 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6405 EXPECT_EQ(ERR_IO_PENDING, rv);
6407 base::RunLoop().RunUntilIdle(); // Write as much as we can.
6409 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6410 ASSERT_TRUE(stream != NULL);
6411 ASSERT_TRUE(stream->stream() != NULL);
6412 EXPECT_EQ(0, stream->stream()->send_window_size());
6413 // All the body data should have been read.
6414 // TODO(satorux): This is because of the weirdness in reading the request
6415 // body in OnSendBodyComplete(). See crbug.com/113107.
6416 EXPECT_TRUE(upload_data_stream.IsEOF());
6417 // But the body is not yet fully sent (kUploadData is not yet sent)
6418 // since we're send-stalled.
6419 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6421 data.ForceNextRead(); // Read in WINDOW_UPDATE frame.
6422 rv = callback.WaitForResult();
6423 helper.VerifyDataConsumed();
6426 // Test we correctly handle the case where the SETTINGS frame results in
6427 // unstalling the send window.
6428 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
6429 const int32 initial_window_size =
6430 SpdySession::GetInitialWindowSize(GetParam().protocol);
6432 // Number of frames we need to send to zero out the window size: data
6433 // frames plus SYN_STREAM plus the last data frame; also we need another
6434 // data frame that we will send once the SETTING is received, therefore +3.
6435 size_t num_writes = initial_window_size / kMaxSpdyFrameChunkSize + 3;
6437 // Calculate last frame's size; 0 size data frame is legal.
6438 size_t last_frame_size = initial_window_size % kMaxSpdyFrameChunkSize;
6440 // Construct content for a data frame of maximum size.
6441 std::string content(kMaxSpdyFrameChunkSize, 'a');
6443 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6444 kRequestUrl, 1, initial_window_size + kUploadDataSize, LOWEST, NULL, 0));
6446 // Full frames.
6447 scoped_ptr<SpdyFrame> body1(
6448 spdy_util_.ConstructSpdyBodyFrame(
6449 1, content.c_str(), content.size(), false));
6451 // Last frame to zero out the window size.
6452 scoped_ptr<SpdyFrame> body2(
6453 spdy_util_.ConstructSpdyBodyFrame(
6454 1, content.c_str(), last_frame_size, false));
6456 // Data frame to be sent once SETTINGS frame is received.
6457 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6459 // Fill in mock reads/writes.
6460 std::vector<MockRead> reads;
6461 std::vector<MockWrite> writes;
6462 size_t i = 0;
6463 writes.push_back(CreateMockWrite(*req, i++));
6464 while (i < num_writes - 2)
6465 writes.push_back(CreateMockWrite(*body1, i++));
6466 writes.push_back(CreateMockWrite(*body2, i++));
6468 // Construct read frame for SETTINGS that gives enough space to upload the
6469 // rest of the data.
6470 SettingsMap settings;
6471 settings[SETTINGS_INITIAL_WINDOW_SIZE] =
6472 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_window_size * 2);
6473 scoped_ptr<SpdyFrame> settings_frame_large(
6474 spdy_util_.ConstructSpdySettings(settings));
6476 reads.push_back(CreateMockRead(*settings_frame_large, i++));
6478 scoped_ptr<SpdyFrame> session_window_update(
6479 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6480 if (GetParam().protocol >= kProtoSPDY31)
6481 reads.push_back(CreateMockRead(*session_window_update, i++));
6483 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
6484 writes.push_back(CreateMockWrite(*settings_ack, i++));
6486 writes.push_back(CreateMockWrite(*body3, i++));
6488 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6489 reads.push_back(CreateMockRead(*reply, i++));
6490 reads.push_back(CreateMockRead(*body2, i++));
6491 reads.push_back(CreateMockRead(*body3, i++));
6492 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6494 // Force all writes to happen before any read, last write will not
6495 // actually queue a frame, due to window size being 0.
6496 DeterministicSocketData data(vector_as_array(&reads), reads.size(),
6497 vector_as_array(&writes), writes.size());
6499 ScopedVector<UploadElementReader> element_readers;
6500 std::string upload_data_string(initial_window_size, 'a');
6501 upload_data_string.append(kUploadData, kUploadDataSize);
6502 element_readers.push_back(new UploadBytesElementReader(
6503 upload_data_string.c_str(), upload_data_string.size()));
6504 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
6506 HttpRequestInfo request;
6507 request.method = "POST";
6508 request.url = GURL("http://www.google.com/");
6509 request.upload_data_stream = &upload_data_stream;
6510 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6511 BoundNetLog(), GetParam(), NULL);
6512 helper.SetDeterministic();
6513 helper.RunPreTestSetup();
6514 helper.AddDeterministicData(&data);
6516 HttpNetworkTransaction* trans = helper.trans();
6518 TestCompletionCallback callback;
6519 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6520 EXPECT_EQ(ERR_IO_PENDING, rv);
6522 data.RunFor(num_writes - 1); // Write as much as we can.
6524 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6525 ASSERT_TRUE(stream != NULL);
6526 ASSERT_TRUE(stream->stream() != NULL);
6527 EXPECT_EQ(0, stream->stream()->send_window_size());
6529 // All the body data should have been read.
6530 // TODO(satorux): This is because of the weirdness in reading the request
6531 // body in OnSendBodyComplete(). See crbug.com/113107.
6532 EXPECT_TRUE(upload_data_stream.IsEOF());
6533 // But the body is not yet fully sent (kUploadData is not yet sent)
6534 // since we're send-stalled.
6535 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6537 data.RunFor(7); // Read in SETTINGS frame to unstall.
6538 rv = callback.WaitForResult();
6539 helper.VerifyDataConsumed();
6540 // If stream is NULL, that means it was unstalled and closed.
6541 EXPECT_TRUE(stream->stream() == NULL);
6544 // Test we correctly handle the case where the SETTINGS frame results in a
6545 // negative send window size.
6546 TEST_P(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
6547 const int32 initial_window_size =
6548 SpdySession::GetInitialWindowSize(GetParam().protocol);
6549 // Number of frames we need to send to zero out the window size: data
6550 // frames plus SYN_STREAM plus the last data frame; also we need another
6551 // data frame that we will send once the SETTING is received, therefore +3.
6552 size_t num_writes = initial_window_size / kMaxSpdyFrameChunkSize + 3;
6554 // Calculate last frame's size; 0 size data frame is legal.
6555 size_t last_frame_size = initial_window_size % kMaxSpdyFrameChunkSize;
6557 // Construct content for a data frame of maximum size.
6558 std::string content(kMaxSpdyFrameChunkSize, 'a');
6560 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6561 kRequestUrl, 1, initial_window_size + kUploadDataSize, LOWEST, NULL, 0));
6563 // Full frames.
6564 scoped_ptr<SpdyFrame> body1(
6565 spdy_util_.ConstructSpdyBodyFrame(
6566 1, content.c_str(), content.size(), false));
6568 // Last frame to zero out the window size.
6569 scoped_ptr<SpdyFrame> body2(
6570 spdy_util_.ConstructSpdyBodyFrame(
6571 1, content.c_str(), last_frame_size, false));
6573 // Data frame to be sent once SETTINGS frame is received.
6574 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6576 // Fill in mock reads/writes.
6577 std::vector<MockRead> reads;
6578 std::vector<MockWrite> writes;
6579 size_t i = 0;
6580 writes.push_back(CreateMockWrite(*req, i++));
6581 while (i < num_writes - 2)
6582 writes.push_back(CreateMockWrite(*body1, i++));
6583 writes.push_back(CreateMockWrite(*body2, i++));
6585 // Construct read frame for SETTINGS that makes the send_window_size
6586 // negative.
6587 SettingsMap new_settings;
6588 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
6589 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_window_size / 2);
6590 scoped_ptr<SpdyFrame> settings_frame_small(
6591 spdy_util_.ConstructSpdySettings(new_settings));
6592 // Construct read frames for WINDOW_UPDATE that makes the send_window_size
6593 // positive.
6594 scoped_ptr<SpdyFrame> session_window_update_init_size(
6595 spdy_util_.ConstructSpdyWindowUpdate(0, initial_window_size));
6596 scoped_ptr<SpdyFrame> window_update_init_size(
6597 spdy_util_.ConstructSpdyWindowUpdate(1, initial_window_size));
6599 reads.push_back(CreateMockRead(*settings_frame_small, i++));
6600 reads.push_back(CreateMockRead(*session_window_update_init_size, i++));
6601 reads.push_back(CreateMockRead(*window_update_init_size, i++));
6603 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
6604 writes.push_back(CreateMockWrite(*settings_ack, i++));
6606 writes.push_back(CreateMockWrite(*body3, i++));
6608 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6609 reads.push_back(CreateMockRead(*reply, i++));
6610 reads.push_back(CreateMockRead(*body2, i++));
6611 reads.push_back(CreateMockRead(*body3, i++));
6612 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6614 // Force all writes to happen before any read, last write will not
6615 // actually queue a frame, due to window size being 0.
6616 DeterministicSocketData data(vector_as_array(&reads), reads.size(),
6617 vector_as_array(&writes), writes.size());
6619 ScopedVector<UploadElementReader> element_readers;
6620 std::string upload_data_string(initial_window_size, 'a');
6621 upload_data_string.append(kUploadData, kUploadDataSize);
6622 element_readers.push_back(new UploadBytesElementReader(
6623 upload_data_string.c_str(), upload_data_string.size()));
6624 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
6626 HttpRequestInfo request;
6627 request.method = "POST";
6628 request.url = GURL("http://www.google.com/");
6629 request.upload_data_stream = &upload_data_stream;
6630 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6631 BoundNetLog(), GetParam(), NULL);
6632 helper.SetDeterministic();
6633 helper.RunPreTestSetup();
6634 helper.AddDeterministicData(&data);
6636 HttpNetworkTransaction* trans = helper.trans();
6638 TestCompletionCallback callback;
6639 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6640 EXPECT_EQ(ERR_IO_PENDING, rv);
6642 data.RunFor(num_writes - 1); // Write as much as we can.
6644 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6645 ASSERT_TRUE(stream != NULL);
6646 ASSERT_TRUE(stream->stream() != NULL);
6647 EXPECT_EQ(0, stream->stream()->send_window_size());
6649 // All the body data should have been read.
6650 // TODO(satorux): This is because of the weirdness in reading the request
6651 // body in OnSendBodyComplete(). See crbug.com/113107.
6652 EXPECT_TRUE(upload_data_stream.IsEOF());
6653 // But the body is not yet fully sent (kUploadData is not yet sent)
6654 // since we're send-stalled.
6655 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6657 // Read in WINDOW_UPDATE or SETTINGS frame.
6658 data.RunFor((GetParam().protocol >= kProtoSPDY31) ? 9 : 8);
6659 rv = callback.WaitForResult();
6660 helper.VerifyDataConsumed();
6663 TEST_P(SpdyNetworkTransactionTest, GoAwayOnOddPushStreamId) {
6664 if (spdy_util_.spdy_version() < SPDY3)
6665 return;
6667 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
6668 spdy_util_.AddUrlToHeaderBlock("http://www.google.com/a.dat",
6669 push_headers.get());
6670 scoped_ptr<SpdyFrame> push(
6671 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 3, 1));
6672 MockRead reads[] = {CreateMockRead(*push, 1)};
6674 scoped_ptr<SpdyFrame> req(
6675 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
6676 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
6677 0, GOAWAY_PROTOCOL_ERROR, "Odd push stream id."));
6678 MockWrite writes[] = {
6679 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2),
6682 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
6683 NormalSpdyTransactionHelper helper(
6684 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6685 helper.RunToCompletion(&data);
6686 TransactionHelperResult out = helper.output();
6687 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
6690 TEST_P(SpdyNetworkTransactionTest,
6691 GoAwayOnPushStreamIdLesserOrEqualThanLastAccepted) {
6692 if (spdy_util_.spdy_version() < SPDY3)
6693 return;
6695 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
6696 NULL, 0, 4, 1, "http://www.google.com/a.dat"));
6697 scoped_ptr<SpdyHeaderBlock> push_b_headers(new SpdyHeaderBlock);
6698 spdy_util_.AddUrlToHeaderBlock("http://www.google.com/b.dat",
6699 push_b_headers.get());
6700 scoped_ptr<SpdyFrame> push_b(
6701 spdy_util_.ConstructInitialSpdyPushFrame(push_b_headers.Pass(), 2, 1));
6702 MockRead reads[] = {
6703 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
6706 scoped_ptr<SpdyFrame> req(
6707 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
6708 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
6710 GOAWAY_PROTOCOL_ERROR,
6711 "New push stream id must be greater than the last accepted."));
6712 MockWrite writes[] = {
6713 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 3),
6716 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
6717 NormalSpdyTransactionHelper helper(
6718 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6719 helper.RunToCompletion(&data);
6720 TransactionHelperResult out = helper.output();
6721 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
6724 class SpdyNetworkTransactionNoTLSUsageCheckTest
6725 : public SpdyNetworkTransactionTest {
6726 protected:
6727 void RunNoTLSUsageCheckTest(scoped_ptr<SSLSocketDataProvider> ssl_provider) {
6728 // Construct the request.
6729 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyGet(
6730 "https://www.google.com/", false, 1, LOWEST));
6731 MockWrite writes[] = {CreateMockWrite(*req)};
6733 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6734 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6735 MockRead reads[] = {
6736 CreateMockRead(*resp), CreateMockRead(*body),
6737 MockRead(ASYNC, 0, 0) // EOF
6740 DelayedSocketData data(
6741 1, reads, arraysize(reads), writes, arraysize(writes));
6742 HttpRequestInfo request;
6743 request.method = "GET";
6744 request.url = GURL("https://www.google.com/");
6745 NormalSpdyTransactionHelper helper(
6746 request, DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6747 helper.RunToCompletionWithSSLData(&data, ssl_provider.Pass());
6748 TransactionHelperResult out = helper.output();
6749 EXPECT_EQ(OK, out.rv);
6750 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
6751 EXPECT_EQ("hello!", out.response_data);
6755 //-----------------------------------------------------------------------------
6756 // All tests are run with three different connection types: SPDY after NPN
6757 // negotiation, SPDY without SSL, and SPDY with SSL.
6759 // TODO(akalin): Use ::testing::Combine() when we are able to use
6760 // <tr1/tuple>.
6761 INSTANTIATE_TEST_CASE_P(
6762 Spdy,
6763 SpdyNetworkTransactionNoTLSUsageCheckTest,
6764 ::testing::Values(SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNPN)));
6766 TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest, TLSVersionTooOld) {
6767 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6768 new SSLSocketDataProvider(ASYNC, OK));
6769 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6770 &ssl_provider->connection_status);
6772 RunNoTLSUsageCheckTest(ssl_provider.Pass());
6775 TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest, TLSCipherSuiteSucky) {
6776 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6777 new SSLSocketDataProvider(ASYNC, OK));
6778 // Set to TLS_RSA_WITH_NULL_MD5
6779 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider->connection_status);
6781 RunNoTLSUsageCheckTest(ssl_provider.Pass());
6784 class SpdyNetworkTransactionTLSUsageCheckTest
6785 : public SpdyNetworkTransactionTest {
6786 protected:
6787 void RunTLSUsageCheckTest(scoped_ptr<SSLSocketDataProvider> ssl_provider) {
6788 scoped_ptr<SpdyFrame> goaway(
6789 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_INADEQUATE_SECURITY, ""));
6790 MockWrite writes[] = {CreateMockWrite(*goaway)};
6792 DelayedSocketData data(1, NULL, 0, writes, arraysize(writes));
6793 HttpRequestInfo request;
6794 request.method = "GET";
6795 request.url = GURL("https://www.google.com/");
6796 NormalSpdyTransactionHelper helper(
6797 request, DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6798 helper.RunToCompletionWithSSLData(&data, ssl_provider.Pass());
6799 TransactionHelperResult out = helper.output();
6800 EXPECT_EQ(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY, out.rv);
6804 INSTANTIATE_TEST_CASE_P(
6805 Spdy,
6806 SpdyNetworkTransactionTLSUsageCheckTest,
6807 ::testing::Values(
6808 SpdyNetworkTransactionTestParams(kProtoSPDY4_14, SPDYNPN),
6809 SpdyNetworkTransactionTestParams(kProtoSPDY4_15, SPDYNPN)));
6811 TEST_P(SpdyNetworkTransactionTLSUsageCheckTest, TLSVersionTooOld) {
6812 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6813 new SSLSocketDataProvider(ASYNC, OK));
6814 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6815 &ssl_provider->connection_status);
6817 RunTLSUsageCheckTest(ssl_provider.Pass());
6820 TEST_P(SpdyNetworkTransactionTLSUsageCheckTest, TLSCipherSuiteSucky) {
6821 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6822 new SSLSocketDataProvider(ASYNC, OK));
6823 // Set to TLS_RSA_WITH_NULL_MD5
6824 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider->connection_status);
6826 RunTLSUsageCheckTest(ssl_provider.Pass());
6829 } // namespace net