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