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