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
25namespace net {
26
27// This is the expected list of advertised protocols from the browser's NPN
28// list.
29static const char kExpectedNPNString[] = "\x08http/1.1\x06spdy/2";
30
31enum SpdyNetworkTransactionTestTypes {
32  SPDYNPN,
33  SPDYNOSSL,
34  SPDYSSL,
35};
36class SpdyNetworkTransactionTest
37    : public ::testing::TestWithParam<SpdyNetworkTransactionTestTypes> {
38 protected:
39
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
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
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:
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
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
106    void SetDeterministic() {
107      session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
108          session_deps_.get());
109      deterministic_ = true;
110    }
111
112    void SetSpdyDisabled() {
113      spdy_enabled_ = false;
114    }
115
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.
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.
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.
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
222    void RunToCompletion(StaticSocketDataProvider* data) {
223      RunPreTestSetup();
224      AddData(data);
225      RunDefaultTest();
226      VerifyDataConsumed();
227    }
228
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
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
288    void AddDataNoSSL(StaticSocketDataProvider* data) {
289      DCHECK(!deterministic_);
290      session_deps_->socket_factory->AddSocketDataProvider(data);
291    }
292    void AddDataNoSSL(DeterministicSocketData* data) {
293      DCHECK(deterministic_);
294      session_deps_->deterministic_socket_factory->AddSocketDataProvider(data);
295    }
296
297    void SetSession(const scoped_refptr<HttpNetworkSession>& session) {
298      session_ = session;
299    }
300    HttpNetworkTransaction* trans() { return trans_.get(); }
301    void ResetTrans() { trans_.reset(); }
302    TransactionHelperResult& output() { return output_; }
303    const HttpRequestInfo& request() const { return request_; }
304    const scoped_refptr<HttpNetworkSession>& session() const {
305      return session_;
306    }
307    scoped_ptr<SpdySessionDependencies>& session_deps() {
308      return session_deps_;
309    }
310    int port() const { return port_; }
311    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
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
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
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
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
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|.
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
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
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.
512INSTANTIATE_TEST_CASE_P(Spdy,
513                        SpdyNetworkTransactionTest,
514                        ::testing::Values(SPDYNOSSL, SPDYSSL, SPDYNPN));
515
516
517// Verify HttpNetworkTransaction constructor.
518TEST_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
525TEST_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
550TEST_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
613TEST_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
708TEST_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
795TEST_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().
900TEST_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.
1033TEST_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
1189TEST_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.
1296class KillerCallback : public TestCompletionCallback {
1297 public:
1298  explicit KillerCallback(HttpNetworkTransaction* transaction)
1299      : transaction_(transaction) {}
1300
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
1314TEST_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.
1408TEST_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.
1479TEST_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.
1550TEST_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.
1578TEST_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.
1610TEST_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.
1649TEST_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.
1693TEST_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.
1732TEST_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.
1772TEST_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.
1790TEST_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.
1852TEST_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.
1929TEST_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.
2012TEST_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.
2104TEST_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
2199TEST_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.
2237TEST_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
2278class SpdyNetworkTransactionTest::StartTransactionCallback
2279    : public CallbackRunner< Tuple1<int> > {
2280 public:
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.
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
2308TEST_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
2367class SpdyNetworkTransactionTest::DeleteSessionCallback
2368    : public CallbackRunner< Tuple1<int> > {
2369 public:
2370  explicit DeleteSessionCallback(NormalSpdyTransactionHelper& helper) :
2371      helper_(helper) {}
2372
2373  // We kill the transaction, which deletes the session and stream.
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
2385TEST_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.
2429TEST_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.
2535TEST_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
2671TEST_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
2724TEST_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
2777TEST_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
2838TEST_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
2904TEST_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
2967TEST_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
3031TEST_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
3092TEST_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
3153TEST_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.
3211TEST_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.
3292TEST_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.
3461TEST_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.
3531TEST_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.
3570TEST_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.
3591TEST_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.
3619TEST_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.
3654TEST_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.
3742TEST_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.
3836TEST_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.
3930TEST_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.
4021TEST_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.
4111TEST_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.
4182TEST_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.
4291TEST_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
4402TEST_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
4423TEST_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.
4462TEST_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
4558TEST_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.
4733TEST_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.
4814TEST_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
4861TEST_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
4951TEST_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
5034TEST_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
5169TEST_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
5326TEST_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
5382TEST_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
5440TEST_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
5496TEST_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