Revert of Add support for escaped target names in isolate driver. (patchset #6 id...
[chromium-blink-merge.git] / net / spdy / spdy_network_transaction_unittest.cc
bloba79d76a8bfeda79de4db1cc1d6eda1dfa4ec46c8
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 const NetLog::EventType type =
3783 (GetParam().protocol <= kProtoSPDY31)
3784 ? net::NetLog::TYPE_HTTP2_SESSION_SYN_STREAM
3785 : net::NetLog::TYPE_HTTP2_SESSION_SEND_HEADERS;
3786 pos = net::ExpectLogContainsSomewhere(entries, 0, type,
3787 net::NetLog::PHASE_NONE);
3789 base::ListValue* header_list;
3790 ASSERT_TRUE(entries[pos].params.get());
3791 ASSERT_TRUE(entries[pos].params->GetList("headers", &header_list));
3793 std::vector<std::string> expected;
3794 expected.push_back(std::string(spdy_util_.GetHostKey()) + ": www.google.com");
3795 expected.push_back(std::string(spdy_util_.GetPathKey()) + ": /");
3796 expected.push_back(std::string(spdy_util_.GetSchemeKey()) + ": http");
3797 expected.push_back(std::string(spdy_util_.GetMethodKey()) + ": GET");
3798 expected.push_back("user-agent: Chrome");
3799 if (spdy_util_.spdy_version() < SPDY4) {
3800 // SPDY4/HTTP2 eliminates use of the :version header.
3801 expected.push_back(std::string(spdy_util_.GetVersionKey()) + ": HTTP/1.1");
3803 EXPECT_EQ(expected.size(), header_list->GetSize());
3804 for (std::vector<std::string>::const_iterator it = expected.begin();
3805 it != expected.end();
3806 ++it) {
3807 base::StringValue header(*it);
3808 EXPECT_NE(header_list->end(), header_list->Find(header)) <<
3809 "Header not found: " << *it;
3813 // Since we buffer the IO from the stream to the renderer, this test verifies
3814 // that when we read out the maximum amount of data (e.g. we received 50 bytes
3815 // on the network, but issued a Read for only 5 of those bytes) that the data
3816 // flow still works correctly.
3817 TEST_P(SpdyNetworkTransactionTest, BufferFull) {
3818 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3820 scoped_ptr<SpdyFrame> req(
3821 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3822 MockWrite writes[] = { CreateMockWrite(*req) };
3824 // 2 data frames in a single read.
3825 scoped_ptr<SpdyFrame> data_frame_1(
3826 framer.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE));
3827 scoped_ptr<SpdyFrame> data_frame_2(
3828 framer.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE));
3829 const SpdyFrame* data_frames[2] = {
3830 data_frame_1.get(),
3831 data_frame_2.get(),
3833 char combined_data_frames[100];
3834 int combined_data_frames_len =
3835 CombineFrames(data_frames, arraysize(data_frames),
3836 combined_data_frames, arraysize(combined_data_frames));
3837 scoped_ptr<SpdyFrame> last_frame(
3838 framer.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN));
3840 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3841 MockRead reads[] = {
3842 CreateMockRead(*resp),
3843 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3844 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
3845 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3846 CreateMockRead(*last_frame),
3847 MockRead(ASYNC, 0, 0) // EOF
3850 DelayedSocketData data(1, reads, arraysize(reads),
3851 writes, arraysize(writes));
3853 TestCompletionCallback callback;
3855 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3856 BoundNetLog(), GetParam(), NULL);
3857 helper.RunPreTestSetup();
3858 helper.AddData(&data);
3859 HttpNetworkTransaction* trans = helper.trans();
3860 int rv = trans->Start(
3861 &CreateGetRequest(), callback.callback(), BoundNetLog());
3862 EXPECT_EQ(ERR_IO_PENDING, rv);
3864 TransactionHelperResult out = helper.output();
3865 out.rv = callback.WaitForResult();
3866 EXPECT_EQ(out.rv, OK);
3868 const HttpResponseInfo* response = trans->GetResponseInfo();
3869 EXPECT_TRUE(response->headers.get() != NULL);
3870 EXPECT_TRUE(response->was_fetched_via_spdy);
3871 out.status_line = response->headers->GetStatusLine();
3872 out.response_info = *response; // Make a copy so we can verify.
3874 // Read Data
3875 TestCompletionCallback read_callback;
3877 std::string content;
3878 do {
3879 // Read small chunks at a time.
3880 const int kSmallReadSize = 3;
3881 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3882 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
3883 if (rv == net::ERR_IO_PENDING) {
3884 data.CompleteRead();
3885 rv = read_callback.WaitForResult();
3887 if (rv > 0) {
3888 content.append(buf->data(), rv);
3889 } else if (rv < 0) {
3890 NOTREACHED();
3892 } while (rv > 0);
3894 out.response_data.swap(content);
3896 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3897 // MockClientSocketFactory) are still alive.
3898 base::RunLoop().RunUntilIdle();
3900 // Verify that we consumed all test data.
3901 helper.VerifyDataConsumed();
3903 EXPECT_EQ(OK, out.rv);
3904 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3905 EXPECT_EQ("goodbye world", out.response_data);
3908 // Verify that basic buffering works; when multiple data frames arrive
3909 // at the same time, ensure that we don't notify a read completion for
3910 // each data frame individually.
3911 TEST_P(SpdyNetworkTransactionTest, Buffering) {
3912 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3914 scoped_ptr<SpdyFrame> req(
3915 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3916 MockWrite writes[] = { CreateMockWrite(*req) };
3918 // 4 data frames in a single read.
3919 scoped_ptr<SpdyFrame> data_frame(
3920 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
3921 scoped_ptr<SpdyFrame> data_frame_fin(
3922 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
3923 const SpdyFrame* data_frames[4] = {
3924 data_frame.get(),
3925 data_frame.get(),
3926 data_frame.get(),
3927 data_frame_fin.get()
3929 char combined_data_frames[100];
3930 int combined_data_frames_len =
3931 CombineFrames(data_frames, arraysize(data_frames),
3932 combined_data_frames, arraysize(combined_data_frames));
3934 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3935 MockRead reads[] = {
3936 CreateMockRead(*resp),
3937 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3938 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
3939 MockRead(ASYNC, 0, 0) // EOF
3942 DelayedSocketData data(1, reads, arraysize(reads),
3943 writes, arraysize(writes));
3945 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3946 BoundNetLog(), GetParam(), NULL);
3947 helper.RunPreTestSetup();
3948 helper.AddData(&data);
3949 HttpNetworkTransaction* trans = helper.trans();
3951 TestCompletionCallback callback;
3952 int rv = trans->Start(
3953 &CreateGetRequest(), callback.callback(), BoundNetLog());
3954 EXPECT_EQ(ERR_IO_PENDING, rv);
3956 TransactionHelperResult out = helper.output();
3957 out.rv = callback.WaitForResult();
3958 EXPECT_EQ(out.rv, OK);
3960 const HttpResponseInfo* response = trans->GetResponseInfo();
3961 EXPECT_TRUE(response->headers.get() != NULL);
3962 EXPECT_TRUE(response->was_fetched_via_spdy);
3963 out.status_line = response->headers->GetStatusLine();
3964 out.response_info = *response; // Make a copy so we can verify.
3966 // Read Data
3967 TestCompletionCallback read_callback;
3969 std::string content;
3970 int reads_completed = 0;
3971 do {
3972 // Read small chunks at a time.
3973 const int kSmallReadSize = 14;
3974 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3975 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
3976 if (rv == net::ERR_IO_PENDING) {
3977 data.CompleteRead();
3978 rv = read_callback.WaitForResult();
3980 if (rv > 0) {
3981 EXPECT_EQ(kSmallReadSize, rv);
3982 content.append(buf->data(), rv);
3983 } else if (rv < 0) {
3984 FAIL() << "Unexpected read error: " << rv;
3986 reads_completed++;
3987 } while (rv > 0);
3989 EXPECT_EQ(3, reads_completed); // Reads are: 14 bytes, 14 bytes, 0 bytes.
3991 out.response_data.swap(content);
3993 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3994 // MockClientSocketFactory) are still alive.
3995 base::RunLoop().RunUntilIdle();
3997 // Verify that we consumed all test data.
3998 helper.VerifyDataConsumed();
4000 EXPECT_EQ(OK, out.rv);
4001 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4002 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
4005 // Verify the case where we buffer data but read it after it has been buffered.
4006 TEST_P(SpdyNetworkTransactionTest, BufferedAll) {
4007 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4009 scoped_ptr<SpdyFrame> req(
4010 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4011 MockWrite writes[] = { CreateMockWrite(*req) };
4013 // 5 data frames in a single read.
4014 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4015 scoped_ptr<SpdyFrame> data_frame(
4016 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4017 scoped_ptr<SpdyFrame> data_frame_fin(
4018 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
4019 const SpdyFrame* frames[5] = {reply.get(), data_frame.get(), data_frame.get(),
4020 data_frame.get(), data_frame_fin.get()};
4021 char combined_frames[200];
4022 int combined_frames_len =
4023 CombineFrames(frames, arraysize(frames),
4024 combined_frames, arraysize(combined_frames));
4026 MockRead reads[] = {
4027 MockRead(ASYNC, combined_frames, combined_frames_len),
4028 MockRead(ASYNC, 0, 0) // EOF
4031 DelayedSocketData data(1, reads, arraysize(reads),
4032 writes, arraysize(writes));
4034 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4035 BoundNetLog(), GetParam(), NULL);
4036 helper.RunPreTestSetup();
4037 helper.AddData(&data);
4038 HttpNetworkTransaction* trans = helper.trans();
4040 TestCompletionCallback callback;
4041 int rv = trans->Start(
4042 &CreateGetRequest(), callback.callback(), BoundNetLog());
4043 EXPECT_EQ(ERR_IO_PENDING, rv);
4045 TransactionHelperResult out = helper.output();
4046 out.rv = callback.WaitForResult();
4047 EXPECT_EQ(out.rv, OK);
4049 const HttpResponseInfo* response = trans->GetResponseInfo();
4050 EXPECT_TRUE(response->headers.get() != NULL);
4051 EXPECT_TRUE(response->was_fetched_via_spdy);
4052 out.status_line = response->headers->GetStatusLine();
4053 out.response_info = *response; // Make a copy so we can verify.
4055 // Read Data
4056 TestCompletionCallback read_callback;
4058 std::string content;
4059 int reads_completed = 0;
4060 do {
4061 // Read small chunks at a time.
4062 const int kSmallReadSize = 14;
4063 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4064 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
4065 if (rv > 0) {
4066 EXPECT_EQ(kSmallReadSize, rv);
4067 content.append(buf->data(), rv);
4068 } else if (rv < 0) {
4069 FAIL() << "Unexpected read error: " << rv;
4071 reads_completed++;
4072 } while (rv > 0);
4074 EXPECT_EQ(3, reads_completed);
4076 out.response_data.swap(content);
4078 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4079 // MockClientSocketFactory) are still alive.
4080 base::RunLoop().RunUntilIdle();
4082 // Verify that we consumed all test data.
4083 helper.VerifyDataConsumed();
4085 EXPECT_EQ(OK, out.rv);
4086 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4087 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
4090 // Verify the case where we buffer data and close the connection.
4091 TEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
4092 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4094 scoped_ptr<SpdyFrame> req(
4095 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4096 MockWrite writes[] = { CreateMockWrite(*req) };
4098 // All data frames in a single read.
4099 // NOTE: We don't FIN the stream.
4100 scoped_ptr<SpdyFrame> data_frame(
4101 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4102 const SpdyFrame* data_frames[4] = {
4103 data_frame.get(),
4104 data_frame.get(),
4105 data_frame.get(),
4106 data_frame.get()
4108 char combined_data_frames[100];
4109 int combined_data_frames_len =
4110 CombineFrames(data_frames, arraysize(data_frames),
4111 combined_data_frames, arraysize(combined_data_frames));
4112 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4113 MockRead reads[] = {
4114 CreateMockRead(*resp),
4115 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait
4116 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
4117 MockRead(ASYNC, 0, 0) // EOF
4120 DelayedSocketData data(1, reads, arraysize(reads),
4121 writes, arraysize(writes));
4123 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4124 BoundNetLog(), GetParam(), NULL);
4125 helper.RunPreTestSetup();
4126 helper.AddData(&data);
4127 HttpNetworkTransaction* trans = helper.trans();
4129 TestCompletionCallback callback;
4131 int rv = trans->Start(
4132 &CreateGetRequest(), callback.callback(), BoundNetLog());
4133 EXPECT_EQ(ERR_IO_PENDING, rv);
4135 TransactionHelperResult out = helper.output();
4136 out.rv = callback.WaitForResult();
4137 EXPECT_EQ(out.rv, OK);
4139 const HttpResponseInfo* response = trans->GetResponseInfo();
4140 EXPECT_TRUE(response->headers.get() != NULL);
4141 EXPECT_TRUE(response->was_fetched_via_spdy);
4142 out.status_line = response->headers->GetStatusLine();
4143 out.response_info = *response; // Make a copy so we can verify.
4145 // Read Data
4146 TestCompletionCallback read_callback;
4148 std::string content;
4149 int reads_completed = 0;
4150 do {
4151 // Read small chunks at a time.
4152 const int kSmallReadSize = 14;
4153 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4154 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
4155 if (rv == net::ERR_IO_PENDING) {
4156 data.CompleteRead();
4157 rv = read_callback.WaitForResult();
4159 if (rv > 0) {
4160 content.append(buf->data(), rv);
4161 } else if (rv < 0) {
4162 // This test intentionally closes the connection, and will get an error.
4163 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
4164 break;
4166 reads_completed++;
4167 } while (rv > 0);
4169 EXPECT_EQ(0, reads_completed);
4171 out.response_data.swap(content);
4173 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4174 // MockClientSocketFactory) are still alive.
4175 base::RunLoop().RunUntilIdle();
4177 // Verify that we consumed all test data.
4178 helper.VerifyDataConsumed();
4181 // Verify the case where we buffer data and cancel the transaction.
4182 TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) {
4183 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4185 scoped_ptr<SpdyFrame> req(
4186 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4187 scoped_ptr<SpdyFrame> rst(
4188 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
4189 MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*rst)};
4191 // NOTE: We don't FIN the stream.
4192 scoped_ptr<SpdyFrame> data_frame(
4193 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4195 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4196 MockRead reads[] = {
4197 CreateMockRead(*resp),
4198 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait
4199 CreateMockRead(*data_frame),
4200 MockRead(ASYNC, 0, 0) // EOF
4203 DelayedSocketData data(1, reads, arraysize(reads),
4204 writes, arraysize(writes));
4206 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4207 BoundNetLog(), GetParam(), NULL);
4208 helper.RunPreTestSetup();
4209 helper.AddData(&data);
4210 HttpNetworkTransaction* trans = helper.trans();
4211 TestCompletionCallback callback;
4213 int rv = trans->Start(
4214 &CreateGetRequest(), callback.callback(), BoundNetLog());
4215 EXPECT_EQ(ERR_IO_PENDING, rv);
4217 TransactionHelperResult out = helper.output();
4218 out.rv = callback.WaitForResult();
4219 EXPECT_EQ(out.rv, OK);
4221 const HttpResponseInfo* response = trans->GetResponseInfo();
4222 EXPECT_TRUE(response->headers.get() != NULL);
4223 EXPECT_TRUE(response->was_fetched_via_spdy);
4224 out.status_line = response->headers->GetStatusLine();
4225 out.response_info = *response; // Make a copy so we can verify.
4227 // Read Data
4228 TestCompletionCallback read_callback;
4230 const int kReadSize = 256;
4231 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kReadSize));
4232 rv = trans->Read(buf.get(), kReadSize, read_callback.callback());
4233 ASSERT_EQ(net::ERR_IO_PENDING, rv) << "Unexpected read: " << rv;
4235 // Complete the read now, which causes buffering to start.
4236 data.CompleteRead();
4237 // Destroy the transaction, causing the stream to get cancelled
4238 // and orphaning the buffered IO task.
4239 helper.ResetTrans();
4241 // Flush the MessageLoop; this will cause the buffered IO task
4242 // to run for the final time.
4243 base::RunLoop().RunUntilIdle();
4245 // Verify that we consumed all test data.
4246 helper.VerifyDataConsumed();
4249 // Test that if the server requests persistence of settings, that we save
4250 // the settings in the HttpServerProperties.
4251 TEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
4252 if (spdy_util_.spdy_version() >= SPDY4) {
4253 // SPDY4 doesn't support settings persistence.
4254 return;
4256 static const SpdyHeaderInfo kSynReplyInfo = {
4257 SYN_REPLY, // Syn Reply
4258 1, // Stream ID
4259 0, // Associated Stream ID
4260 ConvertRequestPriorityToSpdyPriority(
4261 LOWEST, spdy_util_.spdy_version()),
4262 kSpdyCredentialSlotUnused,
4263 CONTROL_FLAG_NONE, // Control Flags
4264 false, // Compressed
4265 RST_STREAM_INVALID, // Status
4266 NULL, // Data
4267 0, // Data Length
4268 DATA_FLAG_NONE // Data Flags
4271 BoundNetLog net_log;
4272 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4273 net_log, GetParam(), NULL);
4274 helper.RunPreTestSetup();
4276 // Verify that no settings exist initially.
4277 HostPortPair host_port_pair("www.google.com", helper.port());
4278 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4279 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4280 host_port_pair).empty());
4282 // Construct the request.
4283 scoped_ptr<SpdyFrame> req(
4284 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4285 MockWrite writes[] = { CreateMockWrite(*req) };
4287 // Construct the reply.
4288 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4289 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4290 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
4291 scoped_ptr<SpdyFrame> reply(
4292 spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
4294 const SpdySettingsIds kSampleId1 = SETTINGS_UPLOAD_BANDWIDTH;
4295 unsigned int kSampleValue1 = 0x0a0a0a0a;
4296 const SpdySettingsIds kSampleId2 = SETTINGS_DOWNLOAD_BANDWIDTH;
4297 unsigned int kSampleValue2 = 0x0b0b0b0b;
4298 const SpdySettingsIds kSampleId3 = SETTINGS_ROUND_TRIP_TIME;
4299 unsigned int kSampleValue3 = 0x0c0c0c0c;
4300 scoped_ptr<SpdyFrame> settings_frame;
4302 // Construct the SETTINGS frame.
4303 SettingsMap settings;
4304 // First add a persisted setting.
4305 settings[kSampleId1] =
4306 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue1);
4307 // Next add a non-persisted setting.
4308 settings[kSampleId2] =
4309 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kSampleValue2);
4310 // Next add another persisted setting.
4311 settings[kSampleId3] =
4312 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue3);
4313 settings_frame.reset(spdy_util_.ConstructSpdySettings(settings));
4316 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4317 MockRead reads[] = {
4318 CreateMockRead(*reply),
4319 CreateMockRead(*body),
4320 CreateMockRead(*settings_frame),
4321 MockRead(ASYNC, 0, 0) // EOF
4324 DelayedSocketData data(1, reads, arraysize(reads),
4325 writes, arraysize(writes));
4326 helper.AddData(&data);
4327 helper.RunDefaultTest();
4328 helper.VerifyDataConsumed();
4329 TransactionHelperResult out = helper.output();
4330 EXPECT_EQ(OK, out.rv);
4331 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4332 EXPECT_EQ("hello!", out.response_data);
4335 // Verify we had two persisted settings.
4336 const SettingsMap& settings_map =
4337 spdy_session_pool->http_server_properties()->GetSpdySettings(
4338 host_port_pair);
4339 ASSERT_EQ(2u, settings_map.size());
4341 // Verify the first persisted setting.
4342 SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4343 EXPECT_TRUE(it1 != settings_map.end());
4344 SettingsFlagsAndValue flags_and_value1 = it1->second;
4345 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4346 EXPECT_EQ(kSampleValue1, flags_and_value1.second);
4348 // Verify the second persisted setting.
4349 SettingsMap::const_iterator it3 = settings_map.find(kSampleId3);
4350 EXPECT_TRUE(it3 != settings_map.end());
4351 SettingsFlagsAndValue flags_and_value3 = it3->second;
4352 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value3.first);
4353 EXPECT_EQ(kSampleValue3, flags_and_value3.second);
4357 // Test that when there are settings saved that they are sent back to the
4358 // server upon session establishment.
4359 TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) {
4360 if (spdy_util_.spdy_version() >= SPDY4) {
4361 // SPDY4 doesn't support settings persistence.
4362 return;
4364 static const SpdyHeaderInfo kSynReplyInfo = {
4365 SYN_REPLY, // Syn Reply
4366 1, // Stream ID
4367 0, // Associated Stream ID
4368 ConvertRequestPriorityToSpdyPriority(
4369 LOWEST, spdy_util_.spdy_version()),
4370 kSpdyCredentialSlotUnused,
4371 CONTROL_FLAG_NONE, // Control Flags
4372 false, // Compressed
4373 RST_STREAM_INVALID, // Status
4374 NULL, // Data
4375 0, // Data Length
4376 DATA_FLAG_NONE // Data Flags
4379 BoundNetLog net_log;
4380 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4381 net_log, GetParam(), NULL);
4382 helper.RunPreTestSetup();
4384 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4386 SpdySessionPoolPeer pool_peer(spdy_session_pool);
4387 pool_peer.SetEnableSendingInitialData(true);
4389 // Verify that no settings exist initially.
4390 HostPortPair host_port_pair("www.google.com", helper.port());
4391 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4392 host_port_pair).empty());
4394 const SpdySettingsIds kSampleId1 = SETTINGS_MAX_CONCURRENT_STREAMS;
4395 unsigned int kSampleValue1 = 0x0a0a0a0a;
4396 const SpdySettingsIds kSampleId2 = SETTINGS_INITIAL_WINDOW_SIZE;
4397 unsigned int kSampleValue2 = 0x0c0c0c0c;
4399 // First add a persisted setting.
4400 spdy_session_pool->http_server_properties()->SetSpdySetting(
4401 host_port_pair,
4402 kSampleId1,
4403 SETTINGS_FLAG_PLEASE_PERSIST,
4404 kSampleValue1);
4406 // Next add another persisted setting.
4407 spdy_session_pool->http_server_properties()->SetSpdySetting(
4408 host_port_pair,
4409 kSampleId2,
4410 SETTINGS_FLAG_PLEASE_PERSIST,
4411 kSampleValue2);
4413 EXPECT_EQ(2u, spdy_session_pool->http_server_properties()->GetSpdySettings(
4414 host_port_pair).size());
4416 // Construct the initial SETTINGS frame.
4417 SettingsMap initial_settings;
4418 initial_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4419 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
4420 scoped_ptr<SpdyFrame> initial_settings_frame(
4421 spdy_util_.ConstructSpdySettings(initial_settings));
4423 // Construct the initial window update.
4424 scoped_ptr<SpdyFrame> initial_window_update(
4425 spdy_util_.ConstructSpdyWindowUpdate(
4426 kSessionFlowControlStreamId,
4427 kDefaultInitialRecvWindowSize -
4428 SpdySession::GetInitialWindowSize(GetParam().protocol)));
4430 // Construct the persisted SETTINGS frame.
4431 const SettingsMap& settings =
4432 spdy_session_pool->http_server_properties()->GetSpdySettings(
4433 host_port_pair);
4434 scoped_ptr<SpdyFrame> settings_frame(
4435 spdy_util_.ConstructSpdySettings(settings));
4437 // Construct the request.
4438 scoped_ptr<SpdyFrame> req(
4439 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4441 std::vector<MockWrite> writes;
4442 if ((GetParam().protocol >= kProtoSPDY4MinimumVersion) &&
4443 (GetParam().protocol <= kProtoSPDY4MaximumVersion)) {
4444 writes.push_back(
4445 MockWrite(ASYNC,
4446 kHttp2ConnectionHeaderPrefix,
4447 kHttp2ConnectionHeaderPrefixSize));
4449 writes.push_back(CreateMockWrite(*initial_settings_frame));
4450 if (GetParam().protocol >= kProtoSPDY31) {
4451 writes.push_back(CreateMockWrite(*initial_window_update));
4453 writes.push_back(CreateMockWrite(*settings_frame));
4454 writes.push_back(CreateMockWrite(*req));
4456 // Construct the reply.
4457 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4458 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4459 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
4460 scoped_ptr<SpdyFrame> reply(
4461 spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
4463 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4464 MockRead reads[] = {
4465 CreateMockRead(*reply),
4466 CreateMockRead(*body),
4467 MockRead(ASYNC, 0, 0) // EOF
4470 DelayedSocketData data(2, reads, arraysize(reads),
4471 vector_as_array(&writes), writes.size());
4472 helper.AddData(&data);
4473 helper.RunDefaultTest();
4474 helper.VerifyDataConsumed();
4475 TransactionHelperResult out = helper.output();
4476 EXPECT_EQ(OK, out.rv);
4477 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4478 EXPECT_EQ("hello!", out.response_data);
4481 // Verify we had two persisted settings.
4482 const SettingsMap& settings_map =
4483 spdy_session_pool->http_server_properties()->GetSpdySettings(
4484 host_port_pair);
4485 ASSERT_EQ(2u, settings_map.size());
4487 // Verify the first persisted setting.
4488 SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4489 EXPECT_TRUE(it1 != settings_map.end());
4490 SettingsFlagsAndValue flags_and_value1 = it1->second;
4491 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4492 EXPECT_EQ(kSampleValue1, flags_and_value1.second);
4494 // Verify the second persisted setting.
4495 SettingsMap::const_iterator it2 = settings_map.find(kSampleId2);
4496 EXPECT_TRUE(it2 != settings_map.end());
4497 SettingsFlagsAndValue flags_and_value2 = it2->second;
4498 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value2.first);
4499 EXPECT_EQ(kSampleValue2, flags_and_value2.second);
4503 TEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
4504 scoped_ptr<SpdyFrame> req(
4505 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4506 MockWrite writes[] = { CreateMockWrite(*req) };
4508 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway());
4509 MockRead reads[] = {
4510 CreateMockRead(*go_away),
4513 DelayedSocketData data(1, reads, arraysize(reads),
4514 writes, arraysize(writes));
4515 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4516 BoundNetLog(), GetParam(), NULL);
4517 helper.AddData(&data);
4518 helper.RunToCompletion(&data);
4519 TransactionHelperResult out = helper.output();
4520 EXPECT_EQ(ERR_ABORTED, out.rv);
4523 TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) {
4524 scoped_ptr<SpdyFrame> req(
4525 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4526 MockWrite writes[] = { CreateMockWrite(*req) };
4528 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4529 MockRead reads[] = {
4530 CreateMockRead(*resp),
4531 MockRead(SYNCHRONOUS, 0, 0) // EOF
4534 DelayedSocketData data(1, reads, arraysize(reads),
4535 writes, arraysize(writes));
4536 BoundNetLog log;
4537 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4538 log, GetParam(), NULL);
4539 helper.RunPreTestSetup();
4540 helper.AddData(&data);
4541 HttpNetworkTransaction* trans = helper.trans();
4543 TestCompletionCallback callback;
4544 TransactionHelperResult out;
4545 out.rv = trans->Start(&CreateGetRequest(), callback.callback(), log);
4547 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4548 out.rv = callback.WaitForResult();
4549 EXPECT_EQ(out.rv, OK);
4551 const HttpResponseInfo* response = trans->GetResponseInfo();
4552 EXPECT_TRUE(response->headers.get() != NULL);
4553 EXPECT_TRUE(response->was_fetched_via_spdy);
4554 out.rv = ReadTransaction(trans, &out.response_data);
4555 EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv);
4557 // Verify that we consumed all test data.
4558 helper.VerifyDataConsumed();
4561 // HTTP_1_1_REQUIRED results in ERR_HTTP_1_1_REQUIRED.
4562 TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredError) {
4563 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4564 if (spdy_util_.spdy_version() < SPDY4)
4565 return;
4567 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4568 BoundNetLog(), GetParam(), nullptr);
4570 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway(
4571 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
4572 MockRead reads[] = {
4573 CreateMockRead(*go_away),
4575 DelayedSocketData data(0, reads, arraysize(reads), nullptr, 0);
4577 helper.RunToCompletion(&data);
4578 TransactionHelperResult out = helper.output();
4579 EXPECT_EQ(ERR_HTTP_1_1_REQUIRED, out.rv);
4582 // Retry with HTTP/1.1 when receiving HTTP_1_1_REQUIRED. Note that no actual
4583 // protocol negotiation happens, instead this test forces protocols for both
4584 // sockets.
4585 TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredRetry) {
4586 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4587 if (spdy_util_.spdy_version() < SPDY4)
4588 return;
4589 // HTTP_1_1_REQUIRED implementation relies on the assumption that HTTP/2 is
4590 // only spoken over SSL.
4591 if (GetParam().ssl_type != SPDYSSL)
4592 return;
4594 HttpRequestInfo request;
4595 request.method = "GET";
4596 request.url = GURL("https://www.google.com/");
4597 scoped_ptr<SpdySessionDependencies> session_deps(
4598 CreateSpdySessionDependencies(GetParam()));
4599 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
4600 session_deps->force_spdy_over_ssl = false;
4601 session_deps->force_spdy_always = false;
4602 session_deps->next_protos = SpdyNextProtos();
4603 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
4604 GetParam(), session_deps.release());
4606 // First socket: HTTP/2 request rejected with HTTP_1_1_REQUIRED.
4607 const char* url = "https://www.google.com/";
4608 scoped_ptr<SpdyHeaderBlock> headers(spdy_util_.ConstructGetHeaderBlock(url));
4609 scoped_ptr<SpdyFrame> req(
4610 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
4611 MockWrite writes0[] = {CreateMockWrite(*req)};
4612 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway(
4613 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
4614 MockRead reads0[] = {CreateMockRead(*go_away)};
4615 DelayedSocketData data0(1, reads0, arraysize(reads0), writes0,
4616 arraysize(writes0));
4618 scoped_ptr<SSLSocketDataProvider> ssl_provider0(
4619 new SSLSocketDataProvider(ASYNC, OK));
4620 // Expect HTTP/2 protocols too in SSLConfig.
4621 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4622 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY31);
4623 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY4_14);
4624 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY4_15);
4625 // Force SPDY.
4626 ssl_provider0->SetNextProto(GetParam().protocol);
4627 helper.AddDataWithSSLSocketDataProvider(&data0, ssl_provider0.Pass());
4629 // Second socket: falling back to HTTP/1.1.
4630 MockWrite writes1[] = {MockWrite(
4631 "GET / HTTP/1.1\r\n"
4632 "Host: www.google.com\r\n"
4633 "Connection: keep-alive\r\n\r\n")};
4634 MockRead reads1[] = {MockRead(
4635 "HTTP/1.1 200 OK\r\n"
4636 "Content-Length: 5\r\n\r\n"
4637 "hello")};
4638 DelayedSocketData data1(1, reads1, arraysize(reads1), writes1,
4639 arraysize(writes1));
4641 scoped_ptr<SSLSocketDataProvider> ssl_provider1(
4642 new SSLSocketDataProvider(ASYNC, OK));
4643 // Expect only HTTP/1.1 protocol in SSLConfig.
4644 ssl_provider1->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4645 // Force HTTP/1.1.
4646 ssl_provider1->SetNextProto(kProtoHTTP11);
4647 helper.AddDataWithSSLSocketDataProvider(&data1, ssl_provider1.Pass());
4649 base::WeakPtr<HttpServerProperties> http_server_properties =
4650 helper.session()->spdy_session_pool()->http_server_properties();
4651 const HostPortPair host_port_pair = HostPortPair::FromURL(GURL(url));
4652 EXPECT_FALSE(http_server_properties->RequiresHTTP11(host_port_pair));
4654 helper.RunPreTestSetup();
4655 helper.StartDefaultTest();
4656 helper.FinishDefaultTestWithoutVerification();
4657 helper.VerifyDataConsumed();
4658 EXPECT_TRUE(http_server_properties->RequiresHTTP11(host_port_pair));
4660 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
4661 ASSERT_TRUE(response != nullptr);
4662 ASSERT_TRUE(response->headers.get() != nullptr);
4663 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4664 EXPECT_FALSE(response->was_fetched_via_spdy);
4665 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1, response->connection_info);
4666 EXPECT_TRUE(response->was_npn_negotiated);
4667 EXPECT_TRUE(request.url.SchemeIs("https"));
4668 EXPECT_EQ("127.0.0.1", response->socket_address.host());
4669 EXPECT_EQ(443, response->socket_address.port());
4670 std::string response_data;
4671 ASSERT_EQ(OK, ReadTransaction(helper.trans(), &response_data));
4672 EXPECT_EQ("hello", response_data);
4675 // Retry with HTTP/1.1 to the proxy when receiving HTTP_1_1_REQUIRED from the
4676 // proxy. Note that no actual protocol negotiation happens, instead this test
4677 // forces protocols for both sockets.
4678 TEST_P(SpdyNetworkTransactionTest, HTTP11RequiredProxyRetry) {
4679 // HTTP_1_1_REQUIRED is only supported by SPDY4.
4680 if (spdy_util_.spdy_version() < SPDY4)
4681 return;
4682 // HTTP_1_1_REQUIRED implementation relies on the assumption that HTTP/2 is
4683 // only spoken over SSL.
4684 if (GetParam().ssl_type != SPDYSSL)
4685 return;
4687 HttpRequestInfo request;
4688 request.method = "GET";
4689 request.url = GURL("https://www.google.com/");
4690 scoped_ptr<SpdySessionDependencies> session_deps(
4691 CreateSpdySessionDependencies(
4692 GetParam(),
4693 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70")));
4694 // Do not force SPDY so that second socket can negotiate HTTP/1.1.
4695 session_deps->force_spdy_over_ssl = false;
4696 session_deps->force_spdy_always = false;
4697 session_deps->next_protos = SpdyNextProtos();
4698 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY, BoundNetLog(),
4699 GetParam(), session_deps.release());
4701 // First socket: HTTP/2 CONNECT rejected with HTTP_1_1_REQUIRED.
4702 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(
4703 nullptr, 0, 1, LOWEST, HostPortPair("www.google.com", 443)));
4704 MockWrite writes0[] = {CreateMockWrite(*req)};
4705 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway(
4706 0, GOAWAY_HTTP_1_1_REQUIRED, "Try again using HTTP/1.1 please."));
4707 MockRead reads0[] = {CreateMockRead(*go_away)};
4708 DelayedSocketData data0(1, reads0, arraysize(reads0), writes0,
4709 arraysize(writes0));
4711 scoped_ptr<SSLSocketDataProvider> ssl_provider0(
4712 new SSLSocketDataProvider(ASYNC, OK));
4713 // Expect HTTP/2 protocols too in SSLConfig.
4714 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4715 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY31);
4716 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY4_14);
4717 ssl_provider0->next_protos_expected_in_ssl_config.push_back(kProtoSPDY4_15);
4718 // Force SPDY.
4719 ssl_provider0->SetNextProto(GetParam().protocol);
4720 helper.AddDataWithSSLSocketDataProvider(&data0, ssl_provider0.Pass());
4722 // Second socket: retry using HTTP/1.1.
4723 MockWrite writes1[] = {
4724 MockWrite(ASYNC, 1,
4725 "CONNECT www.google.com:443 HTTP/1.1\r\n"
4726 "Host: www.google.com\r\n"
4727 "Proxy-Connection: keep-alive\r\n\r\n"),
4728 MockWrite(ASYNC, 3,
4729 "GET / HTTP/1.1\r\n"
4730 "Host: www.google.com\r\n"
4731 "Connection: keep-alive\r\n\r\n"),
4734 MockRead reads1[] = {
4735 MockRead(ASYNC, 2, "HTTP/1.1 200 OK\r\n\r\n"),
4736 MockRead(ASYNC, 4,
4737 "HTTP/1.1 200 OK\r\n"
4738 "Content-Length: 5\r\n\r\n"
4739 "hello"),
4741 DelayedSocketData data1(1, reads1, arraysize(reads1), writes1,
4742 arraysize(writes1));
4744 scoped_ptr<SSLSocketDataProvider> ssl_provider1(
4745 new SSLSocketDataProvider(ASYNC, OK));
4746 // Expect only HTTP/1.1 protocol in SSLConfig.
4747 ssl_provider1->next_protos_expected_in_ssl_config.push_back(kProtoHTTP11);
4748 // Force HTTP/1.1.
4749 ssl_provider1->SetNextProto(kProtoHTTP11);
4750 helper.AddDataWithSSLSocketDataProvider(&data1, ssl_provider1.Pass());
4752 // A third socket is needed for the tunnelled connection.
4753 scoped_ptr<SSLSocketDataProvider> ssl_provider2(
4754 new SSLSocketDataProvider(ASYNC, OK));
4755 helper.session_deps()->socket_factory->AddSSLSocketDataProvider(
4756 ssl_provider2.get());
4758 base::WeakPtr<HttpServerProperties> http_server_properties =
4759 helper.session()->spdy_session_pool()->http_server_properties();
4760 const HostPortPair proxy_host_port_pair = HostPortPair("myproxy", 70);
4761 EXPECT_FALSE(http_server_properties->RequiresHTTP11(proxy_host_port_pair));
4763 helper.RunPreTestSetup();
4764 helper.StartDefaultTest();
4765 helper.FinishDefaultTestWithoutVerification();
4766 helper.VerifyDataConsumed();
4767 EXPECT_TRUE(http_server_properties->RequiresHTTP11(proxy_host_port_pair));
4769 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
4770 ASSERT_TRUE(response != nullptr);
4771 ASSERT_TRUE(response->headers.get() != nullptr);
4772 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4773 EXPECT_FALSE(response->was_fetched_via_spdy);
4774 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1, response->connection_info);
4775 EXPECT_FALSE(response->was_npn_negotiated);
4776 EXPECT_TRUE(request.url.SchemeIs("https"));
4777 EXPECT_EQ("127.0.0.1", response->socket_address.host());
4778 EXPECT_EQ(70, response->socket_address.port());
4779 std::string response_data;
4780 ASSERT_EQ(OK, ReadTransaction(helper.trans(), &response_data));
4781 EXPECT_EQ("hello", response_data);
4784 // Test to make sure we can correctly connect through a proxy.
4785 TEST_P(SpdyNetworkTransactionTest, ProxyConnect) {
4786 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4787 BoundNetLog(), GetParam(), NULL);
4788 helper.session_deps().reset(CreateSpdySessionDependencies(
4789 GetParam(),
4790 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
4791 helper.SetSession(make_scoped_refptr(
4792 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
4793 helper.RunPreTestSetup();
4794 HttpNetworkTransaction* trans = helper.trans();
4796 const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4797 "Host: www.google.com\r\n"
4798 "Proxy-Connection: keep-alive\r\n\r\n"};
4799 const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4800 "Host: www.google.com\r\n"
4801 "Proxy-Connection: keep-alive\r\n\r\n"};
4802 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4803 scoped_ptr<SpdyFrame> req(
4804 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4805 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4806 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4808 MockWrite writes_SPDYNPN[] = {
4809 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4810 CreateMockWrite(*req, 2),
4812 MockRead reads_SPDYNPN[] = {
4813 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4814 CreateMockRead(*resp, 3),
4815 CreateMockRead(*body.get(), 4),
4816 MockRead(ASYNC, 0, 0, 5),
4819 MockWrite writes_SPDYSSL[] = {
4820 MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0),
4821 CreateMockWrite(*req, 2),
4823 MockRead reads_SPDYSSL[] = {
4824 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4825 CreateMockRead(*resp, 3),
4826 CreateMockRead(*body.get(), 4),
4827 MockRead(ASYNC, 0, 0, 5),
4830 MockWrite writes_SPDYNOSSL[] = {
4831 CreateMockWrite(*req, 0),
4834 MockRead reads_SPDYNOSSL[] = {
4835 CreateMockRead(*resp, 1),
4836 CreateMockRead(*body.get(), 2),
4837 MockRead(ASYNC, 0, 0, 3),
4840 scoped_ptr<OrderedSocketData> data;
4841 switch (GetParam().ssl_type) {
4842 case SPDYNOSSL:
4843 data.reset(new OrderedSocketData(reads_SPDYNOSSL,
4844 arraysize(reads_SPDYNOSSL),
4845 writes_SPDYNOSSL,
4846 arraysize(writes_SPDYNOSSL)));
4847 break;
4848 case SPDYSSL:
4849 data.reset(new OrderedSocketData(reads_SPDYSSL,
4850 arraysize(reads_SPDYSSL),
4851 writes_SPDYSSL,
4852 arraysize(writes_SPDYSSL)));
4853 break;
4854 case SPDYNPN:
4855 data.reset(new OrderedSocketData(reads_SPDYNPN,
4856 arraysize(reads_SPDYNPN),
4857 writes_SPDYNPN,
4858 arraysize(writes_SPDYNPN)));
4859 break;
4860 default:
4861 NOTREACHED();
4864 helper.AddData(data.get());
4865 TestCompletionCallback callback;
4867 int rv = trans->Start(
4868 &CreateGetRequest(), callback.callback(), BoundNetLog());
4869 EXPECT_EQ(ERR_IO_PENDING, rv);
4871 rv = callback.WaitForResult();
4872 EXPECT_EQ(0, rv);
4874 // Verify the SYN_REPLY.
4875 HttpResponseInfo response = *trans->GetResponseInfo();
4876 EXPECT_TRUE(response.headers.get() != NULL);
4877 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
4879 std::string response_data;
4880 ASSERT_EQ(OK, ReadTransaction(trans, &response_data));
4881 EXPECT_EQ("hello!", response_data);
4882 helper.VerifyDataConsumed();
4885 // Test to make sure we can correctly connect through a proxy to www.google.com,
4886 // if there already exists a direct spdy connection to www.google.com. See
4887 // http://crbug.com/49874
4888 TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
4889 // When setting up the first transaction, we store the SpdySessionPool so that
4890 // we can use the same pool in the second transaction.
4891 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4892 BoundNetLog(), GetParam(), NULL);
4894 // Use a proxy service which returns a proxy fallback list from DIRECT to
4895 // myproxy:70. For this test there will be no fallback, so it is equivalent
4896 // to simply DIRECT. The reason for appending the second proxy is to verify
4897 // that the session pool key used does is just "DIRECT".
4898 helper.session_deps().reset(CreateSpdySessionDependencies(
4899 GetParam(),
4900 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
4901 helper.SetSession(make_scoped_refptr(
4902 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
4904 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4905 helper.RunPreTestSetup();
4907 // Construct and send a simple GET request.
4908 scoped_ptr<SpdyFrame> req(
4909 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4910 MockWrite writes[] = {
4911 CreateMockWrite(*req, 1),
4914 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4915 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4916 MockRead reads[] = {
4917 CreateMockRead(*resp, 2),
4918 CreateMockRead(*body, 3),
4919 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause
4920 MockRead(ASYNC, 0, 5) // EOF
4922 OrderedSocketData data(reads, arraysize(reads),
4923 writes, arraysize(writes));
4924 helper.AddData(&data);
4925 HttpNetworkTransaction* trans = helper.trans();
4927 TestCompletionCallback callback;
4928 TransactionHelperResult out;
4929 out.rv = trans->Start(
4930 &CreateGetRequest(), callback.callback(), BoundNetLog());
4932 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4933 out.rv = callback.WaitForResult();
4934 EXPECT_EQ(out.rv, OK);
4936 const HttpResponseInfo* response = trans->GetResponseInfo();
4937 EXPECT_TRUE(response->headers.get() != NULL);
4938 EXPECT_TRUE(response->was_fetched_via_spdy);
4939 out.rv = ReadTransaction(trans, &out.response_data);
4940 EXPECT_EQ(OK, out.rv);
4941 out.status_line = response->headers->GetStatusLine();
4942 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4943 EXPECT_EQ("hello!", out.response_data);
4945 // Check that the SpdySession is still in the SpdySessionPool.
4946 HostPortPair host_port_pair("www.google.com", helper.port());
4947 SpdySessionKey session_pool_key_direct(
4948 host_port_pair, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
4949 EXPECT_TRUE(HasSpdySession(spdy_session_pool, session_pool_key_direct));
4950 SpdySessionKey session_pool_key_proxy(
4951 host_port_pair,
4952 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP),
4953 PRIVACY_MODE_DISABLED);
4954 EXPECT_FALSE(HasSpdySession(spdy_session_pool, session_pool_key_proxy));
4956 // Set up data for the proxy connection.
4957 const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4958 "Host: www.google.com\r\n"
4959 "Proxy-Connection: keep-alive\r\n\r\n"};
4960 const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4961 "Host: www.google.com\r\n"
4962 "Proxy-Connection: keep-alive\r\n\r\n"};
4963 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4964 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyGet(
4965 "http://www.google.com/foo.dat", false, 1, LOWEST));
4966 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4967 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
4969 MockWrite writes_SPDYNPN[] = {
4970 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4971 CreateMockWrite(*req2, 2),
4973 MockRead reads_SPDYNPN[] = {
4974 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4975 CreateMockRead(*resp2, 3),
4976 CreateMockRead(*body2, 4),
4977 MockRead(ASYNC, 0, 5) // EOF
4980 MockWrite writes_SPDYNOSSL[] = {
4981 CreateMockWrite(*req2, 0),
4983 MockRead reads_SPDYNOSSL[] = {
4984 CreateMockRead(*resp2, 1),
4985 CreateMockRead(*body2, 2),
4986 MockRead(ASYNC, 0, 3) // EOF
4989 MockWrite writes_SPDYSSL[] = {
4990 MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0),
4991 CreateMockWrite(*req2, 2),
4993 MockRead reads_SPDYSSL[] = {
4994 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4995 CreateMockRead(*resp2, 3),
4996 CreateMockRead(*body2, 4),
4997 MockRead(ASYNC, 0, 0, 5),
5000 scoped_ptr<OrderedSocketData> data_proxy;
5001 switch (GetParam().ssl_type) {
5002 case SPDYNPN:
5003 data_proxy.reset(new OrderedSocketData(reads_SPDYNPN,
5004 arraysize(reads_SPDYNPN),
5005 writes_SPDYNPN,
5006 arraysize(writes_SPDYNPN)));
5007 break;
5008 case SPDYNOSSL:
5009 data_proxy.reset(new OrderedSocketData(reads_SPDYNOSSL,
5010 arraysize(reads_SPDYNOSSL),
5011 writes_SPDYNOSSL,
5012 arraysize(writes_SPDYNOSSL)));
5013 break;
5014 case SPDYSSL:
5015 data_proxy.reset(new OrderedSocketData(reads_SPDYSSL,
5016 arraysize(reads_SPDYSSL),
5017 writes_SPDYSSL,
5018 arraysize(writes_SPDYSSL)));
5019 break;
5020 default:
5021 NOTREACHED();
5024 // Create another request to www.google.com, but this time through a proxy.
5025 HttpRequestInfo request_proxy;
5026 request_proxy.method = "GET";
5027 request_proxy.url = GURL("http://www.google.com/foo.dat");
5028 request_proxy.load_flags = 0;
5029 scoped_ptr<SpdySessionDependencies> ssd_proxy(
5030 CreateSpdySessionDependencies(GetParam()));
5031 // Ensure that this transaction uses the same SpdySessionPool.
5032 scoped_refptr<HttpNetworkSession> session_proxy(
5033 SpdySessionDependencies::SpdyCreateSession(ssd_proxy.get()));
5034 NormalSpdyTransactionHelper helper_proxy(request_proxy, DEFAULT_PRIORITY,
5035 BoundNetLog(), GetParam(), NULL);
5036 HttpNetworkSessionPeer session_peer(session_proxy);
5037 scoped_ptr<net::ProxyService> proxy_service(
5038 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
5039 session_peer.SetProxyService(proxy_service.get());
5040 helper_proxy.session_deps().swap(ssd_proxy);
5041 helper_proxy.SetSession(session_proxy);
5042 helper_proxy.RunPreTestSetup();
5043 helper_proxy.AddData(data_proxy.get());
5045 HttpNetworkTransaction* trans_proxy = helper_proxy.trans();
5046 TestCompletionCallback callback_proxy;
5047 int rv = trans_proxy->Start(
5048 &request_proxy, callback_proxy.callback(), BoundNetLog());
5049 EXPECT_EQ(ERR_IO_PENDING, rv);
5050 rv = callback_proxy.WaitForResult();
5051 EXPECT_EQ(0, rv);
5053 HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo();
5054 EXPECT_TRUE(response_proxy.headers.get() != NULL);
5055 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy.headers->GetStatusLine());
5057 std::string response_data;
5058 ASSERT_EQ(OK, ReadTransaction(trans_proxy, &response_data));
5059 EXPECT_EQ("hello!", response_data);
5061 data.CompleteRead();
5062 helper_proxy.VerifyDataConsumed();
5065 // When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
5066 // on a new connection, if the connection was previously known to be good.
5067 // This can happen when a server reboots without saying goodbye, or when
5068 // we're behind a NAT that masked the RST.
5069 TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
5070 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5071 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
5072 MockRead reads[] = {
5073 CreateMockRead(*resp),
5074 CreateMockRead(*body),
5075 MockRead(ASYNC, ERR_IO_PENDING),
5076 MockRead(ASYNC, ERR_CONNECTION_RESET),
5079 MockRead reads2[] = {
5080 CreateMockRead(*resp),
5081 CreateMockRead(*body),
5082 MockRead(ASYNC, 0, 0) // EOF
5085 // This test has a couple of variants.
5086 enum {
5087 // Induce the RST while waiting for our transaction to send.
5088 VARIANT_RST_DURING_SEND_COMPLETION,
5089 // Induce the RST while waiting for our transaction to read.
5090 // In this case, the send completed - everything copied into the SNDBUF.
5091 VARIANT_RST_DURING_READ_COMPLETION
5094 for (int variant = VARIANT_RST_DURING_SEND_COMPLETION;
5095 variant <= VARIANT_RST_DURING_READ_COMPLETION;
5096 ++variant) {
5097 DelayedSocketData data1(1, reads, arraysize(reads), NULL, 0);
5099 DelayedSocketData data2(1, reads2, arraysize(reads2), NULL, 0);
5101 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5102 BoundNetLog(), GetParam(), NULL);
5103 helper.AddData(&data1);
5104 helper.AddData(&data2);
5105 helper.RunPreTestSetup();
5107 for (int i = 0; i < 2; ++i) {
5108 scoped_ptr<HttpNetworkTransaction> trans(
5109 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5111 TestCompletionCallback callback;
5112 int rv = trans->Start(
5113 &helper.request(), callback.callback(), BoundNetLog());
5114 EXPECT_EQ(ERR_IO_PENDING, rv);
5115 // On the second transaction, we trigger the RST.
5116 if (i == 1) {
5117 if (variant == VARIANT_RST_DURING_READ_COMPLETION) {
5118 // Writes to the socket complete asynchronously on SPDY by running
5119 // through the message loop. Complete the write here.
5120 base::RunLoop().RunUntilIdle();
5123 // Now schedule the ERR_CONNECTION_RESET.
5124 EXPECT_EQ(3u, data1.read_index());
5125 data1.CompleteRead();
5126 EXPECT_EQ(4u, data1.read_index());
5128 rv = callback.WaitForResult();
5129 EXPECT_EQ(OK, rv);
5131 const HttpResponseInfo* response = trans->GetResponseInfo();
5132 ASSERT_TRUE(response != NULL);
5133 EXPECT_TRUE(response->headers.get() != NULL);
5134 EXPECT_TRUE(response->was_fetched_via_spdy);
5135 std::string response_data;
5136 rv = ReadTransaction(trans.get(), &response_data);
5137 EXPECT_EQ(OK, rv);
5138 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5139 EXPECT_EQ("hello!", response_data);
5142 helper.VerifyDataConsumed();
5146 // Test that turning SPDY on and off works properly.
5147 TEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) {
5148 HttpStreamFactory::set_spdy_enabled(true);
5149 scoped_ptr<SpdyFrame> req(
5150 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5151 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
5153 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5154 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
5155 MockRead spdy_reads[] = {
5156 CreateMockRead(*resp),
5157 CreateMockRead(*body),
5158 MockRead(ASYNC, 0, 0) // EOF
5161 DelayedSocketData data(1, spdy_reads, arraysize(spdy_reads),
5162 spdy_writes, arraysize(spdy_writes));
5163 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5164 BoundNetLog(), GetParam(), NULL);
5165 helper.RunToCompletion(&data);
5166 TransactionHelperResult out = helper.output();
5167 EXPECT_EQ(OK, out.rv);
5168 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
5169 EXPECT_EQ("hello!", out.response_data);
5171 net::HttpStreamFactory::set_spdy_enabled(false);
5172 MockRead http_reads[] = {
5173 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5174 MockRead("hello from http"),
5175 MockRead(SYNCHRONOUS, OK),
5177 DelayedSocketData data2(1, http_reads, arraysize(http_reads), NULL, 0);
5178 NormalSpdyTransactionHelper helper2(CreateGetRequest(), DEFAULT_PRIORITY,
5179 BoundNetLog(), GetParam(), NULL);
5180 helper2.SetSpdyDisabled();
5181 helper2.RunToCompletion(&data2);
5182 TransactionHelperResult out2 = helper2.output();
5183 EXPECT_EQ(OK, out2.rv);
5184 EXPECT_EQ("HTTP/1.1 200 OK", out2.status_line);
5185 EXPECT_EQ("hello from http", out2.response_data);
5187 net::HttpStreamFactory::set_spdy_enabled(true);
5190 // Tests that Basic authentication works over SPDY
5191 TEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) {
5192 net::HttpStreamFactory::set_spdy_enabled(true);
5194 // The first request will be a bare GET, the second request will be a
5195 // GET with an Authorization header.
5196 scoped_ptr<SpdyFrame> req_get(
5197 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5198 const char* const kExtraAuthorizationHeaders[] = {
5199 "authorization", "Basic Zm9vOmJhcg=="
5201 scoped_ptr<SpdyFrame> req_get_authorization(
5202 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
5203 arraysize(kExtraAuthorizationHeaders) / 2,
5204 false, 3, LOWEST, true));
5205 MockWrite spdy_writes[] = {
5206 CreateMockWrite(*req_get, 1),
5207 CreateMockWrite(*req_get_authorization, 4),
5210 // The first response is a 401 authentication challenge, and the second
5211 // response will be a 200 response since the second request includes a valid
5212 // Authorization header.
5213 const char* const kExtraAuthenticationHeaders[] = {
5214 "www-authenticate",
5215 "Basic realm=\"MyRealm\""
5217 scoped_ptr<SpdyFrame> resp_authentication(
5218 spdy_util_.ConstructSpdySynReplyError(
5219 "401 Authentication Required",
5220 kExtraAuthenticationHeaders,
5221 arraysize(kExtraAuthenticationHeaders) / 2,
5222 1));
5223 scoped_ptr<SpdyFrame> body_authentication(
5224 spdy_util_.ConstructSpdyBodyFrame(1, true));
5225 scoped_ptr<SpdyFrame> resp_data(
5226 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5227 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
5228 MockRead spdy_reads[] = {
5229 CreateMockRead(*resp_authentication, 2),
5230 CreateMockRead(*body_authentication, 3),
5231 CreateMockRead(*resp_data, 5),
5232 CreateMockRead(*body_data, 6),
5233 MockRead(ASYNC, 0, 7),
5236 OrderedSocketData data(spdy_reads, arraysize(spdy_reads),
5237 spdy_writes, arraysize(spdy_writes));
5238 HttpRequestInfo request(CreateGetRequest());
5239 BoundNetLog net_log;
5240 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5241 net_log, GetParam(), NULL);
5243 helper.RunPreTestSetup();
5244 helper.AddData(&data);
5245 HttpNetworkTransaction* trans = helper.trans();
5246 TestCompletionCallback callback;
5247 const int rv_start = trans->Start(&request, callback.callback(), net_log);
5248 EXPECT_EQ(ERR_IO_PENDING, rv_start);
5249 const int rv_start_complete = callback.WaitForResult();
5250 EXPECT_EQ(OK, rv_start_complete);
5252 // Make sure the response has an auth challenge.
5253 const HttpResponseInfo* const response_start = trans->GetResponseInfo();
5254 ASSERT_TRUE(response_start != NULL);
5255 ASSERT_TRUE(response_start->headers.get() != NULL);
5256 EXPECT_EQ(401, response_start->headers->response_code());
5257 EXPECT_TRUE(response_start->was_fetched_via_spdy);
5258 AuthChallengeInfo* auth_challenge = response_start->auth_challenge.get();
5259 ASSERT_TRUE(auth_challenge != NULL);
5260 EXPECT_FALSE(auth_challenge->is_proxy);
5261 EXPECT_EQ("basic", auth_challenge->scheme);
5262 EXPECT_EQ("MyRealm", auth_challenge->realm);
5264 // Restart with a username/password.
5265 AuthCredentials credentials(base::ASCIIToUTF16("foo"),
5266 base::ASCIIToUTF16("bar"));
5267 TestCompletionCallback callback_restart;
5268 const int rv_restart = trans->RestartWithAuth(
5269 credentials, callback_restart.callback());
5270 EXPECT_EQ(ERR_IO_PENDING, rv_restart);
5271 const int rv_restart_complete = callback_restart.WaitForResult();
5272 EXPECT_EQ(OK, rv_restart_complete);
5273 // TODO(cbentzel): This is actually the same response object as before, but
5274 // data has changed.
5275 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
5276 ASSERT_TRUE(response_restart != NULL);
5277 ASSERT_TRUE(response_restart->headers.get() != NULL);
5278 EXPECT_EQ(200, response_restart->headers->response_code());
5279 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
5282 TEST_P(SpdyNetworkTransactionTest, ServerPushWithHeaders) {
5283 scoped_ptr<SpdyFrame> stream1_syn(
5284 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5285 scoped_ptr<SpdyFrame> stream1_body(
5286 spdy_util_.ConstructSpdyBodyFrame(1, true));
5287 MockWrite writes[] = {
5288 CreateMockWrite(*stream1_syn, 1),
5291 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5292 spdy_util_.AddUrlToHeaderBlock(
5293 "http://www.google.com/foo.dat", initial_headers.get());
5294 scoped_ptr<SpdyFrame> stream2_syn(
5295 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
5297 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5298 (*late_headers)["hello"] = "bye";
5299 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5300 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5301 scoped_ptr<SpdyFrame> stream2_headers(
5302 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5303 false,
5305 LOWEST,
5306 HEADERS,
5307 CONTROL_FLAG_NONE,
5308 0));
5310 scoped_ptr<SpdyFrame>
5311 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5312 const char kPushedData[] = "pushed";
5313 scoped_ptr<SpdyFrame> stream2_body(
5314 spdy_util_.ConstructSpdyBodyFrame(
5315 2, kPushedData, strlen(kPushedData), true));
5316 MockRead reads[] = {
5317 CreateMockRead(*stream1_reply, 2),
5318 CreateMockRead(*stream2_syn, 3),
5319 CreateMockRead(*stream2_headers, 4),
5320 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
5321 CreateMockRead(*stream2_body, 5),
5322 MockRead(ASYNC, ERR_IO_PENDING, 7), // Force a pause
5325 HttpResponseInfo response;
5326 HttpResponseInfo response2;
5327 std::string expected_push_result("pushed");
5328 OrderedSocketData data(reads, arraysize(reads),
5329 writes, arraysize(writes));
5330 RunServerPushTest(&data,
5331 &response,
5332 &response2,
5333 expected_push_result);
5335 // Verify the SYN_REPLY.
5336 EXPECT_TRUE(response.headers.get() != NULL);
5337 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5339 // Verify the pushed stream.
5340 EXPECT_TRUE(response2.headers.get() != NULL);
5341 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5344 TEST_P(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
5345 // We push a stream and attempt to claim it before the headers come down.
5346 scoped_ptr<SpdyFrame> stream1_syn(
5347 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5348 scoped_ptr<SpdyFrame> stream1_body(
5349 spdy_util_.ConstructSpdyBodyFrame(1, true));
5350 MockWrite writes[] = {
5351 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5354 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5355 spdy_util_.AddUrlToHeaderBlock(
5356 "http://www.google.com/foo.dat", initial_headers.get());
5357 scoped_ptr<SpdyFrame> stream2_syn(
5358 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
5360 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5361 (*late_headers)["hello"] = "bye";
5362 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5363 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5364 scoped_ptr<SpdyFrame> stream2_headers(
5365 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5366 false,
5368 LOWEST,
5369 HEADERS,
5370 CONTROL_FLAG_NONE,
5371 0));
5373 scoped_ptr<SpdyFrame>
5374 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5375 const char kPushedData[] = "pushed";
5376 scoped_ptr<SpdyFrame> stream2_body(
5377 spdy_util_.ConstructSpdyBodyFrame(
5378 2, kPushedData, strlen(kPushedData), true));
5379 MockRead reads[] = {
5380 CreateMockRead(*stream1_reply, 1),
5381 CreateMockRead(*stream2_syn, 2),
5382 CreateMockRead(*stream1_body, 3),
5383 CreateMockRead(*stream2_headers, 4),
5384 CreateMockRead(*stream2_body, 5),
5385 MockRead(ASYNC, 0, 6), // EOF
5388 HttpResponseInfo response;
5389 HttpResponseInfo response2;
5390 std::string expected_push_result("pushed");
5391 DeterministicSocketData data(reads, arraysize(reads),
5392 writes, arraysize(writes));
5394 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5395 BoundNetLog(), GetParam(), NULL);
5396 helper.SetDeterministic();
5397 helper.AddDeterministicData(&data);
5398 helper.RunPreTestSetup();
5400 HttpNetworkTransaction* trans = helper.trans();
5402 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5403 // and the body of the primary stream, but before we've received the HEADERS
5404 // for the pushed stream.
5405 data.SetStop(3);
5407 // Start the transaction.
5408 TestCompletionCallback callback;
5409 int rv = trans->Start(
5410 &CreateGetRequest(), callback.callback(), BoundNetLog());
5411 EXPECT_EQ(ERR_IO_PENDING, rv);
5412 data.Run();
5413 rv = callback.WaitForResult();
5414 EXPECT_EQ(0, rv);
5416 // Request the pushed path. At this point, we've received the push, but the
5417 // headers are not yet complete.
5418 scoped_ptr<HttpNetworkTransaction> trans2(
5419 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5420 rv = trans2->Start(
5421 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5422 EXPECT_EQ(ERR_IO_PENDING, rv);
5423 data.RunFor(3);
5424 base::RunLoop().RunUntilIdle();
5426 // Read the server push body.
5427 std::string result2;
5428 ReadResult(trans2.get(), &data, &result2);
5429 // Read the response body.
5430 std::string result;
5431 ReadResult(trans, &data, &result);
5433 // Verify that the received push data is same as the expected push data.
5434 EXPECT_EQ(result2.compare(expected_push_result), 0)
5435 << "Received data: "
5436 << result2
5437 << "||||| Expected data: "
5438 << expected_push_result;
5440 // Verify the SYN_REPLY.
5441 // Copy the response info, because trans goes away.
5442 response = *trans->GetResponseInfo();
5443 response2 = *trans2->GetResponseInfo();
5445 VerifyStreamsClosed(helper);
5447 // Verify the SYN_REPLY.
5448 EXPECT_TRUE(response.headers.get() != NULL);
5449 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5451 // Verify the pushed stream.
5452 EXPECT_TRUE(response2.headers.get() != NULL);
5453 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5455 // Read the final EOF (which will close the session)
5456 data.RunFor(1);
5458 // Verify that we consumed all test data.
5459 EXPECT_TRUE(data.at_read_eof());
5460 EXPECT_TRUE(data.at_write_eof());
5463 // TODO(baranovich): HTTP 2 does not allow multiple HEADERS frames
5464 TEST_P(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) {
5465 // We push a stream and attempt to claim it before the headers come down.
5466 scoped_ptr<SpdyFrame> stream1_syn(
5467 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5468 scoped_ptr<SpdyFrame> stream1_body(
5469 spdy_util_.ConstructSpdyBodyFrame(1, true));
5470 MockWrite writes[] = {
5471 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5474 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5475 if (spdy_util_.spdy_version() < SPDY4) {
5476 // In SPDY4 PUSH_PROMISE headers won't show up in the response headers.
5477 (*initial_headers)["alpha"] = "beta";
5479 spdy_util_.AddUrlToHeaderBlock(
5480 "http://www.google.com/foo.dat", initial_headers.get());
5481 scoped_ptr<SpdyFrame> stream2_syn(
5482 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
5484 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5485 (*middle_headers)["hello"] = "bye";
5486 scoped_ptr<SpdyFrame> stream2_headers1(
5487 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(),
5488 false,
5490 LOWEST,
5491 HEADERS,
5492 CONTROL_FLAG_NONE,
5493 0));
5495 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5496 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5497 if (spdy_util_.spdy_version() < SPDY4) {
5498 // SPDY4/HTTP2 eliminates use of the :version header.
5499 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5501 scoped_ptr<SpdyFrame> stream2_headers2(
5502 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5503 false,
5505 LOWEST,
5506 HEADERS,
5507 CONTROL_FLAG_NONE,
5508 0));
5510 scoped_ptr<SpdyFrame>
5511 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5512 const char kPushedData[] = "pushed";
5513 scoped_ptr<SpdyFrame> stream2_body(
5514 spdy_util_.ConstructSpdyBodyFrame(
5515 2, kPushedData, strlen(kPushedData), true));
5516 MockRead reads[] = {
5517 CreateMockRead(*stream1_reply, 1),
5518 CreateMockRead(*stream2_syn, 2),
5519 CreateMockRead(*stream1_body, 3),
5520 CreateMockRead(*stream2_headers1, 4),
5521 CreateMockRead(*stream2_headers2, 5),
5522 CreateMockRead(*stream2_body, 6),
5523 MockRead(ASYNC, 0, 7), // EOF
5526 HttpResponseInfo response;
5527 HttpResponseInfo response2;
5528 std::string expected_push_result("pushed");
5529 DeterministicSocketData data(reads, arraysize(reads),
5530 writes, arraysize(writes));
5532 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5533 BoundNetLog(), GetParam(), NULL);
5534 helper.SetDeterministic();
5535 helper.AddDeterministicData(&data);
5536 helper.RunPreTestSetup();
5538 HttpNetworkTransaction* trans = helper.trans();
5540 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5541 // the first HEADERS frame, and the body of the primary stream, but before
5542 // we've received the final HEADERS for the pushed stream.
5543 data.SetStop(4);
5545 // Start the transaction.
5546 TestCompletionCallback callback;
5547 int rv = trans->Start(
5548 &CreateGetRequest(), callback.callback(), BoundNetLog());
5549 EXPECT_EQ(ERR_IO_PENDING, rv);
5550 data.Run();
5551 rv = callback.WaitForResult();
5552 EXPECT_EQ(0, rv);
5554 // Request the pushed path. At this point, we've received the push, but the
5555 // headers are not yet complete.
5556 scoped_ptr<HttpNetworkTransaction> trans2(
5557 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5558 rv = trans2->Start(
5559 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5560 EXPECT_EQ(ERR_IO_PENDING, rv);
5561 data.RunFor(3);
5562 base::RunLoop().RunUntilIdle();
5564 // Read the server push body.
5565 std::string result2;
5566 ReadResult(trans2.get(), &data, &result2);
5567 // Read the response body.
5568 std::string result;
5569 ReadResult(trans, &data, &result);
5571 // Verify that the received push data is same as the expected push data.
5572 EXPECT_EQ(expected_push_result, result2);
5574 // Verify the SYN_REPLY.
5575 // Copy the response info, because trans goes away.
5576 response = *trans->GetResponseInfo();
5577 response2 = *trans2->GetResponseInfo();
5579 VerifyStreamsClosed(helper);
5581 // Verify the SYN_REPLY.
5582 EXPECT_TRUE(response.headers.get() != NULL);
5583 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5585 // Verify the pushed stream.
5586 EXPECT_TRUE(response2.headers.get() != NULL);
5587 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5589 // Verify we got all the headers from all header blocks.
5590 if (spdy_util_.spdy_version() < SPDY4)
5591 EXPECT_TRUE(response2.headers->HasHeaderValue("alpha", "beta"));
5592 EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye"));
5593 EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200"));
5595 // Read the final EOF (which will close the session)
5596 data.RunFor(1);
5598 // Verify that we consumed all test data.
5599 EXPECT_TRUE(data.at_read_eof());
5600 EXPECT_TRUE(data.at_write_eof());
5603 TEST_P(SpdyNetworkTransactionTest, ServerPushWithNoStatusHeaderFrames) {
5604 // We push a stream and attempt to claim it before the headers come down.
5605 scoped_ptr<SpdyFrame> stream1_syn(
5606 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5607 scoped_ptr<SpdyFrame> stream1_body(
5608 spdy_util_.ConstructSpdyBodyFrame(1, true));
5609 MockWrite writes[] = {
5610 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5613 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5614 spdy_util_.AddUrlToHeaderBlock(
5615 "http://www.google.com/foo.dat", initial_headers.get());
5616 scoped_ptr<SpdyFrame> stream2_syn(
5617 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
5619 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5620 (*middle_headers)["hello"] = "bye";
5621 scoped_ptr<SpdyFrame> stream2_headers1(
5622 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(),
5623 false,
5625 LOWEST,
5626 HEADERS,
5627 CONTROL_FLAG_NONE,
5628 0));
5630 scoped_ptr<SpdyFrame>
5631 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5632 const char kPushedData[] = "pushed";
5633 scoped_ptr<SpdyFrame> stream2_body(
5634 spdy_util_.ConstructSpdyBodyFrame(
5635 2, kPushedData, strlen(kPushedData), true));
5636 MockRead reads[] = {
5637 CreateMockRead(*stream1_reply, 1),
5638 CreateMockRead(*stream2_syn, 2),
5639 CreateMockRead(*stream1_body, 3),
5640 CreateMockRead(*stream2_headers1, 4),
5641 CreateMockRead(*stream2_body, 5),
5642 MockRead(ASYNC, 0, 6), // EOF
5645 DeterministicSocketData data(reads, arraysize(reads),
5646 writes, arraysize(writes));
5648 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5649 BoundNetLog(), GetParam(), NULL);
5650 helper.SetDeterministic();
5651 helper.AddDeterministicData(&data);
5652 helper.RunPreTestSetup();
5654 HttpNetworkTransaction* trans = helper.trans();
5656 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5657 // the first HEADERS frame, and the body of the primary stream, but before
5658 // we've received the final HEADERS for the pushed stream.
5659 data.SetStop(4);
5661 // Start the transaction.
5662 TestCompletionCallback callback;
5663 int rv = trans->Start(
5664 &CreateGetRequest(), callback.callback(), BoundNetLog());
5665 EXPECT_EQ(ERR_IO_PENDING, rv);
5666 data.Run();
5667 rv = callback.WaitForResult();
5668 EXPECT_EQ(0, rv);
5670 // Request the pushed path. At this point, we've received the push, but the
5671 // headers are not yet complete.
5672 scoped_ptr<HttpNetworkTransaction> trans2(
5673 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5674 rv = trans2->Start(
5675 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5676 EXPECT_EQ(ERR_IO_PENDING, rv);
5677 data.RunFor(2);
5678 base::RunLoop().RunUntilIdle();
5680 // Read the server push body.
5681 std::string result2;
5682 ReadResult(trans2.get(), &data, &result2);
5683 // Read the response body.
5684 std::string result;
5685 ReadResult(trans, &data, &result);
5686 EXPECT_EQ("hello!", result);
5688 // Verify that we haven't received any push data.
5689 EXPECT_EQ("", result2);
5691 // Verify the SYN_REPLY.
5692 // Copy the response info, because trans goes away.
5693 HttpResponseInfo response = *trans->GetResponseInfo();
5694 ASSERT_TRUE(trans2->GetResponseInfo() == NULL);
5696 VerifyStreamsClosed(helper);
5698 // Verify the SYN_REPLY.
5699 EXPECT_TRUE(response.headers.get() != NULL);
5700 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5702 // Read the final EOF (which will close the session).
5703 data.RunFor(1);
5705 // Verify that we consumed all test data.
5706 EXPECT_TRUE(data.at_read_eof());
5707 EXPECT_TRUE(data.at_write_eof());
5710 TEST_P(SpdyNetworkTransactionTest, SynReplyWithHeaders) {
5711 scoped_ptr<SpdyFrame> req(
5712 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5713 scoped_ptr<SpdyFrame> rst(
5714 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
5715 MockWrite writes[] = {
5716 CreateMockWrite(*req), CreateMockWrite(*rst),
5719 scoped_ptr<SpdyFrame> stream1_reply(
5720 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5722 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5723 (*late_headers)["hello"] = "bye";
5724 scoped_ptr<SpdyFrame> stream1_headers(
5725 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5726 false,
5728 LOWEST,
5729 HEADERS,
5730 CONTROL_FLAG_NONE,
5731 0));
5732 scoped_ptr<SpdyFrame> stream1_body(
5733 spdy_util_.ConstructSpdyBodyFrame(1, true));
5734 MockRead reads[] = {
5735 CreateMockRead(*stream1_reply),
5736 CreateMockRead(*stream1_headers),
5737 CreateMockRead(*stream1_body),
5738 MockRead(ASYNC, 0, 0) // EOF
5741 DelayedSocketData data(1, reads, arraysize(reads),
5742 writes, arraysize(writes));
5743 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5744 BoundNetLog(), GetParam(), NULL);
5745 helper.RunToCompletion(&data);
5746 TransactionHelperResult out = helper.output();
5747 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
5750 TEST_P(SpdyNetworkTransactionTest, SynReplyWithLateHeaders) {
5751 scoped_ptr<SpdyFrame> req(
5752 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5753 scoped_ptr<SpdyFrame> rst(
5754 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
5755 MockWrite writes[] = {
5756 CreateMockWrite(*req),
5757 CreateMockWrite(*rst),
5760 scoped_ptr<SpdyFrame> stream1_reply(
5761 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5763 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5764 (*late_headers)["hello"] = "bye";
5765 scoped_ptr<SpdyFrame> stream1_headers(
5766 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5767 false,
5769 LOWEST,
5770 HEADERS,
5771 CONTROL_FLAG_NONE,
5772 0));
5773 scoped_ptr<SpdyFrame> stream1_body(
5774 spdy_util_.ConstructSpdyBodyFrame(1, false));
5775 scoped_ptr<SpdyFrame> stream1_body2(
5776 spdy_util_.ConstructSpdyBodyFrame(1, true));
5777 MockRead reads[] = {
5778 CreateMockRead(*stream1_reply),
5779 CreateMockRead(*stream1_body),
5780 CreateMockRead(*stream1_headers),
5781 CreateMockRead(*stream1_body2),
5782 MockRead(ASYNC, 0, 0) // EOF
5785 DelayedSocketData data(1, reads, arraysize(reads),
5786 writes, arraysize(writes));
5787 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5788 BoundNetLog(), GetParam(), NULL);
5789 helper.RunToCompletion(&data);
5790 TransactionHelperResult out = helper.output();
5791 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
5794 TEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
5795 // In this test we want to verify that we can't accidentally push content
5796 // which can't be pushed by this content server.
5797 // This test assumes that:
5798 // - if we're requesting http://www.foo.com/barbaz
5799 // - the browser has made a connection to "www.foo.com".
5801 // A list of the URL to fetch, followed by the URL being pushed.
5802 static const char* const kTestCases[] = {
5803 "http://www.google.com/foo.html",
5804 "http://www.google.com:81/foo.js", // Bad port
5806 "http://www.google.com/foo.html",
5807 "https://www.google.com/foo.js", // Bad protocol
5809 "http://www.google.com/foo.html",
5810 "ftp://www.google.com/foo.js", // Invalid Protocol
5812 "http://www.google.com/foo.html",
5813 "http://blat.www.google.com/foo.js", // Cross subdomain
5815 "http://www.google.com/foo.html",
5816 "http://www.foo.com/foo.js", // Cross domain
5819 for (size_t index = 0; index < arraysize(kTestCases); index += 2) {
5820 const char* url_to_fetch = kTestCases[index];
5821 const char* url_to_push = kTestCases[index + 1];
5823 scoped_ptr<SpdyFrame> stream1_syn(
5824 spdy_util_.ConstructSpdyGet(url_to_fetch, false, 1, LOWEST));
5825 scoped_ptr<SpdyFrame> stream1_body(
5826 spdy_util_.ConstructSpdyBodyFrame(1, true));
5827 scoped_ptr<SpdyFrame> push_rst(
5828 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
5829 MockWrite writes[] = {
5830 CreateMockWrite(*stream1_syn, 1),
5831 CreateMockWrite(*push_rst, 4),
5834 scoped_ptr<SpdyFrame>
5835 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5836 scoped_ptr<SpdyFrame>
5837 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
5841 url_to_push));
5842 const char kPushedData[] = "pushed";
5843 scoped_ptr<SpdyFrame> stream2_body(
5844 spdy_util_.ConstructSpdyBodyFrame(
5845 2, kPushedData, strlen(kPushedData), true));
5846 scoped_ptr<SpdyFrame> rst(
5847 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
5849 MockRead reads[] = {
5850 CreateMockRead(*stream1_reply, 2),
5851 CreateMockRead(*stream2_syn, 3),
5852 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
5853 CreateMockRead(*stream2_body, 6),
5854 MockRead(ASYNC, ERR_IO_PENDING, 7), // Force a pause
5857 HttpResponseInfo response;
5858 OrderedSocketData data(reads, arraysize(reads),
5859 writes, arraysize(writes));
5861 HttpRequestInfo request;
5862 request.method = "GET";
5863 request.url = GURL(url_to_fetch);
5864 request.load_flags = 0;
5866 // Enable cross-origin push. Since we are not using a proxy, this should
5867 // not actually enable cross-origin SPDY push.
5868 scoped_ptr<SpdySessionDependencies> session_deps(
5869 CreateSpdySessionDependencies(GetParam()));
5870 session_deps->trusted_spdy_proxy = "123.45.67.89:8080";
5871 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5872 BoundNetLog(), GetParam(),
5873 session_deps.release());
5874 helper.RunPreTestSetup();
5875 helper.AddData(&data);
5877 HttpNetworkTransaction* trans = helper.trans();
5879 // Start the transaction with basic parameters.
5880 TestCompletionCallback callback;
5882 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5883 EXPECT_EQ(ERR_IO_PENDING, rv);
5884 rv = callback.WaitForResult();
5886 // Read the response body.
5887 std::string result;
5888 ReadResult(trans, &data, &result);
5890 // Verify that we consumed all test data.
5891 EXPECT_TRUE(data.at_read_eof());
5892 EXPECT_TRUE(data.at_write_eof());
5894 // Verify the SYN_REPLY.
5895 // Copy the response info, because trans goes away.
5896 response = *trans->GetResponseInfo();
5898 VerifyStreamsClosed(helper);
5900 // Verify the SYN_REPLY.
5901 EXPECT_TRUE(response.headers.get() != NULL);
5902 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5906 TEST_P(SpdyNetworkTransactionTest, RetryAfterRefused) {
5907 // Construct the request.
5908 scoped_ptr<SpdyFrame> req(
5909 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5910 scoped_ptr<SpdyFrame> req2(
5911 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
5912 MockWrite writes[] = {
5913 CreateMockWrite(*req, 1),
5914 CreateMockWrite(*req2, 3),
5917 scoped_ptr<SpdyFrame> refused(
5918 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
5919 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5920 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(3, true));
5921 MockRead reads[] = {
5922 CreateMockRead(*refused, 2),
5923 CreateMockRead(*resp, 4),
5924 CreateMockRead(*body, 5),
5925 MockRead(ASYNC, 0, 6) // EOF
5928 OrderedSocketData data(reads, arraysize(reads),
5929 writes, arraysize(writes));
5930 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5931 BoundNetLog(), GetParam(), NULL);
5933 helper.RunPreTestSetup();
5934 helper.AddData(&data);
5936 HttpNetworkTransaction* trans = helper.trans();
5938 // Start the transaction with basic parameters.
5939 TestCompletionCallback callback;
5940 int rv = trans->Start(
5941 &CreateGetRequest(), callback.callback(), BoundNetLog());
5942 EXPECT_EQ(ERR_IO_PENDING, rv);
5943 rv = callback.WaitForResult();
5944 EXPECT_EQ(OK, rv);
5946 // Verify that we consumed all test data.
5947 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
5948 << data.read_count()
5949 << " Read index: "
5950 << data.read_index();
5951 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
5952 << data.write_count()
5953 << " Write index: "
5954 << data.write_index();
5956 // Verify the SYN_REPLY.
5957 HttpResponseInfo response = *trans->GetResponseInfo();
5958 EXPECT_TRUE(response.headers.get() != NULL);
5959 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5962 TEST_P(SpdyNetworkTransactionTest, OutOfOrderSynStream) {
5963 // This first request will start to establish the SpdySession.
5964 // Then we will start the second (MEDIUM priority) and then third
5965 // (HIGHEST priority) request in such a way that the third will actually
5966 // start before the second, causing the second to be numbered differently
5967 // than the order they were created.
5968 scoped_ptr<SpdyFrame> req1(
5969 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5970 scoped_ptr<SpdyFrame> req2(
5971 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, HIGHEST, true));
5972 scoped_ptr<SpdyFrame> req3(
5973 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, MEDIUM, true));
5974 MockWrite writes[] = {
5975 CreateMockWrite(*req1, 0),
5976 CreateMockWrite(*req2, 3),
5977 CreateMockWrite(*req3, 4),
5980 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5981 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
5982 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5983 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
5984 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
5985 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
5986 MockRead reads[] = {
5987 CreateMockRead(*resp1, 1),
5988 CreateMockRead(*body1, 2),
5989 CreateMockRead(*resp2, 5),
5990 CreateMockRead(*body2, 6),
5991 CreateMockRead(*resp3, 7),
5992 CreateMockRead(*body3, 8),
5993 MockRead(ASYNC, 0, 9) // EOF
5996 DeterministicSocketData data(reads, arraysize(reads),
5997 writes, arraysize(writes));
5998 NormalSpdyTransactionHelper helper(CreateGetRequest(), LOWEST,
5999 BoundNetLog(), GetParam(), NULL);
6000 helper.SetDeterministic();
6001 helper.RunPreTestSetup();
6002 helper.AddDeterministicData(&data);
6004 // Start the first transaction to set up the SpdySession
6005 HttpNetworkTransaction* trans = helper.trans();
6006 TestCompletionCallback callback;
6007 HttpRequestInfo info1 = CreateGetRequest();
6008 int rv = trans->Start(&info1, callback.callback(), BoundNetLog());
6009 EXPECT_EQ(ERR_IO_PENDING, rv);
6011 // Run the message loop, but do not allow the write to complete.
6012 // This leaves the SpdySession with a write pending, which prevents
6013 // SpdySession from attempting subsequent writes until this write completes.
6014 base::RunLoop().RunUntilIdle();
6016 // Now, start both new transactions
6017 HttpRequestInfo info2 = CreateGetRequest();
6018 TestCompletionCallback callback2;
6019 scoped_ptr<HttpNetworkTransaction> trans2(
6020 new HttpNetworkTransaction(MEDIUM, helper.session().get()));
6021 rv = trans2->Start(&info2, callback2.callback(), BoundNetLog());
6022 EXPECT_EQ(ERR_IO_PENDING, rv);
6023 base::RunLoop().RunUntilIdle();
6025 HttpRequestInfo info3 = CreateGetRequest();
6026 TestCompletionCallback callback3;
6027 scoped_ptr<HttpNetworkTransaction> trans3(
6028 new HttpNetworkTransaction(HIGHEST, helper.session().get()));
6029 rv = trans3->Start(&info3, callback3.callback(), BoundNetLog());
6030 EXPECT_EQ(ERR_IO_PENDING, rv);
6031 base::RunLoop().RunUntilIdle();
6033 // We now have two SYN_STREAM frames queued up which will be
6034 // dequeued only once the first write completes, which we
6035 // now allow to happen.
6036 data.RunFor(2);
6037 EXPECT_EQ(OK, callback.WaitForResult());
6039 // And now we can allow everything else to run to completion.
6040 data.SetStop(10);
6041 data.Run();
6042 EXPECT_EQ(OK, callback2.WaitForResult());
6043 EXPECT_EQ(OK, callback3.WaitForResult());
6045 helper.VerifyDataConsumed();
6048 // The tests below are only for SPDY/3 and above.
6050 // Test that sent data frames and received WINDOW_UPDATE frames change
6051 // the send_window_size_ correctly.
6053 // WINDOW_UPDATE is different than most other frames in that it can arrive
6054 // while the client is still sending the request body. In order to enforce
6055 // this scenario, we feed a couple of dummy frames and give a delay of 0 to
6056 // socket data provider, so that initial read that is done as soon as the
6057 // stream is created, succeeds and schedules another read. This way reads
6058 // and writes are interleaved; after doing a full frame write, SpdyStream
6059 // will break out of DoLoop and will read and process a WINDOW_UPDATE.
6060 // Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
6061 // since request has not been completely written, therefore we feed
6062 // enough number of WINDOW_UPDATEs to finish the first read and cause a
6063 // write, leading to a complete write of request body; after that we send
6064 // a reply with a body, to cause a graceful shutdown.
6066 // TODO(agayev): develop a socket data provider where both, reads and
6067 // writes are ordered so that writing tests like these are easy and rewrite
6068 // all these tests using it. Right now we are working around the
6069 // limitations as described above and it's not deterministic, tests may
6070 // fail under specific circumstances.
6071 TEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) {
6072 static int kFrameCount = 2;
6073 scoped_ptr<std::string> content(
6074 new std::string(kMaxSpdyFrameChunkSize, 'a'));
6075 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6076 kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
6077 scoped_ptr<SpdyFrame> body(
6078 spdy_util_.ConstructSpdyBodyFrame(
6079 1, content->c_str(), content->size(), false));
6080 scoped_ptr<SpdyFrame> body_end(
6081 spdy_util_.ConstructSpdyBodyFrame(
6082 1, content->c_str(), content->size(), true));
6084 MockWrite writes[] = {
6085 CreateMockWrite(*req, 0),
6086 CreateMockWrite(*body, 1),
6087 CreateMockWrite(*body_end, 2),
6090 static const int32 kDeltaWindowSize = 0xff;
6091 static const int kDeltaCount = 4;
6092 scoped_ptr<SpdyFrame> window_update(
6093 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
6094 scoped_ptr<SpdyFrame> window_update_dummy(
6095 spdy_util_.ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
6096 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6097 MockRead reads[] = {
6098 CreateMockRead(*window_update_dummy, 3),
6099 CreateMockRead(*window_update_dummy, 4),
6100 CreateMockRead(*window_update_dummy, 5),
6101 CreateMockRead(*window_update, 6), // Four updates, therefore window
6102 CreateMockRead(*window_update, 7), // size should increase by
6103 CreateMockRead(*window_update, 8), // kDeltaWindowSize * 4
6104 CreateMockRead(*window_update, 9),
6105 CreateMockRead(*resp, 10),
6106 CreateMockRead(*body_end, 11),
6107 MockRead(ASYNC, 0, 0, 12) // EOF
6110 DeterministicSocketData data(reads, arraysize(reads),
6111 writes, arraysize(writes));
6113 ScopedVector<UploadElementReader> element_readers;
6114 for (int i = 0; i < kFrameCount; ++i) {
6115 element_readers.push_back(
6116 new UploadBytesElementReader(content->c_str(), content->size()));
6118 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
6120 // Setup the request
6121 HttpRequestInfo request;
6122 request.method = "POST";
6123 request.url = GURL(kDefaultURL);
6124 request.upload_data_stream = &upload_data_stream;
6126 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6127 BoundNetLog(), GetParam(), NULL);
6128 helper.SetDeterministic();
6129 helper.AddDeterministicData(&data);
6130 helper.RunPreTestSetup();
6132 HttpNetworkTransaction* trans = helper.trans();
6134 TestCompletionCallback callback;
6135 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6137 EXPECT_EQ(ERR_IO_PENDING, rv);
6139 data.RunFor(11);
6141 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6142 ASSERT_TRUE(stream != NULL);
6143 ASSERT_TRUE(stream->stream() != NULL);
6144 EXPECT_EQ(
6145 static_cast<int>(SpdySession::GetInitialWindowSize(GetParam().protocol)) +
6146 kDeltaWindowSize * kDeltaCount - kMaxSpdyFrameChunkSize * kFrameCount,
6147 stream->stream()->send_window_size());
6149 data.RunFor(1);
6151 rv = callback.WaitForResult();
6152 EXPECT_EQ(OK, rv);
6154 helper.VerifyDataConsumed();
6157 // Test that received data frames and sent WINDOW_UPDATE frames change
6158 // the recv_window_size_ correctly.
6159 TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) {
6160 const int32 initial_window_size =
6161 SpdySession::GetInitialWindowSize(GetParam().protocol);
6162 // Amount of body required to trigger a sent window update.
6163 const size_t kTargetSize = initial_window_size / 2 + 1;
6165 scoped_ptr<SpdyFrame> req(
6166 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
6167 scoped_ptr<SpdyFrame> session_window_update(
6168 spdy_util_.ConstructSpdyWindowUpdate(0, kTargetSize));
6169 scoped_ptr<SpdyFrame> window_update(
6170 spdy_util_.ConstructSpdyWindowUpdate(1, kTargetSize));
6172 std::vector<MockWrite> writes;
6173 writes.push_back(CreateMockWrite(*req));
6174 if (GetParam().protocol >= kProtoSPDY31)
6175 writes.push_back(CreateMockWrite(*session_window_update));
6176 writes.push_back(CreateMockWrite(*window_update));
6178 std::vector<MockRead> reads;
6179 scoped_ptr<SpdyFrame> resp(
6180 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6181 reads.push_back(CreateMockRead(*resp));
6183 ScopedVector<SpdyFrame> body_frames;
6184 const std::string body_data(4096, 'x');
6185 for (size_t remaining = kTargetSize; remaining != 0;) {
6186 size_t frame_size = std::min(remaining, body_data.size());
6187 body_frames.push_back(spdy_util_.ConstructSpdyBodyFrame(
6188 1, body_data.data(), frame_size, false));
6189 reads.push_back(CreateMockRead(*body_frames.back()));
6190 remaining -= frame_size;
6192 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, 0)); // Yield.
6194 DelayedSocketData data(1, vector_as_array(&reads), reads.size(),
6195 vector_as_array(&writes), writes.size());
6197 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
6198 BoundNetLog(), GetParam(), NULL);
6199 helper.AddData(&data);
6200 helper.RunPreTestSetup();
6201 HttpNetworkTransaction* trans = helper.trans();
6203 TestCompletionCallback callback;
6204 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6206 EXPECT_EQ(ERR_IO_PENDING, rv);
6207 rv = callback.WaitForResult();
6208 EXPECT_EQ(OK, rv);
6210 SpdyHttpStream* stream =
6211 static_cast<SpdyHttpStream*>(trans->stream_.get());
6212 ASSERT_TRUE(stream != NULL);
6213 ASSERT_TRUE(stream->stream() != NULL);
6215 // All data has been read, but not consumed. The window reflects this.
6216 EXPECT_EQ(static_cast<int>(initial_window_size - kTargetSize),
6217 stream->stream()->recv_window_size());
6219 const HttpResponseInfo* response = trans->GetResponseInfo();
6220 ASSERT_TRUE(response != NULL);
6221 ASSERT_TRUE(response->headers.get() != NULL);
6222 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6223 EXPECT_TRUE(response->was_fetched_via_spdy);
6225 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
6226 // size increased to default.
6227 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kTargetSize));
6228 EXPECT_EQ(static_cast<int>(kTargetSize),
6229 trans->Read(buf.get(), kTargetSize, CompletionCallback()));
6230 EXPECT_EQ(static_cast<int>(initial_window_size),
6231 stream->stream()->recv_window_size());
6232 EXPECT_THAT(base::StringPiece(buf->data(), kTargetSize), Each(Eq('x')));
6234 // Allow scheduled WINDOW_UPDATE frames to write.
6235 base::RunLoop().RunUntilIdle();
6236 helper.VerifyDataConsumed();
6239 // Test that WINDOW_UPDATE frame causing overflow is handled correctly.
6240 TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
6241 // Number of full frames we hope to write (but will not, used to
6242 // set content-length header correctly)
6243 static int kFrameCount = 3;
6245 scoped_ptr<std::string> content(
6246 new std::string(kMaxSpdyFrameChunkSize, 'a'));
6247 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6248 kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
6249 scoped_ptr<SpdyFrame> body(
6250 spdy_util_.ConstructSpdyBodyFrame(
6251 1, content->c_str(), content->size(), false));
6252 scoped_ptr<SpdyFrame> rst(
6253 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
6255 // We're not going to write a data frame with FIN, we'll receive a bad
6256 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
6257 MockWrite writes[] = {
6258 CreateMockWrite(*req, 0),
6259 CreateMockWrite(*body, 2),
6260 CreateMockWrite(*rst, 3),
6263 static const int32 kDeltaWindowSize = 0x7fffffff; // cause an overflow
6264 scoped_ptr<SpdyFrame> window_update(
6265 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
6266 MockRead reads[] = {
6267 CreateMockRead(*window_update, 1),
6268 MockRead(ASYNC, 0, 4) // EOF
6271 DeterministicSocketData data(reads, arraysize(reads),
6272 writes, arraysize(writes));
6274 ScopedVector<UploadElementReader> element_readers;
6275 for (int i = 0; i < kFrameCount; ++i) {
6276 element_readers.push_back(
6277 new UploadBytesElementReader(content->c_str(), content->size()));
6279 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
6281 // Setup the request
6282 HttpRequestInfo request;
6283 request.method = "POST";
6284 request.url = GURL("http://www.google.com/");
6285 request.upload_data_stream = &upload_data_stream;
6287 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6288 BoundNetLog(), GetParam(), NULL);
6289 helper.SetDeterministic();
6290 helper.RunPreTestSetup();
6291 helper.AddDeterministicData(&data);
6292 HttpNetworkTransaction* trans = helper.trans();
6294 TestCompletionCallback callback;
6295 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6296 ASSERT_EQ(ERR_IO_PENDING, rv);
6298 data.RunFor(5);
6299 ASSERT_TRUE(callback.have_result());
6300 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, callback.WaitForResult());
6301 helper.VerifyDataConsumed();
6304 // Test that after hitting a send window size of 0, the write process
6305 // stalls and upon receiving WINDOW_UPDATE frame write resumes.
6307 // This test constructs a POST request followed by enough data frames
6308 // containing 'a' that would make the window size 0, followed by another
6309 // data frame containing default content (which is "hello!") and this frame
6310 // also contains a FIN flag. DelayedSocketData is used to enforce all
6311 // writes go through before a read could happen. However, the last frame
6312 // ("hello!") is not supposed to go through since by the time its turn
6313 // arrives, window size is 0. At this point MessageLoop::Run() called via
6314 // callback would block. Therefore we call MessageLoop::RunUntilIdle()
6315 // which returns after performing all possible writes. We use DCHECKS to
6316 // ensure that last data frame is still there and stream has stalled.
6317 // After that, next read is artifically enforced, which causes a
6318 // WINDOW_UPDATE to be read and I/O process resumes.
6319 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) {
6320 const int32 initial_window_size =
6321 SpdySession::GetInitialWindowSize(GetParam().protocol);
6322 // Number of frames we need to send to zero out the window size: data
6323 // frames plus SYN_STREAM plus the last data frame; also we need another
6324 // data frame that we will send once the WINDOW_UPDATE is received,
6325 // therefore +3.
6326 size_t num_writes = initial_window_size / kMaxSpdyFrameChunkSize + 3;
6328 // Calculate last frame's size; 0 size data frame is legal.
6329 size_t last_frame_size = initial_window_size % kMaxSpdyFrameChunkSize;
6331 // Construct content for a data frame of maximum size.
6332 std::string content(kMaxSpdyFrameChunkSize, 'a');
6334 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6335 kRequestUrl, 1, initial_window_size + kUploadDataSize, LOWEST, NULL, 0));
6337 // Full frames.
6338 scoped_ptr<SpdyFrame> body1(
6339 spdy_util_.ConstructSpdyBodyFrame(
6340 1, content.c_str(), content.size(), false));
6342 // Last frame to zero out the window size.
6343 scoped_ptr<SpdyFrame> body2(
6344 spdy_util_.ConstructSpdyBodyFrame(
6345 1, content.c_str(), last_frame_size, false));
6347 // Data frame to be sent once WINDOW_UPDATE frame is received.
6348 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6350 // Fill in mock writes.
6351 scoped_ptr<MockWrite[]> writes(new MockWrite[num_writes]);
6352 size_t i = 0;
6353 writes[i] = CreateMockWrite(*req);
6354 for (i = 1; i < num_writes - 2; i++)
6355 writes[i] = CreateMockWrite(*body1);
6356 writes[i++] = CreateMockWrite(*body2);
6357 writes[i] = CreateMockWrite(*body3);
6359 // Construct read frame, give enough space to upload the rest of the
6360 // data.
6361 scoped_ptr<SpdyFrame> session_window_update(
6362 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6363 scoped_ptr<SpdyFrame> window_update(
6364 spdy_util_.ConstructSpdyWindowUpdate(1, kUploadDataSize));
6365 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6366 MockRead reads[] = {
6367 CreateMockRead(*session_window_update),
6368 CreateMockRead(*session_window_update),
6369 CreateMockRead(*window_update),
6370 CreateMockRead(*window_update),
6371 CreateMockRead(*reply),
6372 CreateMockRead(*body2),
6373 CreateMockRead(*body3),
6374 MockRead(ASYNC, 0, 0) // EOF
6377 // Skip the session window updates unless we're using SPDY/3.1 and
6378 // above.
6379 size_t read_offset = (GetParam().protocol >= kProtoSPDY31) ? 0 : 2;
6380 size_t num_reads = arraysize(reads) - read_offset;
6382 // Force all writes to happen before any read, last write will not
6383 // actually queue a frame, due to window size being 0.
6384 DelayedSocketData data(num_writes, reads + read_offset, num_reads,
6385 writes.get(), num_writes);
6387 ScopedVector<UploadElementReader> element_readers;
6388 std::string upload_data_string(initial_window_size, 'a');
6389 upload_data_string.append(kUploadData, kUploadDataSize);
6390 element_readers.push_back(new UploadBytesElementReader(
6391 upload_data_string.c_str(), upload_data_string.size()));
6392 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
6394 HttpRequestInfo request;
6395 request.method = "POST";
6396 request.url = GURL("http://www.google.com/");
6397 request.upload_data_stream = &upload_data_stream;
6398 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6399 BoundNetLog(), GetParam(), NULL);
6400 helper.AddData(&data);
6401 helper.RunPreTestSetup();
6403 HttpNetworkTransaction* trans = helper.trans();
6405 TestCompletionCallback callback;
6406 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6407 EXPECT_EQ(ERR_IO_PENDING, rv);
6409 base::RunLoop().RunUntilIdle(); // Write as much as we can.
6411 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6412 ASSERT_TRUE(stream != NULL);
6413 ASSERT_TRUE(stream->stream() != NULL);
6414 EXPECT_EQ(0, stream->stream()->send_window_size());
6415 // All the body data should have been read.
6416 // TODO(satorux): This is because of the weirdness in reading the request
6417 // body in OnSendBodyComplete(). See crbug.com/113107.
6418 EXPECT_TRUE(upload_data_stream.IsEOF());
6419 // But the body is not yet fully sent (kUploadData is not yet sent)
6420 // since we're send-stalled.
6421 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6423 data.ForceNextRead(); // Read in WINDOW_UPDATE frame.
6424 rv = callback.WaitForResult();
6425 helper.VerifyDataConsumed();
6428 // Test we correctly handle the case where the SETTINGS frame results in
6429 // unstalling the send window.
6430 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
6431 const int32 initial_window_size =
6432 SpdySession::GetInitialWindowSize(GetParam().protocol);
6434 // Number of frames we need to send to zero out the window size: data
6435 // frames plus SYN_STREAM plus the last data frame; also we need another
6436 // data frame that we will send once the SETTING is received, therefore +3.
6437 size_t num_writes = initial_window_size / kMaxSpdyFrameChunkSize + 3;
6439 // Calculate last frame's size; 0 size data frame is legal.
6440 size_t last_frame_size = initial_window_size % kMaxSpdyFrameChunkSize;
6442 // Construct content for a data frame of maximum size.
6443 std::string content(kMaxSpdyFrameChunkSize, 'a');
6445 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6446 kRequestUrl, 1, initial_window_size + kUploadDataSize, LOWEST, NULL, 0));
6448 // Full frames.
6449 scoped_ptr<SpdyFrame> body1(
6450 spdy_util_.ConstructSpdyBodyFrame(
6451 1, content.c_str(), content.size(), false));
6453 // Last frame to zero out the window size.
6454 scoped_ptr<SpdyFrame> body2(
6455 spdy_util_.ConstructSpdyBodyFrame(
6456 1, content.c_str(), last_frame_size, false));
6458 // Data frame to be sent once SETTINGS frame is received.
6459 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6461 // Fill in mock reads/writes.
6462 std::vector<MockRead> reads;
6463 std::vector<MockWrite> writes;
6464 size_t i = 0;
6465 writes.push_back(CreateMockWrite(*req, i++));
6466 while (i < num_writes - 2)
6467 writes.push_back(CreateMockWrite(*body1, i++));
6468 writes.push_back(CreateMockWrite(*body2, i++));
6470 // Construct read frame for SETTINGS that gives enough space to upload the
6471 // rest of the data.
6472 SettingsMap settings;
6473 settings[SETTINGS_INITIAL_WINDOW_SIZE] =
6474 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_window_size * 2);
6475 scoped_ptr<SpdyFrame> settings_frame_large(
6476 spdy_util_.ConstructSpdySettings(settings));
6478 reads.push_back(CreateMockRead(*settings_frame_large, i++));
6480 scoped_ptr<SpdyFrame> session_window_update(
6481 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6482 if (GetParam().protocol >= kProtoSPDY31)
6483 reads.push_back(CreateMockRead(*session_window_update, i++));
6485 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
6486 writes.push_back(CreateMockWrite(*settings_ack, i++));
6488 writes.push_back(CreateMockWrite(*body3, i++));
6490 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6491 reads.push_back(CreateMockRead(*reply, i++));
6492 reads.push_back(CreateMockRead(*body2, i++));
6493 reads.push_back(CreateMockRead(*body3, i++));
6494 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6496 // Force all writes to happen before any read, last write will not
6497 // actually queue a frame, due to window size being 0.
6498 DeterministicSocketData data(vector_as_array(&reads), reads.size(),
6499 vector_as_array(&writes), writes.size());
6501 ScopedVector<UploadElementReader> element_readers;
6502 std::string upload_data_string(initial_window_size, 'a');
6503 upload_data_string.append(kUploadData, kUploadDataSize);
6504 element_readers.push_back(new UploadBytesElementReader(
6505 upload_data_string.c_str(), upload_data_string.size()));
6506 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
6508 HttpRequestInfo request;
6509 request.method = "POST";
6510 request.url = GURL("http://www.google.com/");
6511 request.upload_data_stream = &upload_data_stream;
6512 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6513 BoundNetLog(), GetParam(), NULL);
6514 helper.SetDeterministic();
6515 helper.RunPreTestSetup();
6516 helper.AddDeterministicData(&data);
6518 HttpNetworkTransaction* trans = helper.trans();
6520 TestCompletionCallback callback;
6521 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6522 EXPECT_EQ(ERR_IO_PENDING, rv);
6524 data.RunFor(num_writes - 1); // Write as much as we can.
6526 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6527 ASSERT_TRUE(stream != NULL);
6528 ASSERT_TRUE(stream->stream() != NULL);
6529 EXPECT_EQ(0, stream->stream()->send_window_size());
6531 // All the body data should have been read.
6532 // TODO(satorux): This is because of the weirdness in reading the request
6533 // body in OnSendBodyComplete(). See crbug.com/113107.
6534 EXPECT_TRUE(upload_data_stream.IsEOF());
6535 // But the body is not yet fully sent (kUploadData is not yet sent)
6536 // since we're send-stalled.
6537 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6539 data.RunFor(7); // Read in SETTINGS frame to unstall.
6540 rv = callback.WaitForResult();
6541 helper.VerifyDataConsumed();
6542 // If stream is NULL, that means it was unstalled and closed.
6543 EXPECT_TRUE(stream->stream() == NULL);
6546 // Test we correctly handle the case where the SETTINGS frame results in a
6547 // negative send window size.
6548 TEST_P(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
6549 const int32 initial_window_size =
6550 SpdySession::GetInitialWindowSize(GetParam().protocol);
6551 // Number of frames we need to send to zero out the window size: data
6552 // frames plus SYN_STREAM plus the last data frame; also we need another
6553 // data frame that we will send once the SETTING is received, therefore +3.
6554 size_t num_writes = initial_window_size / kMaxSpdyFrameChunkSize + 3;
6556 // Calculate last frame's size; 0 size data frame is legal.
6557 size_t last_frame_size = initial_window_size % kMaxSpdyFrameChunkSize;
6559 // Construct content for a data frame of maximum size.
6560 std::string content(kMaxSpdyFrameChunkSize, 'a');
6562 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6563 kRequestUrl, 1, initial_window_size + kUploadDataSize, LOWEST, NULL, 0));
6565 // Full frames.
6566 scoped_ptr<SpdyFrame> body1(
6567 spdy_util_.ConstructSpdyBodyFrame(
6568 1, content.c_str(), content.size(), false));
6570 // Last frame to zero out the window size.
6571 scoped_ptr<SpdyFrame> body2(
6572 spdy_util_.ConstructSpdyBodyFrame(
6573 1, content.c_str(), last_frame_size, false));
6575 // Data frame to be sent once SETTINGS frame is received.
6576 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6578 // Fill in mock reads/writes.
6579 std::vector<MockRead> reads;
6580 std::vector<MockWrite> writes;
6581 size_t i = 0;
6582 writes.push_back(CreateMockWrite(*req, i++));
6583 while (i < num_writes - 2)
6584 writes.push_back(CreateMockWrite(*body1, i++));
6585 writes.push_back(CreateMockWrite(*body2, i++));
6587 // Construct read frame for SETTINGS that makes the send_window_size
6588 // negative.
6589 SettingsMap new_settings;
6590 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
6591 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_window_size / 2);
6592 scoped_ptr<SpdyFrame> settings_frame_small(
6593 spdy_util_.ConstructSpdySettings(new_settings));
6594 // Construct read frames for WINDOW_UPDATE that makes the send_window_size
6595 // positive.
6596 scoped_ptr<SpdyFrame> session_window_update_init_size(
6597 spdy_util_.ConstructSpdyWindowUpdate(0, initial_window_size));
6598 scoped_ptr<SpdyFrame> window_update_init_size(
6599 spdy_util_.ConstructSpdyWindowUpdate(1, initial_window_size));
6601 reads.push_back(CreateMockRead(*settings_frame_small, i++));
6602 reads.push_back(CreateMockRead(*session_window_update_init_size, i++));
6603 reads.push_back(CreateMockRead(*window_update_init_size, i++));
6605 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
6606 writes.push_back(CreateMockWrite(*settings_ack, i++));
6608 writes.push_back(CreateMockWrite(*body3, i++));
6610 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6611 reads.push_back(CreateMockRead(*reply, i++));
6612 reads.push_back(CreateMockRead(*body2, i++));
6613 reads.push_back(CreateMockRead(*body3, i++));
6614 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6616 // Force all writes to happen before any read, last write will not
6617 // actually queue a frame, due to window size being 0.
6618 DeterministicSocketData data(vector_as_array(&reads), reads.size(),
6619 vector_as_array(&writes), writes.size());
6621 ScopedVector<UploadElementReader> element_readers;
6622 std::string upload_data_string(initial_window_size, 'a');
6623 upload_data_string.append(kUploadData, kUploadDataSize);
6624 element_readers.push_back(new UploadBytesElementReader(
6625 upload_data_string.c_str(), upload_data_string.size()));
6626 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
6628 HttpRequestInfo request;
6629 request.method = "POST";
6630 request.url = GURL("http://www.google.com/");
6631 request.upload_data_stream = &upload_data_stream;
6632 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6633 BoundNetLog(), GetParam(), NULL);
6634 helper.SetDeterministic();
6635 helper.RunPreTestSetup();
6636 helper.AddDeterministicData(&data);
6638 HttpNetworkTransaction* trans = helper.trans();
6640 TestCompletionCallback callback;
6641 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6642 EXPECT_EQ(ERR_IO_PENDING, rv);
6644 data.RunFor(num_writes - 1); // Write as much as we can.
6646 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6647 ASSERT_TRUE(stream != NULL);
6648 ASSERT_TRUE(stream->stream() != NULL);
6649 EXPECT_EQ(0, stream->stream()->send_window_size());
6651 // All the body data should have been read.
6652 // TODO(satorux): This is because of the weirdness in reading the request
6653 // body in OnSendBodyComplete(). See crbug.com/113107.
6654 EXPECT_TRUE(upload_data_stream.IsEOF());
6655 // But the body is not yet fully sent (kUploadData is not yet sent)
6656 // since we're send-stalled.
6657 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6659 // Read in WINDOW_UPDATE or SETTINGS frame.
6660 data.RunFor((GetParam().protocol >= kProtoSPDY31) ? 9 : 8);
6661 rv = callback.WaitForResult();
6662 helper.VerifyDataConsumed();
6665 TEST_P(SpdyNetworkTransactionTest, GoAwayOnOddPushStreamId) {
6666 if (spdy_util_.spdy_version() < SPDY3)
6667 return;
6669 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
6670 spdy_util_.AddUrlToHeaderBlock("http://www.google.com/a.dat",
6671 push_headers.get());
6672 scoped_ptr<SpdyFrame> push(
6673 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 3, 1));
6674 MockRead reads[] = {CreateMockRead(*push, 1)};
6676 scoped_ptr<SpdyFrame> req(
6677 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
6678 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
6679 0, GOAWAY_PROTOCOL_ERROR, "Odd push stream id."));
6680 MockWrite writes[] = {
6681 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2),
6684 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
6685 NormalSpdyTransactionHelper helper(
6686 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6687 helper.RunToCompletion(&data);
6688 TransactionHelperResult out = helper.output();
6689 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
6692 TEST_P(SpdyNetworkTransactionTest,
6693 GoAwayOnPushStreamIdLesserOrEqualThanLastAccepted) {
6694 if (spdy_util_.spdy_version() < SPDY3)
6695 return;
6697 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
6698 NULL, 0, 4, 1, "http://www.google.com/a.dat"));
6699 scoped_ptr<SpdyHeaderBlock> push_b_headers(new SpdyHeaderBlock);
6700 spdy_util_.AddUrlToHeaderBlock("http://www.google.com/b.dat",
6701 push_b_headers.get());
6702 scoped_ptr<SpdyFrame> push_b(
6703 spdy_util_.ConstructInitialSpdyPushFrame(push_b_headers.Pass(), 2, 1));
6704 MockRead reads[] = {
6705 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
6708 scoped_ptr<SpdyFrame> req(
6709 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
6710 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
6712 GOAWAY_PROTOCOL_ERROR,
6713 "New push stream id must be greater than the last accepted."));
6714 MockWrite writes[] = {
6715 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 3),
6718 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
6719 NormalSpdyTransactionHelper helper(
6720 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6721 helper.RunToCompletion(&data);
6722 TransactionHelperResult out = helper.output();
6723 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
6726 class SpdyNetworkTransactionNoTLSUsageCheckTest
6727 : public SpdyNetworkTransactionTest {
6728 protected:
6729 void RunNoTLSUsageCheckTest(scoped_ptr<SSLSocketDataProvider> ssl_provider) {
6730 // Construct the request.
6731 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyGet(
6732 "https://www.google.com/", false, 1, LOWEST));
6733 MockWrite writes[] = {CreateMockWrite(*req)};
6735 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6736 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6737 MockRead reads[] = {
6738 CreateMockRead(*resp), CreateMockRead(*body),
6739 MockRead(ASYNC, 0, 0) // EOF
6742 DelayedSocketData data(
6743 1, reads, arraysize(reads), writes, arraysize(writes));
6744 HttpRequestInfo request;
6745 request.method = "GET";
6746 request.url = GURL("https://www.google.com/");
6747 NormalSpdyTransactionHelper helper(
6748 request, DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6749 helper.RunToCompletionWithSSLData(&data, ssl_provider.Pass());
6750 TransactionHelperResult out = helper.output();
6751 EXPECT_EQ(OK, out.rv);
6752 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
6753 EXPECT_EQ("hello!", out.response_data);
6757 //-----------------------------------------------------------------------------
6758 // All tests are run with three different connection types: SPDY after NPN
6759 // negotiation, SPDY without SSL, and SPDY with SSL.
6761 // TODO(akalin): Use ::testing::Combine() when we are able to use
6762 // <tr1/tuple>.
6763 INSTANTIATE_TEST_CASE_P(
6764 Spdy,
6765 SpdyNetworkTransactionNoTLSUsageCheckTest,
6766 ::testing::Values(SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNPN)));
6768 TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest, TLSVersionTooOld) {
6769 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6770 new SSLSocketDataProvider(ASYNC, OK));
6771 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6772 &ssl_provider->connection_status);
6774 RunNoTLSUsageCheckTest(ssl_provider.Pass());
6777 TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest, TLSCipherSuiteSucky) {
6778 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6779 new SSLSocketDataProvider(ASYNC, OK));
6780 // Set to TLS_RSA_WITH_NULL_MD5
6781 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider->connection_status);
6783 RunNoTLSUsageCheckTest(ssl_provider.Pass());
6786 class SpdyNetworkTransactionTLSUsageCheckTest
6787 : public SpdyNetworkTransactionTest {
6788 protected:
6789 void RunTLSUsageCheckTest(scoped_ptr<SSLSocketDataProvider> ssl_provider) {
6790 scoped_ptr<SpdyFrame> goaway(
6791 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_INADEQUATE_SECURITY, ""));
6792 MockWrite writes[] = {CreateMockWrite(*goaway)};
6794 DelayedSocketData data(1, NULL, 0, writes, arraysize(writes));
6795 HttpRequestInfo request;
6796 request.method = "GET";
6797 request.url = GURL("https://www.google.com/");
6798 NormalSpdyTransactionHelper helper(
6799 request, DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6800 helper.RunToCompletionWithSSLData(&data, ssl_provider.Pass());
6801 TransactionHelperResult out = helper.output();
6802 EXPECT_EQ(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY, out.rv);
6806 INSTANTIATE_TEST_CASE_P(
6807 Spdy,
6808 SpdyNetworkTransactionTLSUsageCheckTest,
6809 ::testing::Values(
6810 SpdyNetworkTransactionTestParams(kProtoSPDY4_14, SPDYNPN),
6811 SpdyNetworkTransactionTestParams(kProtoSPDY4_15, SPDYNPN)));
6813 TEST_P(SpdyNetworkTransactionTLSUsageCheckTest, TLSVersionTooOld) {
6814 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6815 new SSLSocketDataProvider(ASYNC, OK));
6816 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6817 &ssl_provider->connection_status);
6819 RunTLSUsageCheckTest(ssl_provider.Pass());
6822 TEST_P(SpdyNetworkTransactionTLSUsageCheckTest, TLSCipherSuiteSucky) {
6823 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6824 new SSLSocketDataProvider(ASYNC, OK));
6825 // Set to TLS_RSA_WITH_NULL_MD5
6826 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider->connection_status);
6828 RunTLSUsageCheckTest(ssl_provider.Pass());
6831 } // namespace net