1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <string>
6#include <vector>
7
8#include "base/bind.h"
9#include "base/bind_helpers.h"
10#include "base/files/file_util.h"
11#include "base/files/scoped_temp_dir.h"
12#include "base/memory/scoped_vector.h"
13#include "base/run_loop.h"
14#include "base/stl_util.h"
15#include "base/strings/string_piece.h"
16#include "base/test/test_file_util.h"
17#include "net/base/auth.h"
18#include "net/base/net_log_unittest.h"
19#include "net/base/request_priority.h"
20#include "net/base/upload_bytes_element_reader.h"
21#include "net/base/upload_data_stream.h"
22#include "net/base/upload_file_element_reader.h"
23#include "net/http/http_network_session_peer.h"
24#include "net/http/http_network_transaction.h"
25#include "net/http/http_server_properties.h"
26#include "net/http/http_transaction_test_util.h"
27#include "net/socket/client_socket_pool_base.h"
28#include "net/socket/next_proto.h"
29#include "net/spdy/buffered_spdy_framer.h"
30#include "net/spdy/spdy_http_stream.h"
31#include "net/spdy/spdy_http_utils.h"
32#include "net/spdy/spdy_session.h"
33#include "net/spdy/spdy_session_pool.h"
34#include "net/spdy/spdy_test_util_common.h"
35#include "net/spdy/spdy_test_utils.h"
36#include "net/ssl/ssl_connection_status_flags.h"
37#include "net/url_request/url_request_test_util.h"
38#include "testing/gmock/include/gmock/gmock.h"
39#include "testing/platform_test.h"
40
41//-----------------------------------------------------------------------------
42
43namespace net {
44
45namespace {
46
47using testing::Each;
48using testing::Eq;
49
50const char kRequestUrl[] = "http://www.google.com/";
51
52enum SpdyNetworkTransactionTestSSLType {
53  SPDYNPN,
54  SPDYNOSSL,
55  SPDYSSL,
56};
57
58struct SpdyNetworkTransactionTestParams {
59  SpdyNetworkTransactionTestParams()
60      : protocol(kProtoSPDY3),
61        ssl_type(SPDYNPN) {}
62
63  SpdyNetworkTransactionTestParams(
64      NextProto protocol,
65      SpdyNetworkTransactionTestSSLType ssl_type)
66      : protocol(protocol),
67        ssl_type(ssl_type) {}
68
69  NextProto protocol;
70  SpdyNetworkTransactionTestSSLType ssl_type;
71};
72
73void UpdateSpdySessionDependencies(
74    SpdyNetworkTransactionTestParams test_params,
75    SpdySessionDependencies* session_deps) {
76  switch (test_params.ssl_type) {
77    case SPDYNPN:
78      session_deps->http_server_properties.SetAlternateProtocol(
79          HostPortPair("www.google.com", 80), 443,
80          AlternateProtocolFromNextProto(test_params.protocol), 1);
81      session_deps->use_alternate_protocols = true;
82      session_deps->next_protos = SpdyNextProtos();
83      break;
84    case SPDYNOSSL:
85      session_deps->force_spdy_over_ssl = false;
86      session_deps->force_spdy_always = true;
87      break;
88    case SPDYSSL:
89      session_deps->force_spdy_over_ssl = true;
90      session_deps->force_spdy_always = true;
91      break;
92    default:
93      NOTREACHED();
94  }
95}
96
97SpdySessionDependencies* CreateSpdySessionDependencies(
98    SpdyNetworkTransactionTestParams test_params) {
99  SpdySessionDependencies* session_deps =
100      new SpdySessionDependencies(test_params.protocol);
101  UpdateSpdySessionDependencies(test_params, session_deps);
102  return session_deps;
103}
104
105SpdySessionDependencies* CreateSpdySessionDependencies(
106    SpdyNetworkTransactionTestParams test_params,
107    ProxyService* proxy_service) {
108  SpdySessionDependencies* session_deps =
109      new SpdySessionDependencies(test_params.protocol, proxy_service);
110  UpdateSpdySessionDependencies(test_params, session_deps);
111  return session_deps;
112}
113
114}  // namespace
115
116class SpdyNetworkTransactionTest
117    : public ::testing::TestWithParam<SpdyNetworkTransactionTestParams> {
118 protected:
119  SpdyNetworkTransactionTest() : spdy_util_(GetParam().protocol) {
120  }
121
122  virtual ~SpdyNetworkTransactionTest() {
123    // UploadDataStream posts deletion tasks back to the message loop on
124    // destruction.
125    upload_data_stream_.reset();
126    base::RunLoop().RunUntilIdle();
127  }
128
129  virtual void SetUp() {
130    google_get_request_initialized_ = false;
131    google_post_request_initialized_ = false;
132    google_chunked_post_request_initialized_ = false;
133    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
134  }
135
136  struct TransactionHelperResult {
137    int rv;
138    std::string status_line;
139    std::string response_data;
140    HttpResponseInfo response_info;
141  };
142
143  // A helper class that handles all the initial npn/ssl setup.
144  class NormalSpdyTransactionHelper {
145   public:
146    NormalSpdyTransactionHelper(const HttpRequestInfo& request,
147                                RequestPriority priority,
148                                const BoundNetLog& log,
149                                SpdyNetworkTransactionTestParams test_params,
150                                SpdySessionDependencies* session_deps)
151        : request_(request),
152          priority_(priority),
153          session_deps_(session_deps == NULL ?
154                        CreateSpdySessionDependencies(test_params) :
155                        session_deps),
156          session_(SpdySessionDependencies::SpdyCreateSession(
157                       session_deps_.get())),
158          log_(log),
159          test_params_(test_params),
160          deterministic_(false),
161          spdy_enabled_(true) {
162      switch (test_params_.ssl_type) {
163        case SPDYNOSSL:
164        case SPDYSSL:
165          port_ = 80;
166          break;
167        case SPDYNPN:
168          port_ = 443;
169          break;
170        default:
171          NOTREACHED();
172      }
173    }
174
175    ~NormalSpdyTransactionHelper() {
176      // Any test which doesn't close the socket by sending it an EOF will
177      // have a valid session left open, which leaks the entire session pool.
178      // This is just fine - in fact, some of our tests intentionally do this
179      // so that we can check consistency of the SpdySessionPool as the test
180      // finishes.  If we had put an EOF on the socket, the SpdySession would
181      // have closed and we wouldn't be able to check the consistency.
182
183      // Forcefully close existing sessions here.
184      session()->spdy_session_pool()->CloseAllSessions();
185    }
186
187    void SetDeterministic() {
188      session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
189          session_deps_.get());
190      deterministic_ = true;
191    }
192
193    void SetSpdyDisabled() {
194      spdy_enabled_ = false;
195      port_ = 80;
196    }
197
198    void RunPreTestSetup() {
199      if (!session_deps_.get())
200        session_deps_.reset(CreateSpdySessionDependencies(test_params_));
201      if (!session_.get()) {
202        session_ = SpdySessionDependencies::SpdyCreateSession(
203            session_deps_.get());
204      }
205
206      // We're now ready to use SSL-npn SPDY.
207      trans_.reset(new HttpNetworkTransaction(priority_, session_.get()));
208    }
209
210    // Start the transaction, read some data, finish.
211    void RunDefaultTest() {
212      if (!StartDefaultTest())
213        return;
214      FinishDefaultTest();
215    }
216
217    bool StartDefaultTest() {
218      output_.rv = trans_->Start(&request_, callback_.callback(), log_);
219
220      // We expect an IO Pending or some sort of error.
221      EXPECT_LT(output_.rv, 0);
222      return output_.rv == ERR_IO_PENDING;
223    }
224
225    void FinishDefaultTest() {
226      output_.rv = callback_.WaitForResult();
227      if (output_.rv != OK) {
228        session_->spdy_session_pool()->CloseCurrentSessions(net::ERR_ABORTED);
229        return;
230      }
231
232      // Verify responses.
233      const HttpResponseInfo* response = trans_->GetResponseInfo();
234      ASSERT_TRUE(response != NULL);
235      ASSERT_TRUE(response->headers.get() != NULL);
236      EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
237      EXPECT_EQ(spdy_enabled_, response->was_fetched_via_spdy);
238      if (HttpStreamFactory::spdy_enabled()) {
239        EXPECT_EQ(
240            HttpResponseInfo::ConnectionInfoFromNextProto(
241                test_params_.protocol),
242            response->connection_info);
243      } else {
244        EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1,
245                  response->connection_info);
246      }
247      if (test_params_.ssl_type == SPDYNPN && spdy_enabled_) {
248        EXPECT_TRUE(response->was_npn_negotiated);
249      } else {
250        EXPECT_TRUE(!response->was_npn_negotiated);
251      }
252      // If SPDY is not enabled, a HTTP request should not be diverted
253      // over a SSL session.
254      if (!spdy_enabled_) {
255        EXPECT_EQ(request_.url.SchemeIs("https"),
256                  response->was_npn_negotiated);
257      }
258      EXPECT_EQ("127.0.0.1", response->socket_address.host());
259      EXPECT_EQ(port_, response->socket_address.port());
260      output_.status_line = response->headers->GetStatusLine();
261      output_.response_info = *response;  // Make a copy so we can verify.
262      output_.rv = ReadTransaction(trans_.get(), &output_.response_data);
263    }
264
265    // Most tests will want to call this function. In particular, the MockReads
266    // should end with an empty read, and that read needs to be processed to
267    // ensure proper deletion of the spdy_session_pool.
268    void VerifyDataConsumed() {
269      for (DataVector::iterator it = data_vector_.begin();
270          it != data_vector_.end(); ++it) {
271        EXPECT_TRUE((*it)->at_read_eof()) << "Read count: "
272                                          << (*it)->read_count()
273                                          << " Read index: "
274                                          << (*it)->read_index();
275        EXPECT_TRUE((*it)->at_write_eof()) << "Write count: "
276                                           << (*it)->write_count()
277                                           << " Write index: "
278                                           << (*it)->write_index();
279      }
280    }
281
282    // Occasionally a test will expect to error out before certain reads are
283    // processed. In that case we want to explicitly ensure that the reads were
284    // not processed.
285    void VerifyDataNotConsumed() {
286      for (DataVector::iterator it = data_vector_.begin();
287          it != data_vector_.end(); ++it) {
288        EXPECT_TRUE(!(*it)->at_read_eof()) << "Read count: "
289                                           << (*it)->read_count()
290                                           << " Read index: "
291                                           << (*it)->read_index();
292        EXPECT_TRUE(!(*it)->at_write_eof()) << "Write count: "
293                                            << (*it)->write_count()
294                                            << " Write index: "
295                                            << (*it)->write_index();
296      }
297    }
298
299    void RunToCompletion(StaticSocketDataProvider* data) {
300      RunPreTestSetup();
301      AddData(data);
302      RunDefaultTest();
303      VerifyDataConsumed();
304    }
305
306    void RunToCompletionWithSSLData(
307        StaticSocketDataProvider* data,
308        scoped_ptr<SSLSocketDataProvider> ssl_provider) {
309      RunPreTestSetup();
310      AddDataWithSSLSocketDataProvider(data, ssl_provider.Pass());
311      RunDefaultTest();
312      VerifyDataConsumed();
313    }
314
315    void AddData(StaticSocketDataProvider* data) {
316      scoped_ptr<SSLSocketDataProvider> ssl_provider(
317          new SSLSocketDataProvider(ASYNC, OK));
318      AddDataWithSSLSocketDataProvider(data, ssl_provider.Pass());
319    }
320
321    void AddDataWithSSLSocketDataProvider(
322        StaticSocketDataProvider* data,
323        scoped_ptr<SSLSocketDataProvider> ssl_provider) {
324      DCHECK(!deterministic_);
325      data_vector_.push_back(data);
326      if (test_params_.ssl_type == SPDYNPN)
327        ssl_provider->SetNextProto(test_params_.protocol);
328
329      if (test_params_.ssl_type == SPDYNPN ||
330          test_params_.ssl_type == SPDYSSL) {
331        session_deps_->socket_factory->AddSSLSocketDataProvider(
332            ssl_provider.get());
333      }
334      ssl_vector_.push_back(ssl_provider.release());
335
336      session_deps_->socket_factory->AddSocketDataProvider(data);
337      if (test_params_.ssl_type == SPDYNPN) {
338        MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
339        StaticSocketDataProvider* hanging_non_alternate_protocol_socket =
340            new StaticSocketDataProvider(NULL, 0, NULL, 0);
341        hanging_non_alternate_protocol_socket->set_connect_data(
342            never_finishing_connect);
343        session_deps_->socket_factory->AddSocketDataProvider(
344            hanging_non_alternate_protocol_socket);
345        alternate_vector_.push_back(hanging_non_alternate_protocol_socket);
346      }
347    }
348
349    void AddDeterministicData(DeterministicSocketData* data) {
350      DCHECK(deterministic_);
351      data_vector_.push_back(data);
352      SSLSocketDataProvider* ssl_provider =
353          new SSLSocketDataProvider(ASYNC, OK);
354      if (test_params_.ssl_type == SPDYNPN)
355        ssl_provider->SetNextProto(test_params_.protocol);
356
357      ssl_vector_.push_back(ssl_provider);
358      if (test_params_.ssl_type == SPDYNPN ||
359          test_params_.ssl_type == SPDYSSL) {
360        session_deps_->deterministic_socket_factory->
361            AddSSLSocketDataProvider(ssl_provider);
362      }
363      session_deps_->deterministic_socket_factory->AddSocketDataProvider(data);
364      if (test_params_.ssl_type == SPDYNPN) {
365        MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
366        DeterministicSocketData* hanging_non_alternate_protocol_socket =
367            new DeterministicSocketData(NULL, 0, NULL, 0);
368        hanging_non_alternate_protocol_socket->set_connect_data(
369            never_finishing_connect);
370        session_deps_->deterministic_socket_factory->AddSocketDataProvider(
371            hanging_non_alternate_protocol_socket);
372        alternate_deterministic_vector_.push_back(
373            hanging_non_alternate_protocol_socket);
374      }
375    }
376
377    void SetSession(const scoped_refptr<HttpNetworkSession>& session) {
378      session_ = session;
379    }
380    HttpNetworkTransaction* trans() { return trans_.get(); }
381    void ResetTrans() { trans_.reset(); }
382    TransactionHelperResult& output() { return output_; }
383    const HttpRequestInfo& request() const { return request_; }
384    const scoped_refptr<HttpNetworkSession>& session() const {
385      return session_;
386    }
387    scoped_ptr<SpdySessionDependencies>& session_deps() {
388      return session_deps_;
389    }
390    int port() const { return port_; }
391    SpdyNetworkTransactionTestParams test_params() const {
392      return test_params_;
393    }
394
395   private:
396    typedef std::vector<StaticSocketDataProvider*> DataVector;
397    typedef ScopedVector<SSLSocketDataProvider> SSLVector;
398    typedef ScopedVector<StaticSocketDataProvider> AlternateVector;
399    typedef ScopedVector<DeterministicSocketData> AlternateDeterministicVector;
400    HttpRequestInfo request_;
401    RequestPriority priority_;
402    scoped_ptr<SpdySessionDependencies> session_deps_;
403    scoped_refptr<HttpNetworkSession> session_;
404    TransactionHelperResult output_;
405    scoped_ptr<StaticSocketDataProvider> first_transaction_;
406    SSLVector ssl_vector_;
407    TestCompletionCallback callback_;
408    scoped_ptr<HttpNetworkTransaction> trans_;
409    scoped_ptr<HttpNetworkTransaction> trans_http_;
410    DataVector data_vector_;
411    AlternateVector alternate_vector_;
412    AlternateDeterministicVector alternate_deterministic_vector_;
413    const BoundNetLog& log_;
414    SpdyNetworkTransactionTestParams test_params_;
415    int port_;
416    bool deterministic_;
417    bool spdy_enabled_;
418  };
419
420  void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
421                                             int expected_status);
422
423  void ConnectStatusHelper(const MockRead& status);
424
425  const HttpRequestInfo& CreateGetPushRequest() {
426    google_get_push_request_.method = "GET";
427    google_get_push_request_.url = GURL("http://www.google.com/foo.dat");
428    google_get_push_request_.load_flags = 0;
429    return google_get_push_request_;
430  }
431
432  const HttpRequestInfo& CreateGetRequest() {
433    if (!google_get_request_initialized_) {
434      google_get_request_.method = "GET";
435      google_get_request_.url = GURL(kDefaultURL);
436      google_get_request_.load_flags = 0;
437      google_get_request_initialized_ = true;
438    }
439    return google_get_request_;
440  }
441
442  const HttpRequestInfo& CreateGetRequestWithUserAgent() {
443    if (!google_get_request_initialized_) {
444      google_get_request_.method = "GET";
445      google_get_request_.url = GURL(kDefaultURL);
446      google_get_request_.load_flags = 0;
447      google_get_request_.extra_headers.SetHeader("User-Agent", "Chrome");
448      google_get_request_initialized_ = true;
449    }
450    return google_get_request_;
451  }
452
453  const HttpRequestInfo& CreatePostRequest() {
454    if (!google_post_request_initialized_) {
455      ScopedVector<UploadElementReader> element_readers;
456      element_readers.push_back(
457          new UploadBytesElementReader(kUploadData, kUploadDataSize));
458      upload_data_stream_.reset(
459          new UploadDataStream(element_readers.Pass(), 0));
460
461      google_post_request_.method = "POST";
462      google_post_request_.url = GURL(kDefaultURL);
463      google_post_request_.upload_data_stream = upload_data_stream_.get();
464      google_post_request_initialized_ = true;
465    }
466    return google_post_request_;
467  }
468
469  const HttpRequestInfo& CreateFilePostRequest() {
470    if (!google_post_request_initialized_) {
471      base::FilePath file_path;
472      CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
473      CHECK_EQ(static_cast<int>(kUploadDataSize),
474               base::WriteFile(file_path, kUploadData, kUploadDataSize));
475
476      ScopedVector<UploadElementReader> element_readers;
477      element_readers.push_back(
478          new UploadFileElementReader(base::MessageLoopProxy::current().get(),
479                                      file_path,
480                                      0,
481                                      kUploadDataSize,
482                                      base::Time()));
483      upload_data_stream_.reset(
484          new UploadDataStream(element_readers.Pass(), 0));
485
486      google_post_request_.method = "POST";
487      google_post_request_.url = GURL(kDefaultURL);
488      google_post_request_.upload_data_stream = upload_data_stream_.get();
489      google_post_request_initialized_ = true;
490    }
491    return google_post_request_;
492  }
493
494  const HttpRequestInfo& CreateUnreadableFilePostRequest() {
495    if (google_post_request_initialized_)
496      return google_post_request_;
497
498    base::FilePath file_path;
499    CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
500    CHECK_EQ(static_cast<int>(kUploadDataSize),
501             base::WriteFile(file_path, kUploadData, kUploadDataSize));
502    CHECK(base::MakeFileUnreadable(file_path));
503
504    ScopedVector<UploadElementReader> element_readers;
505    element_readers.push_back(
506        new UploadFileElementReader(base::MessageLoopProxy::current().get(),
507                                    file_path,
508                                    0,
509                                    kUploadDataSize,
510                                    base::Time()));
511    upload_data_stream_.reset(
512        new UploadDataStream(element_readers.Pass(), 0));
513
514    google_post_request_.method = "POST";
515    google_post_request_.url = GURL(kDefaultURL);
516    google_post_request_.upload_data_stream = upload_data_stream_.get();
517    google_post_request_initialized_ = true;
518    return google_post_request_;
519  }
520
521  const HttpRequestInfo& CreateComplexPostRequest() {
522    if (!google_post_request_initialized_) {
523      const int kFileRangeOffset = 1;
524      const int kFileRangeLength = 3;
525      CHECK_LT(kFileRangeOffset + kFileRangeLength, kUploadDataSize);
526
527      base::FilePath file_path;
528      CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
529      CHECK_EQ(static_cast<int>(kUploadDataSize),
530               base::WriteFile(file_path, kUploadData, kUploadDataSize));
531
532      ScopedVector<UploadElementReader> element_readers;
533      element_readers.push_back(
534          new UploadBytesElementReader(kUploadData, kFileRangeOffset));
535      element_readers.push_back(
536          new UploadFileElementReader(base::MessageLoopProxy::current().get(),
537                                      file_path,
538                                      kFileRangeOffset,
539                                      kFileRangeLength,
540                                      base::Time()));
541      element_readers.push_back(new UploadBytesElementReader(
542          kUploadData + kFileRangeOffset + kFileRangeLength,
543          kUploadDataSize - (kFileRangeOffset + kFileRangeLength)));
544      upload_data_stream_.reset(
545          new UploadDataStream(element_readers.Pass(), 0));
546
547      google_post_request_.method = "POST";
548      google_post_request_.url = GURL(kDefaultURL);
549      google_post_request_.upload_data_stream = upload_data_stream_.get();
550      google_post_request_initialized_ = true;
551    }
552    return google_post_request_;
553  }
554
555  const HttpRequestInfo& CreateChunkedPostRequest() {
556    if (!google_chunked_post_request_initialized_) {
557      upload_data_stream_.reset(
558          new UploadDataStream(UploadDataStream::CHUNKED, 0));
559      google_chunked_post_request_.method = "POST";
560      google_chunked_post_request_.url = GURL(kDefaultURL);
561      google_chunked_post_request_.upload_data_stream =
562          upload_data_stream_.get();
563      google_chunked_post_request_initialized_ = true;
564    }
565    return google_chunked_post_request_;
566  }
567
568  // Read the result of a particular transaction, knowing that we've got
569  // multiple transactions in the read pipeline; so as we read, we may have
570  // to skip over data destined for other transactions while we consume
571  // the data for |trans|.
572  int ReadResult(HttpNetworkTransaction* trans,
573                 StaticSocketDataProvider* data,
574                 std::string* result) {
575    const int kSize = 3000;
576
577    int bytes_read = 0;
578    scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(kSize));
579    TestCompletionCallback callback;
580    while (true) {
581      int rv = trans->Read(buf.get(), kSize, callback.callback());
582      if (rv == ERR_IO_PENDING) {
583        // Multiple transactions may be in the data set.  Keep pulling off
584        // reads until we complete our callback.
585        while (!callback.have_result()) {
586          data->CompleteRead();
587          base::RunLoop().RunUntilIdle();
588        }
589        rv = callback.WaitForResult();
590      } else if (rv <= 0) {
591        break;
592      }
593      result->append(buf->data(), rv);
594      bytes_read += rv;
595    }
596    return bytes_read;
597  }
598
599  void VerifyStreamsClosed(const NormalSpdyTransactionHelper& helper) {
600    // This lengthy block is reaching into the pool to dig out the active
601    // session.  Once we have the session, we verify that the streams are
602    // all closed and not leaked at this point.
603    const GURL& url = helper.request().url;
604    int port = helper.test_params().ssl_type == SPDYNPN ? 443 : 80;
605    HostPortPair host_port_pair(url.host(), port);
606    SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
607                       PRIVACY_MODE_DISABLED);
608    BoundNetLog log;
609    const scoped_refptr<HttpNetworkSession>& session = helper.session();
610    base::WeakPtr<SpdySession> spdy_session =
611        session->spdy_session_pool()->FindAvailableSession(key, log);
612    ASSERT_TRUE(spdy_session != NULL);
613    EXPECT_EQ(0u, spdy_session->num_active_streams());
614    EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams());
615  }
616
617  void RunServerPushTest(OrderedSocketData* data,
618                         HttpResponseInfo* response,
619                         HttpResponseInfo* push_response,
620                         const std::string& expected) {
621    NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
622                                       BoundNetLog(), GetParam(), NULL);
623    helper.RunPreTestSetup();
624    helper.AddData(data);
625
626    HttpNetworkTransaction* trans = helper.trans();
627
628    // Start the transaction with basic parameters.
629    TestCompletionCallback callback;
630    int rv = trans->Start(
631        &CreateGetRequest(), callback.callback(), BoundNetLog());
632    EXPECT_EQ(ERR_IO_PENDING, rv);
633    rv = callback.WaitForResult();
634
635    // Request the pushed path.
636    scoped_ptr<HttpNetworkTransaction> trans2(
637        new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
638    rv = trans2->Start(
639        &CreateGetPushRequest(), callback.callback(), BoundNetLog());
640    EXPECT_EQ(ERR_IO_PENDING, rv);
641    base::RunLoop().RunUntilIdle();
642
643    // The data for the pushed path may be coming in more than 1 frame. Compile
644    // the results into a single string.
645
646    // Read the server push body.
647    std::string result2;
648    ReadResult(trans2.get(), data, &result2);
649    // Read the response body.
650    std::string result;
651    ReadResult(trans, data, &result);
652
653    // Verify that we consumed all test data.
654    EXPECT_TRUE(data->at_read_eof());
655    EXPECT_TRUE(data->at_write_eof());
656
657    // Verify that the received push data is same as the expected push data.
658    EXPECT_EQ(result2.compare(expected), 0) << "Received data: "
659                                            << result2
660                                            << "||||| Expected data: "
661                                            << expected;
662
663    // Verify the SYN_REPLY.
664    // Copy the response info, because trans goes away.
665    *response = *trans->GetResponseInfo();
666    *push_response = *trans2->GetResponseInfo();
667
668    VerifyStreamsClosed(helper);
669  }
670
671  static void DeleteSessionCallback(NormalSpdyTransactionHelper* helper,
672                                    int result) {
673    helper->ResetTrans();
674  }
675
676  static void StartTransactionCallback(
677      const scoped_refptr<HttpNetworkSession>& session,
678      int result) {
679    scoped_ptr<HttpNetworkTransaction> trans(
680        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
681    TestCompletionCallback callback;
682    HttpRequestInfo request;
683    request.method = "GET";
684    request.url = GURL("http://www.google.com/");
685    request.load_flags = 0;
686    int rv = trans->Start(&request, callback.callback(), BoundNetLog());
687    EXPECT_EQ(ERR_IO_PENDING, rv);
688    callback.WaitForResult();
689  }
690
691  SpdyTestUtil spdy_util_;
692
693 private:
694  scoped_ptr<UploadDataStream> upload_data_stream_;
695  bool google_get_request_initialized_;
696  bool google_post_request_initialized_;
697  bool google_chunked_post_request_initialized_;
698  HttpRequestInfo google_get_request_;
699  HttpRequestInfo google_post_request_;
700  HttpRequestInfo google_chunked_post_request_;
701  HttpRequestInfo google_get_push_request_;
702  base::ScopedTempDir temp_dir_;
703};
704
705//-----------------------------------------------------------------------------
706// All tests are run with three different connection types: SPDY after NPN
707// negotiation, SPDY without SSL, and SPDY with SSL.
708//
709// TODO(akalin): Use ::testing::Combine() when we are able to use
710// <tr1/tuple>.
711INSTANTIATE_TEST_CASE_P(
712    Spdy,
713    SpdyNetworkTransactionTest,
714    ::testing::Values(
715        SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2, SPDYNOSSL),
716        SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2, SPDYSSL),
717        SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2, SPDYNPN),
718        SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYNOSSL),
719        SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYSSL),
720        SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYNPN),
721        SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNOSSL),
722        SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYSSL),
723        SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNPN),
724        SpdyNetworkTransactionTestParams(kProtoSPDY4, SPDYNOSSL),
725        SpdyNetworkTransactionTestParams(kProtoSPDY4, SPDYSSL),
726        SpdyNetworkTransactionTestParams(kProtoSPDY4, SPDYNPN)));
727
728// Verify HttpNetworkTransaction constructor.
729TEST_P(SpdyNetworkTransactionTest, Constructor) {
730  scoped_ptr<SpdySessionDependencies> session_deps(
731      CreateSpdySessionDependencies(GetParam()));
732  scoped_refptr<HttpNetworkSession> session(
733      SpdySessionDependencies::SpdyCreateSession(session_deps.get()));
734  scoped_ptr<HttpTransaction> trans(
735      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
736}
737
738TEST_P(SpdyNetworkTransactionTest, Get) {
739  // Construct the request.
740  scoped_ptr<SpdyFrame> req(
741      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
742  MockWrite writes[] = { CreateMockWrite(*req) };
743
744  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
745  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
746  MockRead reads[] = {
747    CreateMockRead(*resp),
748    CreateMockRead(*body),
749    MockRead(ASYNC, 0, 0)  // EOF
750  };
751
752  DelayedSocketData data(1, reads, arraysize(reads),
753                         writes, arraysize(writes));
754  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
755                                     BoundNetLog(), GetParam(), NULL);
756  helper.RunToCompletion(&data);
757  TransactionHelperResult out = helper.output();
758  EXPECT_EQ(OK, out.rv);
759  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
760  EXPECT_EQ("hello!", out.response_data);
761}
762
763TEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) {
764  for (RequestPriority p = MINIMUM_PRIORITY; p <= MAXIMUM_PRIORITY;
765       p = RequestPriority(p + 1)) {
766    // Construct the request.
767    scoped_ptr<SpdyFrame> req(
768        spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, p, true));
769    MockWrite writes[] = { CreateMockWrite(*req) };
770
771    SpdyPriority spdy_prio = 0;
772    EXPECT_TRUE(GetSpdyPriority(spdy_util_.spdy_version(), *req, &spdy_prio));
773    // this repeats the RequestPriority-->SpdyPriority mapping from
774    // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
775    // sure it's being done right.
776    if (spdy_util_.spdy_version() < SPDY3) {
777      switch(p) {
778        case HIGHEST:
779          EXPECT_EQ(0, spdy_prio);
780          break;
781        case MEDIUM:
782          EXPECT_EQ(1, spdy_prio);
783          break;
784        case LOW:
785        case LOWEST:
786          EXPECT_EQ(2, spdy_prio);
787          break;
788        case IDLE:
789          EXPECT_EQ(3, spdy_prio);
790          break;
791        default:
792          FAIL();
793      }
794    } else {
795      switch(p) {
796        case HIGHEST:
797          EXPECT_EQ(0, spdy_prio);
798          break;
799        case MEDIUM:
800          EXPECT_EQ(1, spdy_prio);
801          break;
802        case LOW:
803          EXPECT_EQ(2, spdy_prio);
804          break;
805        case LOWEST:
806          EXPECT_EQ(3, spdy_prio);
807          break;
808        case IDLE:
809          EXPECT_EQ(4, spdy_prio);
810          break;
811        default:
812          FAIL();
813      }
814    }
815
816    scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
817    scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
818    MockRead reads[] = {
819      CreateMockRead(*resp),
820      CreateMockRead(*body),
821      MockRead(ASYNC, 0, 0)  // EOF
822    };
823
824    DelayedSocketData data(1, reads, arraysize(reads),
825                              writes, arraysize(writes));
826    HttpRequestInfo http_req = CreateGetRequest();
827
828    NormalSpdyTransactionHelper helper(http_req, p, BoundNetLog(),
829                                       GetParam(), NULL);
830    helper.RunToCompletion(&data);
831    TransactionHelperResult out = helper.output();
832    EXPECT_EQ(OK, out.rv);
833    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
834    EXPECT_EQ("hello!", out.response_data);
835  }
836}
837
838// Start three gets simultaniously; making sure that multiplexed
839// streams work properly.
840
841// This can't use the TransactionHelper method, since it only
842// handles a single transaction, and finishes them as soon
843// as it launches them.
844
845// TODO(gavinp): create a working generalized TransactionHelper that
846// can allow multiple streams in flight.
847
848TEST_P(SpdyNetworkTransactionTest, ThreeGets) {
849  scoped_ptr<SpdyFrame> req(
850      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
851  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
852  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
853  scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
854
855  scoped_ptr<SpdyFrame> req2(
856      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
857  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
858  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
859  scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
860
861  scoped_ptr<SpdyFrame> req3(
862      spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
863  scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
864  scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
865  scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
866
867  MockWrite writes[] = {
868    CreateMockWrite(*req),
869    CreateMockWrite(*req2),
870    CreateMockWrite(*req3),
871  };
872  MockRead reads[] = {
873    CreateMockRead(*resp, 1),
874    CreateMockRead(*body),
875    CreateMockRead(*resp2, 4),
876    CreateMockRead(*body2),
877    CreateMockRead(*resp3, 7),
878    CreateMockRead(*body3),
879
880    CreateMockRead(*fbody),
881    CreateMockRead(*fbody2),
882    CreateMockRead(*fbody3),
883
884    MockRead(ASYNC, 0, 0),  // EOF
885  };
886  OrderedSocketData data(reads, arraysize(reads),
887                         writes, arraysize(writes));
888  OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
889
890  BoundNetLog log;
891  TransactionHelperResult out;
892  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
893                                     BoundNetLog(), GetParam(), NULL);
894  helper.RunPreTestSetup();
895  helper.AddData(&data);
896  // We require placeholder data because three get requests are sent out, so
897  // there needs to be three sets of SSL connection data.
898  helper.AddData(&data_placeholder);
899  helper.AddData(&data_placeholder);
900  scoped_ptr<HttpNetworkTransaction> trans1(
901      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
902  scoped_ptr<HttpNetworkTransaction> trans2(
903      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
904  scoped_ptr<HttpNetworkTransaction> trans3(
905      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
906
907  TestCompletionCallback callback1;
908  TestCompletionCallback callback2;
909  TestCompletionCallback callback3;
910
911  HttpRequestInfo httpreq1 = CreateGetRequest();
912  HttpRequestInfo httpreq2 = CreateGetRequest();
913  HttpRequestInfo httpreq3 = CreateGetRequest();
914
915  out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
916  ASSERT_EQ(ERR_IO_PENDING, out.rv);
917  out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
918  ASSERT_EQ(ERR_IO_PENDING, out.rv);
919  out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
920  ASSERT_EQ(ERR_IO_PENDING, out.rv);
921
922  out.rv = callback1.WaitForResult();
923  ASSERT_EQ(OK, out.rv);
924  out.rv = callback3.WaitForResult();
925  ASSERT_EQ(OK, out.rv);
926
927  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
928  EXPECT_TRUE(response1->headers.get() != NULL);
929  EXPECT_TRUE(response1->was_fetched_via_spdy);
930  out.status_line = response1->headers->GetStatusLine();
931  out.response_info = *response1;
932
933  trans2->GetResponseInfo();
934
935  out.rv = ReadTransaction(trans1.get(), &out.response_data);
936  helper.VerifyDataConsumed();
937  EXPECT_EQ(OK, out.rv);
938
939  EXPECT_EQ(OK, out.rv);
940  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
941  EXPECT_EQ("hello!hello!", out.response_data);
942}
943
944TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
945  scoped_ptr<SpdyFrame> req(
946      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
947  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
948  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
949  scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
950
951  scoped_ptr<SpdyFrame> req2(
952      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
953  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
954  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
955  scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
956
957  MockWrite writes[] = {
958    CreateMockWrite(*req),
959    CreateMockWrite(*req2),
960  };
961  MockRead reads[] = {
962    CreateMockRead(*resp, 1),
963    CreateMockRead(*body),
964    CreateMockRead(*resp2, 4),
965    CreateMockRead(*body2),
966    CreateMockRead(*fbody),
967    CreateMockRead(*fbody2),
968    MockRead(ASYNC, 0, 0),  // EOF
969  };
970  OrderedSocketData data(reads, arraysize(reads),
971                         writes, arraysize(writes));
972
973  MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
974
975  OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
976  data_placeholder.set_connect_data(never_finishing_connect);
977
978  BoundNetLog log;
979  TransactionHelperResult out;
980  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
981                                     BoundNetLog(), GetParam(), NULL);
982  helper.RunPreTestSetup();
983  helper.AddData(&data);
984  // We require placeholder data because two get requests are sent out, so
985  // there needs to be two sets of SSL connection data.
986  helper.AddData(&data_placeholder);
987  scoped_ptr<HttpNetworkTransaction> trans1(
988      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
989  scoped_ptr<HttpNetworkTransaction> trans2(
990      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
991
992  TestCompletionCallback callback1;
993  TestCompletionCallback callback2;
994
995  HttpRequestInfo httpreq1 = CreateGetRequest();
996  HttpRequestInfo httpreq2 = CreateGetRequest();
997
998  out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
999  ASSERT_EQ(ERR_IO_PENDING, out.rv);
1000  out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1001  ASSERT_EQ(ERR_IO_PENDING, out.rv);
1002
1003  out.rv = callback1.WaitForResult();
1004  ASSERT_EQ(OK, out.rv);
1005  out.rv = callback2.WaitForResult();
1006  ASSERT_EQ(OK, out.rv);
1007
1008  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1009  EXPECT_TRUE(response1->headers.get() != NULL);
1010  EXPECT_TRUE(response1->was_fetched_via_spdy);
1011  out.status_line = response1->headers->GetStatusLine();
1012  out.response_info = *response1;
1013  out.rv = ReadTransaction(trans1.get(), &out.response_data);
1014  EXPECT_EQ(OK, out.rv);
1015  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1016  EXPECT_EQ("hello!hello!", out.response_data);
1017
1018  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1019  EXPECT_TRUE(response2->headers.get() != NULL);
1020  EXPECT_TRUE(response2->was_fetched_via_spdy);
1021  out.status_line = response2->headers->GetStatusLine();
1022  out.response_info = *response2;
1023  out.rv = ReadTransaction(trans2.get(), &out.response_data);
1024  EXPECT_EQ(OK, out.rv);
1025  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1026  EXPECT_EQ("hello!hello!", out.response_data);
1027
1028  helper.VerifyDataConsumed();
1029}
1030
1031TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
1032  scoped_ptr<SpdyFrame> req(
1033      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1034  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1035  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1036  scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
1037
1038  scoped_ptr<SpdyFrame> req2(
1039      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1040  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1041  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1042  scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1043
1044  MockWrite writes[] = {
1045    CreateMockWrite(*req),
1046    CreateMockWrite(*req2),
1047  };
1048  MockRead reads[] = {
1049    CreateMockRead(*resp, 1),
1050    CreateMockRead(*body),
1051    CreateMockRead(*resp2, 4),
1052    CreateMockRead(*body2),
1053    CreateMockRead(*fbody),
1054    CreateMockRead(*fbody2),
1055    MockRead(ASYNC, 0, 0),  // EOF
1056  };
1057  OrderedSocketData preconnect_data(reads, arraysize(reads),
1058                                    writes, arraysize(writes));
1059
1060  MockConnect never_finishing_connect(ASYNC, ERR_IO_PENDING);
1061
1062  OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1063  data_placeholder.set_connect_data(never_finishing_connect);
1064
1065  BoundNetLog log;
1066  TransactionHelperResult out;
1067  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1068                                     BoundNetLog(), GetParam(), NULL);
1069  helper.RunPreTestSetup();
1070  helper.AddData(&preconnect_data);
1071  // We require placeholder data because 3 connections are attempted (first is
1072  // the preconnect, 2nd and 3rd are the never finished connections.
1073  helper.AddData(&data_placeholder);
1074  helper.AddData(&data_placeholder);
1075
1076  scoped_ptr<HttpNetworkTransaction> trans1(
1077      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1078  scoped_ptr<HttpNetworkTransaction> trans2(
1079      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1080
1081  TestCompletionCallback callback1;
1082  TestCompletionCallback callback2;
1083
1084  HttpRequestInfo httpreq = CreateGetRequest();
1085
1086  // Preconnect the first.
1087  SSLConfig preconnect_ssl_config;
1088  helper.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config);
1089  HttpStreamFactory* http_stream_factory =
1090      helper.session()->http_stream_factory();
1091  helper.session()->GetNextProtos(&preconnect_ssl_config.next_protos);
1092
1093  http_stream_factory->PreconnectStreams(
1094      1, httpreq, DEFAULT_PRIORITY,
1095      preconnect_ssl_config, preconnect_ssl_config);
1096
1097  out.rv = trans1->Start(&httpreq, callback1.callback(), log);
1098  ASSERT_EQ(ERR_IO_PENDING, out.rv);
1099  out.rv = trans2->Start(&httpreq, callback2.callback(), log);
1100  ASSERT_EQ(ERR_IO_PENDING, out.rv);
1101
1102  out.rv = callback1.WaitForResult();
1103  ASSERT_EQ(OK, out.rv);
1104  out.rv = callback2.WaitForResult();
1105  ASSERT_EQ(OK, out.rv);
1106
1107  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1108  EXPECT_TRUE(response1->headers.get() != NULL);
1109  EXPECT_TRUE(response1->was_fetched_via_spdy);
1110  out.status_line = response1->headers->GetStatusLine();
1111  out.response_info = *response1;
1112  out.rv = ReadTransaction(trans1.get(), &out.response_data);
1113  EXPECT_EQ(OK, out.rv);
1114  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1115  EXPECT_EQ("hello!hello!", out.response_data);
1116
1117  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1118  EXPECT_TRUE(response2->headers.get() != NULL);
1119  EXPECT_TRUE(response2->was_fetched_via_spdy);
1120  out.status_line = response2->headers->GetStatusLine();
1121  out.response_info = *response2;
1122  out.rv = ReadTransaction(trans2.get(), &out.response_data);
1123  EXPECT_EQ(OK, out.rv);
1124  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1125  EXPECT_EQ("hello!hello!", out.response_data);
1126
1127  helper.VerifyDataConsumed();
1128}
1129
1130// Similar to ThreeGets above, however this test adds a SETTINGS
1131// frame.  The SETTINGS frame is read during the IO loop waiting on
1132// the first transaction completion, and sets a maximum concurrent
1133// stream limit of 1.  This means that our IO loop exists after the
1134// second transaction completes, so we can assert on read_index().
1135TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
1136  // Construct the request.
1137  scoped_ptr<SpdyFrame> req(
1138      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1139  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1140  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1141  scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
1142
1143  scoped_ptr<SpdyFrame> req2(
1144      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1145  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1146  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1147  scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1148
1149  scoped_ptr<SpdyFrame> req3(
1150      spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
1151  scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
1152  scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
1153  scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
1154
1155  SettingsMap settings;
1156  const uint32 max_concurrent_streams = 1;
1157  settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1158      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1159  scoped_ptr<SpdyFrame> settings_frame(
1160      spdy_util_.ConstructSpdySettings(settings));
1161  scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1162
1163  MockWrite writes[] = {
1164    CreateMockWrite(*req),
1165    CreateMockWrite(*settings_ack, 2),
1166    CreateMockWrite(*req2),
1167    CreateMockWrite(*req3),
1168  };
1169
1170  MockRead reads[] = {
1171    CreateMockRead(*settings_frame, 1),
1172    CreateMockRead(*resp),
1173    CreateMockRead(*body),
1174    CreateMockRead(*fbody),
1175    CreateMockRead(*resp2, 8),
1176    CreateMockRead(*body2),
1177    CreateMockRead(*fbody2),
1178    CreateMockRead(*resp3, 13),
1179    CreateMockRead(*body3),
1180    CreateMockRead(*fbody3),
1181
1182    MockRead(ASYNC, 0, 0),  // EOF
1183  };
1184
1185  OrderedSocketData data(reads, arraysize(reads),
1186                         writes, arraysize(writes));
1187  OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1188
1189  BoundNetLog log;
1190  TransactionHelperResult out;
1191  {
1192    NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1193                                       BoundNetLog(), GetParam(), NULL);
1194    helper.RunPreTestSetup();
1195    helper.AddData(&data);
1196    // We require placeholder data because three get requests are sent out, so
1197    // there needs to be three sets of SSL connection data.
1198    helper.AddData(&data_placeholder);
1199    helper.AddData(&data_placeholder);
1200    scoped_ptr<HttpNetworkTransaction> trans1(
1201        new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1202    scoped_ptr<HttpNetworkTransaction> trans2(
1203        new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1204    scoped_ptr<HttpNetworkTransaction> trans3(
1205        new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1206
1207    TestCompletionCallback callback1;
1208    TestCompletionCallback callback2;
1209    TestCompletionCallback callback3;
1210
1211    HttpRequestInfo httpreq1 = CreateGetRequest();
1212    HttpRequestInfo httpreq2 = CreateGetRequest();
1213    HttpRequestInfo httpreq3 = CreateGetRequest();
1214
1215    out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1216    ASSERT_EQ(out.rv, ERR_IO_PENDING);
1217    // Run transaction 1 through quickly to force a read of our SETTINGS
1218    // frame.
1219    out.rv = callback1.WaitForResult();
1220    ASSERT_EQ(OK, out.rv);
1221
1222    out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1223    ASSERT_EQ(out.rv, ERR_IO_PENDING);
1224    out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1225    ASSERT_EQ(out.rv, ERR_IO_PENDING);
1226    out.rv = callback2.WaitForResult();
1227    ASSERT_EQ(OK, out.rv);
1228    EXPECT_EQ(7U, data.read_index());  // i.e. the third trans was queued
1229
1230    out.rv = callback3.WaitForResult();
1231    ASSERT_EQ(OK, out.rv);
1232
1233    const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1234    ASSERT_TRUE(response1 != NULL);
1235    EXPECT_TRUE(response1->headers.get() != NULL);
1236    EXPECT_TRUE(response1->was_fetched_via_spdy);
1237    out.status_line = response1->headers->GetStatusLine();
1238    out.response_info = *response1;
1239    out.rv = ReadTransaction(trans1.get(), &out.response_data);
1240    EXPECT_EQ(OK, out.rv);
1241    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1242    EXPECT_EQ("hello!hello!", out.response_data);
1243
1244    const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1245    out.status_line = response2->headers->GetStatusLine();
1246    out.response_info = *response2;
1247    out.rv = ReadTransaction(trans2.get(), &out.response_data);
1248    EXPECT_EQ(OK, out.rv);
1249    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1250    EXPECT_EQ("hello!hello!", out.response_data);
1251
1252    const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1253    out.status_line = response3->headers->GetStatusLine();
1254    out.response_info = *response3;
1255    out.rv = ReadTransaction(trans3.get(), &out.response_data);
1256    EXPECT_EQ(OK, out.rv);
1257    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1258    EXPECT_EQ("hello!hello!", out.response_data);
1259
1260    helper.VerifyDataConsumed();
1261  }
1262  EXPECT_EQ(OK, out.rv);
1263}
1264
1265// Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1266// a fourth transaction.  The third and fourth transactions have
1267// different data ("hello!" vs "hello!hello!") and because of the
1268// user specified priority, we expect to see them inverted in
1269// the response from the server.
1270TEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
1271  // Construct the request.
1272  scoped_ptr<SpdyFrame> req(
1273      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1274  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1275  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1276  scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
1277
1278  scoped_ptr<SpdyFrame> req2(
1279      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1280  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1281  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1282  scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1283
1284  scoped_ptr<SpdyFrame> req4(
1285      spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, HIGHEST, true));
1286  scoped_ptr<SpdyFrame> resp4(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
1287  scoped_ptr<SpdyFrame> fbody4(spdy_util_.ConstructSpdyBodyFrame(5, true));
1288
1289  scoped_ptr<SpdyFrame> req3(
1290      spdy_util_.ConstructSpdyGet(NULL, 0, false, 7, LOWEST, true));
1291  scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 7));
1292  scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(7, false));
1293  scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(7, true));
1294
1295  SettingsMap settings;
1296  const uint32 max_concurrent_streams = 1;
1297  settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1298      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1299  scoped_ptr<SpdyFrame> settings_frame(
1300      spdy_util_.ConstructSpdySettings(settings));
1301  scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1302
1303  MockWrite writes[] = { CreateMockWrite(*req),
1304    CreateMockWrite(*settings_ack, 2),
1305    CreateMockWrite(*req2),
1306    CreateMockWrite(*req4),
1307    CreateMockWrite(*req3),
1308  };
1309  MockRead reads[] = {
1310    CreateMockRead(*settings_frame, 1),
1311    CreateMockRead(*resp),
1312    CreateMockRead(*body),
1313    CreateMockRead(*fbody),
1314    CreateMockRead(*resp2, 8),
1315    CreateMockRead(*body2),
1316    CreateMockRead(*fbody2),
1317    CreateMockRead(*resp4, 14),
1318    CreateMockRead(*fbody4),
1319    CreateMockRead(*resp3, 17),
1320    CreateMockRead(*body3),
1321    CreateMockRead(*fbody3),
1322
1323    MockRead(ASYNC, 0, 0),  // EOF
1324  };
1325
1326  OrderedSocketData data(reads, arraysize(reads),
1327                         writes, arraysize(writes));
1328  OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1329
1330  BoundNetLog log;
1331  TransactionHelperResult out;
1332  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1333                                     BoundNetLog(), GetParam(), NULL);
1334  helper.RunPreTestSetup();
1335  helper.AddData(&data);
1336  // We require placeholder data because four get requests are sent out, so
1337  // there needs to be four sets of SSL connection data.
1338  helper.AddData(&data_placeholder);
1339  helper.AddData(&data_placeholder);
1340  helper.AddData(&data_placeholder);
1341  scoped_ptr<HttpNetworkTransaction> trans1(
1342      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1343  scoped_ptr<HttpNetworkTransaction> trans2(
1344      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1345  scoped_ptr<HttpNetworkTransaction> trans3(
1346      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1347  scoped_ptr<HttpNetworkTransaction> trans4(
1348      new HttpNetworkTransaction(HIGHEST, helper.session().get()));
1349
1350  TestCompletionCallback callback1;
1351  TestCompletionCallback callback2;
1352  TestCompletionCallback callback3;
1353  TestCompletionCallback callback4;
1354
1355  HttpRequestInfo httpreq1 = CreateGetRequest();
1356  HttpRequestInfo httpreq2 = CreateGetRequest();
1357  HttpRequestInfo httpreq3 = CreateGetRequest();
1358  HttpRequestInfo httpreq4 = CreateGetRequest();
1359
1360  out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1361  ASSERT_EQ(ERR_IO_PENDING, out.rv);
1362  // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1363  out.rv = callback1.WaitForResult();
1364  ASSERT_EQ(OK, out.rv);
1365
1366  out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1367  ASSERT_EQ(ERR_IO_PENDING, out.rv);
1368  out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1369  ASSERT_EQ(ERR_IO_PENDING, out.rv);
1370  out.rv = trans4->Start(&httpreq4, callback4.callback(), log);
1371  ASSERT_EQ(ERR_IO_PENDING, out.rv);
1372
1373  out.rv = callback2.WaitForResult();
1374  ASSERT_EQ(OK, out.rv);
1375  EXPECT_EQ(data.read_index(), 7U);  // i.e. the third & fourth trans queued
1376
1377  out.rv = callback3.WaitForResult();
1378  ASSERT_EQ(OK, out.rv);
1379
1380  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1381  EXPECT_TRUE(response1->headers.get() != NULL);
1382  EXPECT_TRUE(response1->was_fetched_via_spdy);
1383  out.status_line = response1->headers->GetStatusLine();
1384  out.response_info = *response1;
1385  out.rv = ReadTransaction(trans1.get(), &out.response_data);
1386  EXPECT_EQ(OK, out.rv);
1387  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1388  EXPECT_EQ("hello!hello!", out.response_data);
1389
1390  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1391  out.status_line = response2->headers->GetStatusLine();
1392  out.response_info = *response2;
1393  out.rv = ReadTransaction(trans2.get(), &out.response_data);
1394  EXPECT_EQ(OK, out.rv);
1395  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1396  EXPECT_EQ("hello!hello!", out.response_data);
1397
1398  // notice: response3 gets two hellos, response4 gets one
1399  // hello, so we know dequeuing priority was respected.
1400  const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1401  out.status_line = response3->headers->GetStatusLine();
1402  out.response_info = *response3;
1403  out.rv = ReadTransaction(trans3.get(), &out.response_data);
1404  EXPECT_EQ(OK, out.rv);
1405  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1406  EXPECT_EQ("hello!hello!", out.response_data);
1407
1408  out.rv = callback4.WaitForResult();
1409  EXPECT_EQ(OK, out.rv);
1410  const HttpResponseInfo* response4 = trans4->GetResponseInfo();
1411  out.status_line = response4->headers->GetStatusLine();
1412  out.response_info = *response4;
1413  out.rv = ReadTransaction(trans4.get(), &out.response_data);
1414  EXPECT_EQ(OK, out.rv);
1415  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1416  EXPECT_EQ("hello!", out.response_data);
1417  helper.VerifyDataConsumed();
1418  EXPECT_EQ(OK, out.rv);
1419}
1420
1421// Similar to ThreeGetsMaxConcurrrent above, however, this test
1422// deletes a session in the middle of the transaction to insure
1423// that we properly remove pendingcreatestream objects from
1424// the spdy_session
1425TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
1426  // Construct the request.
1427  scoped_ptr<SpdyFrame> req(
1428      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1429  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1430  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1431  scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
1432
1433  scoped_ptr<SpdyFrame> req2(
1434      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1435  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1436  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1437  scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1438
1439  SettingsMap settings;
1440  const uint32 max_concurrent_streams = 1;
1441  settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1442      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1443  scoped_ptr<SpdyFrame> settings_frame(
1444      spdy_util_.ConstructSpdySettings(settings));
1445  scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1446
1447  MockWrite writes[] = {
1448    CreateMockWrite(*req),
1449    CreateMockWrite(*settings_ack, 2),
1450    CreateMockWrite(*req2),
1451  };
1452  MockRead reads[] = {
1453    CreateMockRead(*settings_frame, 1),
1454    CreateMockRead(*resp),
1455    CreateMockRead(*body),
1456    CreateMockRead(*fbody),
1457    CreateMockRead(*resp2, 8),
1458    CreateMockRead(*body2),
1459    CreateMockRead(*fbody2),
1460    MockRead(ASYNC, 0, 0),  // EOF
1461  };
1462
1463  OrderedSocketData data(reads, arraysize(reads),
1464                         writes, arraysize(writes));
1465  OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1466
1467  BoundNetLog log;
1468  TransactionHelperResult out;
1469  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1470                                     BoundNetLog(), GetParam(), NULL);
1471  helper.RunPreTestSetup();
1472  helper.AddData(&data);
1473  // We require placeholder data because three get requests are sent out, so
1474  // there needs to be three sets of SSL connection data.
1475  helper.AddData(&data_placeholder);
1476  helper.AddData(&data_placeholder);
1477  scoped_ptr<HttpNetworkTransaction> trans1(
1478      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1479  scoped_ptr<HttpNetworkTransaction> trans2(
1480      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1481  scoped_ptr<HttpNetworkTransaction> trans3(
1482      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1483
1484  TestCompletionCallback callback1;
1485  TestCompletionCallback callback2;
1486  TestCompletionCallback callback3;
1487
1488  HttpRequestInfo httpreq1 = CreateGetRequest();
1489  HttpRequestInfo httpreq2 = CreateGetRequest();
1490  HttpRequestInfo httpreq3 = CreateGetRequest();
1491
1492  out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1493  ASSERT_EQ(out.rv, ERR_IO_PENDING);
1494  // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1495  out.rv = callback1.WaitForResult();
1496  ASSERT_EQ(OK, out.rv);
1497
1498  out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1499  ASSERT_EQ(out.rv, ERR_IO_PENDING);
1500  out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1501  delete trans3.release();
1502  ASSERT_EQ(out.rv, ERR_IO_PENDING);
1503  out.rv = callback2.WaitForResult();
1504  ASSERT_EQ(OK, out.rv);
1505
1506  EXPECT_EQ(8U, data.read_index());
1507
1508  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1509  ASSERT_TRUE(response1 != NULL);
1510  EXPECT_TRUE(response1->headers.get() != NULL);
1511  EXPECT_TRUE(response1->was_fetched_via_spdy);
1512  out.status_line = response1->headers->GetStatusLine();
1513  out.response_info = *response1;
1514  out.rv = ReadTransaction(trans1.get(), &out.response_data);
1515  EXPECT_EQ(OK, out.rv);
1516  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1517  EXPECT_EQ("hello!hello!", out.response_data);
1518
1519  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1520  ASSERT_TRUE(response2 != NULL);
1521  out.status_line = response2->headers->GetStatusLine();
1522  out.response_info = *response2;
1523  out.rv = ReadTransaction(trans2.get(), &out.response_data);
1524  EXPECT_EQ(OK, out.rv);
1525  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1526  EXPECT_EQ("hello!hello!", out.response_data);
1527  helper.VerifyDataConsumed();
1528  EXPECT_EQ(OK, out.rv);
1529}
1530
1531namespace {
1532
1533// The KillerCallback will delete the transaction on error as part of the
1534// callback.
1535class KillerCallback : public TestCompletionCallbackBase {
1536 public:
1537  explicit KillerCallback(HttpNetworkTransaction* transaction)
1538      : transaction_(transaction),
1539        callback_(base::Bind(&KillerCallback::OnComplete,
1540                             base::Unretained(this))) {
1541  }
1542
1543  virtual ~KillerCallback() {}
1544
1545  const CompletionCallback& callback() const { return callback_; }
1546
1547 private:
1548  void OnComplete(int result) {
1549    if (result < 0)
1550      delete transaction_;
1551
1552    SetResult(result);
1553  }
1554
1555  HttpNetworkTransaction* transaction_;
1556  CompletionCallback callback_;
1557};
1558
1559}  // namespace
1560
1561// Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1562// closes the socket while we have a pending transaction waiting for
1563// a pending stream creation.  http://crbug.com/52901
1564TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
1565  // Construct the request.
1566  scoped_ptr<SpdyFrame> req(
1567      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1568  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1569  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1570  scoped_ptr<SpdyFrame> fin_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1571
1572  scoped_ptr<SpdyFrame> req2(
1573      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1574  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1575
1576  SettingsMap settings;
1577  const uint32 max_concurrent_streams = 1;
1578  settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1579      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1580  scoped_ptr<SpdyFrame> settings_frame(
1581      spdy_util_.ConstructSpdySettings(settings));
1582  scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1583
1584  MockWrite writes[] = {
1585    CreateMockWrite(*req),
1586    CreateMockWrite(*settings_ack, 2),
1587    CreateMockWrite(*req2),
1588  };
1589  MockRead reads[] = {
1590    CreateMockRead(*settings_frame, 1),
1591    CreateMockRead(*resp),
1592    CreateMockRead(*body),
1593    CreateMockRead(*fin_body),
1594    CreateMockRead(*resp2, 8),
1595    MockRead(ASYNC, ERR_CONNECTION_RESET, 0),  // Abort!
1596  };
1597
1598  OrderedSocketData data(reads, arraysize(reads),
1599                         writes, arraysize(writes));
1600  OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1601
1602  BoundNetLog log;
1603  TransactionHelperResult out;
1604  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1605                                     BoundNetLog(), GetParam(), NULL);
1606  helper.RunPreTestSetup();
1607  helper.AddData(&data);
1608  // We require placeholder data because three get requests are sent out, so
1609  // there needs to be three sets of SSL connection data.
1610  helper.AddData(&data_placeholder);
1611  helper.AddData(&data_placeholder);
1612  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session().get());
1613  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session().get());
1614  HttpNetworkTransaction* trans3(
1615      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1616
1617  TestCompletionCallback callback1;
1618  TestCompletionCallback callback2;
1619  KillerCallback callback3(trans3);
1620
1621  HttpRequestInfo httpreq1 = CreateGetRequest();
1622  HttpRequestInfo httpreq2 = CreateGetRequest();
1623  HttpRequestInfo httpreq3 = CreateGetRequest();
1624
1625  out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
1626  ASSERT_EQ(out.rv, ERR_IO_PENDING);
1627  // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1628  out.rv = callback1.WaitForResult();
1629  ASSERT_EQ(OK, out.rv);
1630
1631  out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
1632  ASSERT_EQ(out.rv, ERR_IO_PENDING);
1633  out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1634  ASSERT_EQ(out.rv, ERR_IO_PENDING);
1635  out.rv = callback3.WaitForResult();
1636  ASSERT_EQ(ERR_ABORTED, out.rv);
1637
1638  EXPECT_EQ(6U, data.read_index());
1639
1640  const HttpResponseInfo* response1 = trans1.GetResponseInfo();
1641  ASSERT_TRUE(response1 != NULL);
1642  EXPECT_TRUE(response1->headers.get() != NULL);
1643  EXPECT_TRUE(response1->was_fetched_via_spdy);
1644  out.status_line = response1->headers->GetStatusLine();
1645  out.response_info = *response1;
1646  out.rv = ReadTransaction(&trans1, &out.response_data);
1647  EXPECT_EQ(OK, out.rv);
1648
1649  const HttpResponseInfo* response2 = trans2.GetResponseInfo();
1650  ASSERT_TRUE(response2 != NULL);
1651  out.status_line = response2->headers->GetStatusLine();
1652  out.response_info = *response2;
1653  out.rv = ReadTransaction(&trans2, &out.response_data);
1654  EXPECT_EQ(ERR_CONNECTION_RESET, out.rv);
1655
1656  helper.VerifyDataConsumed();
1657}
1658
1659// Test that a simple PUT request works.
1660TEST_P(SpdyNetworkTransactionTest, Put) {
1661  // Setup the request
1662  HttpRequestInfo request;
1663  request.method = "PUT";
1664  request.url = GURL("http://www.google.com/");
1665
1666  scoped_ptr<SpdyHeaderBlock> put_headers(
1667      spdy_util_.ConstructPutHeaderBlock("http://www.google.com", 0));
1668  scoped_ptr<SpdyFrame> req(
1669      spdy_util_.ConstructSpdySyn(1, *put_headers, LOWEST, false, true));
1670  MockWrite writes[] = {
1671    CreateMockWrite(*req),
1672  };
1673
1674  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1675  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1676  MockRead reads[] = {
1677    CreateMockRead(*resp),
1678    CreateMockRead(*body),
1679    MockRead(ASYNC, 0, 0)  // EOF
1680  };
1681
1682  DelayedSocketData data(1, reads, arraysize(reads),
1683                         writes, arraysize(writes));
1684  NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1685                                     BoundNetLog(), GetParam(), NULL);
1686  helper.RunToCompletion(&data);
1687  TransactionHelperResult out = helper.output();
1688
1689  EXPECT_EQ(OK, out.rv);
1690  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1691}
1692
1693// Test that a simple HEAD request works.
1694TEST_P(SpdyNetworkTransactionTest, Head) {
1695  // Setup the request
1696  HttpRequestInfo request;
1697  request.method = "HEAD";
1698  request.url = GURL("http://www.google.com/");
1699
1700  scoped_ptr<SpdyHeaderBlock> head_headers(
1701      spdy_util_.ConstructHeadHeaderBlock("http://www.google.com", 0));
1702  scoped_ptr<SpdyFrame> req(
1703      spdy_util_.ConstructSpdySyn(1, *head_headers, LOWEST, false, true));
1704  MockWrite writes[] = {
1705    CreateMockWrite(*req),
1706  };
1707
1708  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1709  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1710  MockRead reads[] = {
1711    CreateMockRead(*resp),
1712    CreateMockRead(*body),
1713    MockRead(ASYNC, 0, 0)  // EOF
1714  };
1715
1716  DelayedSocketData data(1, reads, arraysize(reads),
1717                         writes, arraysize(writes));
1718  NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1719                                     BoundNetLog(), GetParam(), NULL);
1720  helper.RunToCompletion(&data);
1721  TransactionHelperResult out = helper.output();
1722
1723  EXPECT_EQ(OK, out.rv);
1724  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1725}
1726
1727// Test that a simple POST works.
1728TEST_P(SpdyNetworkTransactionTest, Post) {
1729  scoped_ptr<SpdyFrame> req(
1730      spdy_util_.ConstructSpdyPost(
1731          kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
1732  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1733  MockWrite writes[] = {
1734    CreateMockWrite(*req),
1735    CreateMockWrite(*body),  // POST upload frame
1736  };
1737
1738  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1739  MockRead reads[] = {
1740    CreateMockRead(*resp),
1741    CreateMockRead(*body),
1742    MockRead(ASYNC, 0, 0)  // EOF
1743  };
1744
1745  DelayedSocketData data(2, reads, arraysize(reads),
1746                         writes, arraysize(writes));
1747  NormalSpdyTransactionHelper helper(CreatePostRequest(), DEFAULT_PRIORITY,
1748                                     BoundNetLog(), GetParam(), NULL);
1749  helper.RunToCompletion(&data);
1750  TransactionHelperResult out = helper.output();
1751  EXPECT_EQ(OK, out.rv);
1752  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1753  EXPECT_EQ("hello!", out.response_data);
1754}
1755
1756// Test that a POST with a file works.
1757TEST_P(SpdyNetworkTransactionTest, FilePost) {
1758  scoped_ptr<SpdyFrame> req(
1759      spdy_util_.ConstructSpdyPost(
1760          kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
1761  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1762  MockWrite writes[] = {
1763    CreateMockWrite(*req),
1764    CreateMockWrite(*body),  // POST upload frame
1765  };
1766
1767  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1768  MockRead reads[] = {
1769    CreateMockRead(*resp),
1770    CreateMockRead(*body),
1771    MockRead(ASYNC, 0, 0)  // EOF
1772  };
1773
1774  DelayedSocketData data(2, reads, arraysize(reads),
1775                         writes, arraysize(writes));
1776  NormalSpdyTransactionHelper helper(CreateFilePostRequest(), DEFAULT_PRIORITY,
1777                                     BoundNetLog(), GetParam(), NULL);
1778  helper.RunToCompletion(&data);
1779  TransactionHelperResult out = helper.output();
1780  EXPECT_EQ(OK, out.rv);
1781  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1782  EXPECT_EQ("hello!", out.response_data);
1783}
1784
1785// Test that a POST with a unreadable file fails.
1786TEST_P(SpdyNetworkTransactionTest, UnreadableFilePost) {
1787  MockWrite writes[] = {
1788    MockWrite(ASYNC, 0, 0)  // EOF
1789  };
1790  MockRead reads[] = {
1791    MockRead(ASYNC, 0, 0)  // EOF
1792  };
1793
1794  DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
1795  NormalSpdyTransactionHelper helper(CreateUnreadableFilePostRequest(),
1796                                     DEFAULT_PRIORITY,
1797                                     BoundNetLog(), GetParam(), NULL);
1798  helper.RunPreTestSetup();
1799  helper.AddData(&data);
1800  helper.RunDefaultTest();
1801
1802  base::RunLoop().RunUntilIdle();
1803  helper.VerifyDataNotConsumed();
1804  EXPECT_EQ(ERR_ACCESS_DENIED, helper.output().rv);
1805}
1806
1807// Test that a complex POST works.
1808TEST_P(SpdyNetworkTransactionTest, ComplexPost) {
1809  scoped_ptr<SpdyFrame> req(
1810      spdy_util_.ConstructSpdyPost(
1811          kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
1812  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1813  MockWrite writes[] = {
1814    CreateMockWrite(*req),
1815    CreateMockWrite(*body),  // POST upload frame
1816  };
1817
1818  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1819  MockRead reads[] = {
1820    CreateMockRead(*resp),
1821    CreateMockRead(*body),
1822    MockRead(ASYNC, 0, 0)  // EOF
1823  };
1824
1825  DelayedSocketData data(2, reads, arraysize(reads),
1826                         writes, arraysize(writes));
1827  NormalSpdyTransactionHelper helper(CreateComplexPostRequest(),
1828                                     DEFAULT_PRIORITY,
1829                                     BoundNetLog(), GetParam(), NULL);
1830  helper.RunToCompletion(&data);
1831  TransactionHelperResult out = helper.output();
1832  EXPECT_EQ(OK, out.rv);
1833  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1834  EXPECT_EQ("hello!", out.response_data);
1835}
1836
1837// Test that a chunked POST works.
1838TEST_P(SpdyNetworkTransactionTest, ChunkedPost) {
1839  scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1840  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1841  MockWrite writes[] = {
1842    CreateMockWrite(*req),
1843    CreateMockWrite(*body),
1844  };
1845
1846  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1847  MockRead reads[] = {
1848    CreateMockRead(*resp),
1849    CreateMockRead(*body),
1850    MockRead(ASYNC, 0, 0)  // EOF
1851  };
1852
1853  DelayedSocketData data(2, reads, arraysize(reads),
1854                         writes, arraysize(writes));
1855  NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
1856                                     DEFAULT_PRIORITY,
1857                                     BoundNetLog(), GetParam(), NULL);
1858
1859  // These chunks get merged into a single frame when being sent.
1860  const int kFirstChunkSize = kUploadDataSize/2;
1861  helper.request().upload_data_stream->AppendChunk(
1862      kUploadData, kFirstChunkSize, false);
1863  helper.request().upload_data_stream->AppendChunk(
1864      kUploadData + kFirstChunkSize, kUploadDataSize - kFirstChunkSize, true);
1865
1866  helper.RunToCompletion(&data);
1867  TransactionHelperResult out = helper.output();
1868  EXPECT_EQ(OK, out.rv);
1869  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1870  EXPECT_EQ(kUploadData, out.response_data);
1871}
1872
1873// Test that a chunked POST works with chunks appended after transaction starts.
1874TEST_P(SpdyNetworkTransactionTest, DelayedChunkedPost) {
1875  scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1876  scoped_ptr<SpdyFrame> chunk1(spdy_util_.ConstructSpdyBodyFrame(1, false));
1877  scoped_ptr<SpdyFrame> chunk2(spdy_util_.ConstructSpdyBodyFrame(1, false));
1878  scoped_ptr<SpdyFrame> chunk3(spdy_util_.ConstructSpdyBodyFrame(1, true));
1879  MockWrite writes[] = {
1880    CreateMockWrite(*req),
1881    CreateMockWrite(*chunk1),
1882    CreateMockWrite(*chunk2),
1883    CreateMockWrite(*chunk3),
1884  };
1885
1886  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1887  MockRead reads[] = {
1888    CreateMockRead(*resp),
1889    CreateMockRead(*chunk1),
1890    CreateMockRead(*chunk2),
1891    CreateMockRead(*chunk3),
1892    MockRead(ASYNC, 0, 0)  // EOF
1893  };
1894
1895  DelayedSocketData data(4, reads, arraysize(reads),
1896                         writes, arraysize(writes));
1897  NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
1898                                     DEFAULT_PRIORITY,
1899                                     BoundNetLog(), GetParam(), NULL);
1900
1901  helper.request().upload_data_stream->AppendChunk(
1902      kUploadData, kUploadDataSize, false);
1903
1904  helper.RunPreTestSetup();
1905  helper.AddData(&data);
1906  ASSERT_TRUE(helper.StartDefaultTest());
1907
1908  base::RunLoop().RunUntilIdle();
1909  helper.request().upload_data_stream->AppendChunk(
1910      kUploadData, kUploadDataSize, false);
1911  base::RunLoop().RunUntilIdle();
1912  helper.request().upload_data_stream->AppendChunk(
1913      kUploadData, kUploadDataSize, true);
1914
1915  helper.FinishDefaultTest();
1916  helper.VerifyDataConsumed();
1917
1918  std::string expected_response;
1919  expected_response += kUploadData;
1920  expected_response += kUploadData;
1921  expected_response += kUploadData;
1922
1923  TransactionHelperResult out = helper.output();
1924  EXPECT_EQ(OK, out.rv);
1925  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1926  EXPECT_EQ(expected_response, out.response_data);
1927}
1928
1929// Test that a POST without any post data works.
1930TEST_P(SpdyNetworkTransactionTest, NullPost) {
1931  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
1932  // Setup the request
1933  HttpRequestInfo request;
1934  request.method = "POST";
1935  request.url = GURL(kRequestUrl);
1936  // Create an empty UploadData.
1937  request.upload_data_stream = NULL;
1938
1939  // When request.upload_data_stream is NULL for post, content-length is
1940  // expected to be 0.
1941  scoped_ptr<SpdyHeaderBlock> req_block(
1942      spdy_util_.ConstructPostHeaderBlock(kRequestUrl, 0));
1943  scoped_ptr<SpdyFrame> req(
1944      spdy_util_.ConstructSpdySyn(1, *req_block, LOWEST, false, true));
1945
1946  MockWrite writes[] = {
1947    CreateMockWrite(*req),
1948  };
1949
1950  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1951  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1952  MockRead reads[] = {
1953    CreateMockRead(*resp),
1954    CreateMockRead(*body),
1955    MockRead(ASYNC, 0, 0)  // EOF
1956  };
1957
1958  DelayedSocketData data(1, reads, arraysize(reads),
1959                         writes, arraysize(writes));
1960
1961  NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1962                                     BoundNetLog(), GetParam(), NULL);
1963  helper.RunToCompletion(&data);
1964  TransactionHelperResult out = helper.output();
1965  EXPECT_EQ(OK, out.rv);
1966  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1967  EXPECT_EQ("hello!", out.response_data);
1968}
1969
1970// Test that a simple POST works.
1971TEST_P(SpdyNetworkTransactionTest, EmptyPost) {
1972  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
1973  // Create an empty UploadDataStream.
1974  ScopedVector<UploadElementReader> element_readers;
1975  UploadDataStream stream(element_readers.Pass(), 0);
1976
1977  // Setup the request
1978  HttpRequestInfo request;
1979  request.method = "POST";
1980  request.url = GURL(kRequestUrl);
1981  request.upload_data_stream = &stream;
1982
1983  const uint64 kContentLength = 0;
1984
1985  scoped_ptr<SpdyHeaderBlock> req_block(
1986      spdy_util_.ConstructPostHeaderBlock(kRequestUrl, kContentLength));
1987  scoped_ptr<SpdyFrame> req(
1988      spdy_util_.ConstructSpdySyn(1, *req_block, LOWEST, false, true));
1989
1990  MockWrite writes[] = {
1991    CreateMockWrite(*req),
1992  };
1993
1994  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1995  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1996  MockRead reads[] = {
1997    CreateMockRead(*resp),
1998    CreateMockRead(*body),
1999    MockRead(ASYNC, 0, 0)  // EOF
2000  };
2001
2002  DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
2003
2004  NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
2005                                     BoundNetLog(), GetParam(), NULL);
2006  helper.RunToCompletion(&data);
2007  TransactionHelperResult out = helper.output();
2008  EXPECT_EQ(OK, out.rv);
2009  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
2010  EXPECT_EQ("hello!", out.response_data);
2011}
2012
2013// While we're doing a post, the server sends the reply before upload completes.
2014TEST_P(SpdyNetworkTransactionTest, ResponseBeforePostCompletes) {
2015  scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
2016  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2017  MockWrite writes[] = {
2018    CreateMockWrite(*req, 0),
2019    CreateMockWrite(*body, 3),
2020  };
2021  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
2022  MockRead reads[] = {
2023    CreateMockRead(*resp, 1),
2024    CreateMockRead(*body, 2),
2025    MockRead(ASYNC, 0, 4)  // EOF
2026  };
2027
2028  // Write the request headers, and read the complete response
2029  // while still waiting for chunked request data.
2030  DeterministicSocketData data(reads, arraysize(reads),
2031                               writes, arraysize(writes));
2032  NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
2033                                     DEFAULT_PRIORITY,
2034                                     BoundNetLog(), GetParam(), NULL);
2035  helper.SetDeterministic();
2036  helper.RunPreTestSetup();
2037  helper.AddDeterministicData(&data);
2038
2039  ASSERT_TRUE(helper.StartDefaultTest());
2040
2041  // Process the request headers, SYN_REPLY, and response body.
2042  // The request body is still in flight.
2043  data.RunFor(3);
2044
2045  const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
2046  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2047
2048  // Finish sending the request body.
2049  helper.request().upload_data_stream->AppendChunk(
2050      kUploadData, kUploadDataSize, true);
2051  data.RunFor(2);
2052
2053  std::string response_body;
2054  EXPECT_EQ(OK, ReadTransaction(helper.trans(), &response_body));
2055  EXPECT_EQ(kUploadData, response_body);
2056  helper.VerifyDataConsumed();
2057}
2058
2059// The client upon cancellation tries to send a RST_STREAM frame. The mock
2060// socket causes the TCP write to return zero. This test checks that the client
2061// tries to queue up the RST_STREAM frame again.
2062TEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
2063  scoped_ptr<SpdyFrame> req(
2064      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2065  scoped_ptr<SpdyFrame> rst(
2066      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2067  MockWrite writes[] = {
2068    CreateMockWrite(*req.get(), 0, SYNCHRONOUS),
2069    MockWrite(SYNCHRONOUS, 0, 0, 2),
2070    CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
2071  };
2072
2073  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2074  MockRead reads[] = {
2075    CreateMockRead(*resp.get(), 1, ASYNC),
2076    MockRead(ASYNC, 0, 0, 4)  // EOF
2077  };
2078
2079  DeterministicSocketData data(reads, arraysize(reads),
2080                               writes, arraysize(writes));
2081  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2082                                     BoundNetLog(), GetParam(), NULL);
2083  helper.SetDeterministic();
2084  helper.RunPreTestSetup();
2085  helper.AddDeterministicData(&data);
2086  HttpNetworkTransaction* trans = helper.trans();
2087
2088  TestCompletionCallback callback;
2089  int rv = trans->Start(
2090      &CreateGetRequest(), callback.callback(), BoundNetLog());
2091  EXPECT_EQ(ERR_IO_PENDING, rv);
2092
2093  data.SetStop(2);
2094  data.Run();
2095  helper.ResetTrans();
2096  data.SetStop(20);
2097  data.Run();
2098
2099  helper.VerifyDataConsumed();
2100}
2101
2102// Test that the transaction doesn't crash when we don't have a reply.
2103TEST_P(SpdyNetworkTransactionTest, ResponseWithoutSynReply) {
2104  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2105  MockRead reads[] = {
2106    CreateMockRead(*body),
2107    MockRead(ASYNC, 0, 0)  // EOF
2108  };
2109
2110  DelayedSocketData data(1, reads, arraysize(reads), NULL, 0);
2111  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2112                                     BoundNetLog(), GetParam(), NULL);
2113  helper.RunToCompletion(&data);
2114  TransactionHelperResult out = helper.output();
2115  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
2116}
2117
2118// Test that the transaction doesn't crash when we get two replies on the same
2119// stream ID. See http://crbug.com/45639.
2120TEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
2121  scoped_ptr<SpdyFrame> req(
2122      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2123  scoped_ptr<SpdyFrame> rst(
2124      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
2125  MockWrite writes[] = {
2126    CreateMockWrite(*req),
2127    CreateMockWrite(*rst),
2128  };
2129
2130  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2131  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2132  MockRead reads[] = {
2133    CreateMockRead(*resp),
2134    CreateMockRead(*resp),
2135    CreateMockRead(*body),
2136    MockRead(ASYNC, 0, 0)  // EOF
2137  };
2138
2139  DelayedSocketData data(1, reads, arraysize(reads),
2140                         writes, arraysize(writes));
2141
2142  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2143                                     BoundNetLog(), GetParam(), NULL);
2144  helper.RunPreTestSetup();
2145  helper.AddData(&data);
2146
2147  HttpNetworkTransaction* trans = helper.trans();
2148
2149  TestCompletionCallback callback;
2150  int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2151  EXPECT_EQ(ERR_IO_PENDING, rv);
2152  rv = callback.WaitForResult();
2153  EXPECT_EQ(OK, rv);
2154
2155  const HttpResponseInfo* response = trans->GetResponseInfo();
2156  ASSERT_TRUE(response != NULL);
2157  EXPECT_TRUE(response->headers.get() != NULL);
2158  EXPECT_TRUE(response->was_fetched_via_spdy);
2159  std::string response_data;
2160  rv = ReadTransaction(trans, &response_data);
2161  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
2162
2163  helper.VerifyDataConsumed();
2164}
2165
2166TEST_P(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) {
2167  // Construct the request.
2168  scoped_ptr<SpdyFrame> req(
2169      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2170  scoped_ptr<SpdyFrame> rst(
2171      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
2172  MockWrite writes[] = {
2173    CreateMockWrite(*req),
2174    CreateMockWrite(*rst),
2175  };
2176
2177  const char* const headers[] = {
2178    "transfer-encoding", "chunked"
2179  };
2180  scoped_ptr<SpdyFrame> resp(
2181      spdy_util_.ConstructSpdyGetSynReply(headers, 1, 1));
2182  scoped_ptr<SpdyFrame> body(
2183      spdy_util_.ConstructSpdyBodyFrame(1, true));
2184  MockRead reads[] = {
2185    CreateMockRead(*resp),
2186    CreateMockRead(*body),
2187    MockRead(ASYNC, 0, 0)  // EOF
2188  };
2189
2190  DelayedSocketData data(1, reads, arraysize(reads),
2191                         writes, arraysize(writes));
2192  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2193                                     BoundNetLog(), GetParam(), NULL);
2194  helper.RunToCompletion(&data);
2195  TransactionHelperResult out = helper.output();
2196  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
2197
2198  helper.session()->spdy_session_pool()->CloseAllSessions();
2199  helper.VerifyDataConsumed();
2200}
2201
2202TEST_P(SpdyNetworkTransactionTest, ResetPushWithTransferEncoding) {
2203  // Construct the request.
2204  scoped_ptr<SpdyFrame> req(
2205      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2206  scoped_ptr<SpdyFrame> rst(
2207      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
2208  MockWrite writes[] = {
2209    CreateMockWrite(*req),
2210    CreateMockWrite(*rst),
2211  };
2212
2213  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2214  const char* const headers[] = {
2215    "transfer-encoding", "chunked"
2216  };
2217  scoped_ptr<SpdyFrame> push(
2218      spdy_util_.ConstructSpdyPush(headers, arraysize(headers) / 2,
2219                                   2, 1, "http://www.google.com/1"));
2220  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2221  MockRead reads[] = {
2222    CreateMockRead(*resp),
2223    CreateMockRead(*push),
2224    CreateMockRead(*body),
2225    MockRead(ASYNC, 0, 0)  // EOF
2226  };
2227
2228  DelayedSocketData data(1, reads, arraysize(reads),
2229                         writes, arraysize(writes));
2230  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2231                                     BoundNetLog(), GetParam(), NULL);
2232  helper.RunToCompletion(&data);
2233  TransactionHelperResult out = helper.output();
2234  EXPECT_EQ(OK, out.rv);
2235  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
2236  EXPECT_EQ("hello!", out.response_data);
2237
2238  helper.session()->spdy_session_pool()->CloseAllSessions();
2239  helper.VerifyDataConsumed();
2240}
2241
2242TEST_P(SpdyNetworkTransactionTest, CancelledTransaction) {
2243  // Construct the request.
2244  scoped_ptr<SpdyFrame> req(
2245      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2246  MockWrite writes[] = {
2247    CreateMockWrite(*req),
2248  };
2249
2250  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2251  MockRead reads[] = {
2252    CreateMockRead(*resp),
2253    // This following read isn't used by the test, except during the
2254    // RunUntilIdle() call at the end since the SpdySession survives the
2255    // HttpNetworkTransaction and still tries to continue Read()'ing.  Any
2256    // MockRead will do here.
2257    MockRead(ASYNC, 0, 0)  // EOF
2258  };
2259
2260  StaticSocketDataProvider data(reads, arraysize(reads),
2261                                writes, arraysize(writes));
2262
2263  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2264                                     BoundNetLog(), GetParam(), NULL);
2265  helper.RunPreTestSetup();
2266  helper.AddData(&data);
2267  HttpNetworkTransaction* trans = helper.trans();
2268
2269  TestCompletionCallback callback;
2270  int rv = trans->Start(
2271      &CreateGetRequest(), callback.callback(), BoundNetLog());
2272  EXPECT_EQ(ERR_IO_PENDING, rv);
2273  helper.ResetTrans();  // Cancel the transaction.
2274
2275  // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
2276  // MockClientSocketFactory) are still alive.
2277  base::RunLoop().RunUntilIdle();
2278  helper.VerifyDataNotConsumed();
2279}
2280
2281// Verify that the client sends a Rst Frame upon cancelling the stream.
2282TEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
2283  scoped_ptr<SpdyFrame> req(
2284      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2285  scoped_ptr<SpdyFrame> rst(
2286      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2287  MockWrite writes[] = {
2288    CreateMockWrite(*req, 0, SYNCHRONOUS),
2289    CreateMockWrite(*rst, 2, SYNCHRONOUS),
2290  };
2291
2292  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2293  MockRead reads[] = {
2294    CreateMockRead(*resp, 1, ASYNC),
2295    MockRead(ASYNC, 0, 0, 3)  // EOF
2296  };
2297
2298  DeterministicSocketData data(reads, arraysize(reads),
2299                               writes, arraysize(writes));
2300
2301  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2302                                     BoundNetLog(),
2303                                     GetParam(), NULL);
2304  helper.SetDeterministic();
2305  helper.RunPreTestSetup();
2306  helper.AddDeterministicData(&data);
2307  HttpNetworkTransaction* trans = helper.trans();
2308
2309  TestCompletionCallback callback;
2310
2311  int rv = trans->Start(
2312      &CreateGetRequest(), callback.callback(), BoundNetLog());
2313  EXPECT_EQ(ERR_IO_PENDING, rv);
2314
2315  data.SetStop(2);
2316  data.Run();
2317  helper.ResetTrans();
2318  data.SetStop(20);
2319  data.Run();
2320
2321  helper.VerifyDataConsumed();
2322}
2323
2324// Verify that the client can correctly deal with the user callback attempting
2325// to start another transaction on a session that is closing down. See
2326// http://crbug.com/47455
2327TEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
2328  scoped_ptr<SpdyFrame> req(
2329      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2330  MockWrite writes[] = { CreateMockWrite(*req) };
2331  MockWrite writes2[] = { CreateMockWrite(*req) };
2332
2333  // The indicated length of this frame is longer than its actual length. When
2334  // the session receives an empty frame after this one, it shuts down the
2335  // session, and calls the read callback with the incomplete data.
2336  const uint8 kGetBodyFrame2[] = {
2337    0x00, 0x00, 0x00, 0x01,
2338    0x01, 0x00, 0x00, 0x07,
2339    'h', 'e', 'l', 'l', 'o', '!',
2340  };
2341
2342  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2343  MockRead reads[] = {
2344    CreateMockRead(*resp, 2),
2345    MockRead(ASYNC, ERR_IO_PENDING, 3),  // Force a pause
2346    MockRead(ASYNC, reinterpret_cast<const char*>(kGetBodyFrame2),
2347             arraysize(kGetBodyFrame2), 4),
2348    MockRead(ASYNC, ERR_IO_PENDING, 5),  // Force a pause
2349    MockRead(ASYNC, 0, 0, 6),  // EOF
2350  };
2351  MockRead reads2[] = {
2352    CreateMockRead(*resp, 2),
2353    MockRead(ASYNC, 0, 0, 3),  // EOF
2354  };
2355
2356  OrderedSocketData data(reads, arraysize(reads),
2357                         writes, arraysize(writes));
2358  DelayedSocketData data2(1, reads2, arraysize(reads2),
2359                          writes2, arraysize(writes2));
2360
2361  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2362                                     BoundNetLog(), GetParam(), NULL);
2363  helper.RunPreTestSetup();
2364  helper.AddData(&data);
2365  helper.AddData(&data2);
2366  HttpNetworkTransaction* trans = helper.trans();
2367
2368  // Start the transaction with basic parameters.
2369  TestCompletionCallback callback;
2370  int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2371  EXPECT_EQ(ERR_IO_PENDING, rv);
2372  rv = callback.WaitForResult();
2373
2374  const int kSize = 3000;
2375  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
2376  rv = trans->Read(
2377      buf.get(),
2378      kSize,
2379      base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback,
2380                 helper.session()));
2381  // This forces an err_IO_pending, which sets the callback.
2382  data.CompleteRead();
2383  // This finishes the read.
2384  data.CompleteRead();
2385  helper.VerifyDataConsumed();
2386}
2387
2388// Verify that the client can correctly deal with the user callback deleting the
2389// transaction. Failures will usually be valgrind errors. See
2390// http://crbug.com/46925
2391TEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
2392  scoped_ptr<SpdyFrame> req(
2393      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2394  MockWrite writes[] = { CreateMockWrite(*req) };
2395
2396  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2397  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2398  MockRead reads[] = {
2399    CreateMockRead(*resp.get(), 2),
2400    MockRead(ASYNC, ERR_IO_PENDING, 3),  // Force a pause
2401    CreateMockRead(*body.get(), 4),
2402    MockRead(ASYNC, 0, 0, 5),  // EOF
2403  };
2404
2405  OrderedSocketData data(reads, arraysize(reads),
2406                         writes, arraysize(writes));
2407
2408  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2409                                     BoundNetLog(), GetParam(), NULL);
2410  helper.RunPreTestSetup();
2411  helper.AddData(&data);
2412  HttpNetworkTransaction* trans = helper.trans();
2413
2414  // Start the transaction with basic parameters.
2415  TestCompletionCallback callback;
2416  int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2417  EXPECT_EQ(ERR_IO_PENDING, rv);
2418  rv = callback.WaitForResult();
2419
2420  // Setup a user callback which will delete the session, and clear out the
2421  // memory holding the stream object. Note that the callback deletes trans.
2422  const int kSize = 3000;
2423  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
2424  rv = trans->Read(
2425      buf.get(),
2426      kSize,
2427      base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback,
2428                 base::Unretained(&helper)));
2429  ASSERT_EQ(ERR_IO_PENDING, rv);
2430  data.CompleteRead();
2431
2432  // Finish running rest of tasks.
2433  base::RunLoop().RunUntilIdle();
2434  helper.VerifyDataConsumed();
2435}
2436
2437// Send a spdy request to www.google.com that gets redirected to www.foo.com.
2438TEST_P(SpdyNetworkTransactionTest, RedirectGetRequest) {
2439  scoped_ptr<SpdyHeaderBlock> headers(
2440      spdy_util_.ConstructGetHeaderBlock("http://www.google.com/"));
2441  (*headers)["user-agent"] = "";
2442  (*headers)["accept-encoding"] = "gzip, deflate";
2443  scoped_ptr<SpdyHeaderBlock> headers2(
2444      spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2445  (*headers2)["user-agent"] = "";
2446  (*headers2)["accept-encoding"] = "gzip, deflate";
2447
2448  // Setup writes/reads to www.google.com
2449  scoped_ptr<SpdyFrame> req(
2450      spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
2451  scoped_ptr<SpdyFrame> req2(
2452      spdy_util_.ConstructSpdySyn(1, *headers2, LOWEST, false, true));
2453  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReplyRedirect(1));
2454  MockWrite writes[] = {
2455    CreateMockWrite(*req, 1),
2456  };
2457  MockRead reads[] = {
2458    CreateMockRead(*resp, 2),
2459    MockRead(ASYNC, 0, 0, 3)  // EOF
2460  };
2461
2462  // Setup writes/reads to www.foo.com
2463  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2464  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
2465  MockWrite writes2[] = {
2466    CreateMockWrite(*req2, 1),
2467  };
2468  MockRead reads2[] = {
2469    CreateMockRead(*resp2, 2),
2470    CreateMockRead(*body2, 3),
2471    MockRead(ASYNC, 0, 0, 4)  // EOF
2472  };
2473  OrderedSocketData data(reads, arraysize(reads),
2474                         writes, arraysize(writes));
2475  OrderedSocketData data2(reads2, arraysize(reads2),
2476                          writes2, arraysize(writes2));
2477
2478  // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2479  TestDelegate d;
2480  {
2481    SpdyURLRequestContext spdy_url_request_context(
2482        GetParam().protocol,
2483        false  /* force_spdy_over_ssl*/,
2484        true  /* force_spdy_always */);
2485    scoped_ptr<URLRequest> r(
2486        spdy_url_request_context.CreateRequest(GURL("http://www.google.com/"),
2487                                               DEFAULT_PRIORITY,
2488                                               &d,
2489                                               NULL));
2490    spdy_url_request_context.socket_factory().
2491        AddSocketDataProvider(&data);
2492    spdy_url_request_context.socket_factory().
2493        AddSocketDataProvider(&data2);
2494
2495    d.set_quit_on_redirect(true);
2496    r->Start();
2497    base::RunLoop().Run();
2498
2499    EXPECT_EQ(1, d.received_redirect_count());
2500
2501    r->FollowDeferredRedirect();
2502    base::RunLoop().Run();
2503    EXPECT_EQ(1, d.response_started_count());
2504    EXPECT_FALSE(d.received_data_before_response());
2505    EXPECT_EQ(net::URLRequestStatus::SUCCESS, r->status().status());
2506    std::string contents("hello!");
2507    EXPECT_EQ(contents, d.data_received());
2508  }
2509  EXPECT_TRUE(data.at_read_eof());
2510  EXPECT_TRUE(data.at_write_eof());
2511  EXPECT_TRUE(data2.at_read_eof());
2512  EXPECT_TRUE(data2.at_write_eof());
2513}
2514
2515// Send a spdy request to www.google.com. Get a pushed stream that redirects to
2516// www.foo.com.
2517TEST_P(SpdyNetworkTransactionTest, RedirectServerPush) {
2518  scoped_ptr<SpdyHeaderBlock> headers(
2519      spdy_util_.ConstructGetHeaderBlock("http://www.google.com/"));
2520  (*headers)["user-agent"] = "";
2521  (*headers)["accept-encoding"] = "gzip, deflate";
2522
2523  // Setup writes/reads to www.google.com
2524  scoped_ptr<SpdyFrame> req(
2525      spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
2526  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2527  scoped_ptr<SpdyFrame> rep(
2528      spdy_util_.ConstructSpdyPush(NULL,
2529                        0,
2530                        2,
2531                        1,
2532                        "http://www.google.com/foo.dat",
2533                        "301 Moved Permanently",
2534                        "http://www.foo.com/index.php"));
2535  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2536  scoped_ptr<SpdyFrame> rst(
2537      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
2538  MockWrite writes[] = {
2539    CreateMockWrite(*req, 1),
2540    CreateMockWrite(*rst, 6),
2541  };
2542  MockRead reads[] = {
2543    CreateMockRead(*resp, 2),
2544    CreateMockRead(*rep, 3),
2545    CreateMockRead(*body, 4),
2546    MockRead(ASYNC, ERR_IO_PENDING, 5),  // Force a pause
2547    MockRead(ASYNC, 0, 0, 7)  // EOF
2548  };
2549
2550  // Setup writes/reads to www.foo.com
2551  scoped_ptr<SpdyHeaderBlock> headers2(
2552      spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2553  (*headers2)["user-agent"] = "";
2554  (*headers2)["accept-encoding"] = "gzip, deflate";
2555  scoped_ptr<SpdyFrame> req2(
2556      spdy_util_.ConstructSpdySyn(1, *headers2, LOWEST, false, true));
2557  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2558  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
2559  MockWrite writes2[] = {
2560    CreateMockWrite(*req2, 1),
2561  };
2562  MockRead reads2[] = {
2563    CreateMockRead(*resp2, 2),
2564    CreateMockRead(*body2, 3),
2565    MockRead(ASYNC, 0, 0, 5)  // EOF
2566  };
2567  OrderedSocketData data(reads, arraysize(reads),
2568                         writes, arraysize(writes));
2569  OrderedSocketData data2(reads2, arraysize(reads2),
2570                          writes2, arraysize(writes2));
2571
2572  // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2573  TestDelegate d;
2574  TestDelegate d2;
2575  SpdyURLRequestContext spdy_url_request_context(
2576      GetParam().protocol,
2577      false  /* force_spdy_over_ssl*/,
2578      true  /* force_spdy_always */);
2579  {
2580    scoped_ptr<URLRequest> r(
2581        spdy_url_request_context.CreateRequest(GURL("http://www.google.com/"),
2582                                               DEFAULT_PRIORITY,
2583                                               &d,
2584                                               NULL));
2585    spdy_url_request_context.socket_factory().
2586        AddSocketDataProvider(&data);
2587
2588    r->Start();
2589    base::RunLoop().Run();
2590
2591    EXPECT_EQ(0, d.received_redirect_count());
2592    std::string contents("hello!");
2593    EXPECT_EQ(contents, d.data_received());
2594
2595    scoped_ptr<URLRequest> r2(
2596        spdy_url_request_context.CreateRequest(
2597            GURL("http://www.google.com/foo.dat"),
2598            DEFAULT_PRIORITY,
2599            &d2,
2600            NULL));
2601    spdy_url_request_context.socket_factory().
2602        AddSocketDataProvider(&data2);
2603
2604    d2.set_quit_on_redirect(true);
2605    r2->Start();
2606    base::RunLoop().Run();
2607    EXPECT_EQ(1, d2.received_redirect_count());
2608
2609    r2->FollowDeferredRedirect();
2610    base::RunLoop().Run();
2611    EXPECT_EQ(1, d2.response_started_count());
2612    EXPECT_FALSE(d2.received_data_before_response());
2613    EXPECT_EQ(net::URLRequestStatus::SUCCESS, r2->status().status());
2614    std::string contents2("hello!");
2615    EXPECT_EQ(contents2, d2.data_received());
2616  }
2617  data.CompleteRead();
2618  data2.CompleteRead();
2619  EXPECT_TRUE(data.at_read_eof());
2620  EXPECT_TRUE(data.at_write_eof());
2621  EXPECT_TRUE(data2.at_read_eof());
2622  EXPECT_TRUE(data2.at_write_eof());
2623}
2624
2625TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
2626  scoped_ptr<SpdyFrame> stream1_syn(
2627      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2628  scoped_ptr<SpdyFrame> stream1_body(
2629      spdy_util_.ConstructSpdyBodyFrame(1, true));
2630  MockWrite writes[] = {
2631    CreateMockWrite(*stream1_syn, 1),
2632  };
2633
2634  scoped_ptr<SpdyFrame>
2635      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2636  scoped_ptr<SpdyFrame>
2637      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2638                                    0,
2639                                    2,
2640                                    1,
2641                                    "http://www.google.com/foo.dat"));
2642  const char kPushedData[] = "pushed";
2643  scoped_ptr<SpdyFrame> stream2_body(
2644      spdy_util_.ConstructSpdyBodyFrame(
2645          2, kPushedData, strlen(kPushedData), true));
2646  MockRead reads[] = {
2647    CreateMockRead(*stream1_reply, 2),
2648    CreateMockRead(*stream2_syn, 3),
2649    CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2650    CreateMockRead(*stream2_body, 5),
2651    MockRead(ASYNC, ERR_IO_PENDING, 6),  // Force a pause
2652  };
2653
2654  HttpResponseInfo response;
2655  HttpResponseInfo response2;
2656  std::string expected_push_result("pushed");
2657  OrderedSocketData data(reads, arraysize(reads),
2658                         writes, arraysize(writes));
2659  RunServerPushTest(&data,
2660                    &response,
2661                    &response2,
2662                    expected_push_result);
2663
2664  // Verify the SYN_REPLY.
2665  EXPECT_TRUE(response.headers.get() != NULL);
2666  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2667
2668  // Verify the pushed stream.
2669  EXPECT_TRUE(response2.headers.get() != NULL);
2670  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2671}
2672
2673TEST_P(SpdyNetworkTransactionTest, ServerPushBeforeSynReply) {
2674  scoped_ptr<SpdyFrame> stream1_syn(
2675      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2676  scoped_ptr<SpdyFrame> stream1_body(
2677      spdy_util_.ConstructSpdyBodyFrame(1, true));
2678  MockWrite writes[] = {
2679    CreateMockWrite(*stream1_syn, 1),
2680  };
2681
2682  scoped_ptr<SpdyFrame>
2683      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2684  scoped_ptr<SpdyFrame>
2685      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2686                                    0,
2687                                    2,
2688                                    1,
2689                                    "http://www.google.com/foo.dat"));
2690  const char kPushedData[] = "pushed";
2691  scoped_ptr<SpdyFrame> stream2_body(
2692      spdy_util_.ConstructSpdyBodyFrame(
2693          2, kPushedData, strlen(kPushedData), true));
2694  MockRead reads[] = {
2695    CreateMockRead(*stream2_syn, 2),
2696    CreateMockRead(*stream1_reply, 3),
2697    CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2698    CreateMockRead(*stream2_body, 5),
2699    MockRead(ASYNC, ERR_IO_PENDING, 6),  // Force a pause
2700  };
2701
2702  HttpResponseInfo response;
2703  HttpResponseInfo response2;
2704  std::string expected_push_result("pushed");
2705  OrderedSocketData data(reads, arraysize(reads),
2706                         writes, arraysize(writes));
2707  RunServerPushTest(&data,
2708                    &response,
2709                    &response2,
2710                    expected_push_result);
2711
2712  // Verify the SYN_REPLY.
2713  EXPECT_TRUE(response.headers.get() != NULL);
2714  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2715
2716  // Verify the pushed stream.
2717  EXPECT_TRUE(response2.headers.get() != NULL);
2718  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2719}
2720
2721TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
2722  scoped_ptr<SpdyFrame> stream1_syn(
2723      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2724  MockWrite writes[] = { CreateMockWrite(*stream1_syn, 1), };
2725
2726  scoped_ptr<SpdyFrame>
2727      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2728  scoped_ptr<SpdyFrame>
2729      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2730                                    0,
2731                                    2,
2732                                    1,
2733                                    "http://www.google.com/foo.dat"));
2734  const char kPushedData[] = "pushed";
2735  scoped_ptr<SpdyFrame> stream2_body(
2736      spdy_util_.ConstructSpdyBodyFrame(
2737          2, kPushedData, strlen(kPushedData), true));
2738  scoped_ptr<SpdyFrame>
2739      stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2740  MockRead reads[] = {
2741    CreateMockRead(*stream1_reply, 2),
2742    CreateMockRead(*stream2_syn, 3),
2743    CreateMockRead(*stream2_body, 4),
2744    CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
2745    MockRead(ASYNC, ERR_IO_PENDING, 6),  // Force a pause
2746  };
2747
2748  HttpResponseInfo response;
2749  HttpResponseInfo response2;
2750  std::string expected_push_result("pushed");
2751  OrderedSocketData data(reads, arraysize(reads),
2752                         writes, arraysize(writes));
2753  RunServerPushTest(&data,
2754                    &response,
2755                    &response2,
2756                    expected_push_result);
2757
2758  // Verify the SYN_REPLY.
2759  EXPECT_TRUE(response.headers.get() != NULL);
2760  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2761
2762  // Verify the pushed stream.
2763  EXPECT_TRUE(response2.headers.get() != NULL);
2764  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2765}
2766
2767TEST_P(SpdyNetworkTransactionTest, ServerPushServerAborted) {
2768  scoped_ptr<SpdyFrame> stream1_syn(
2769      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2770  scoped_ptr<SpdyFrame> stream1_body(
2771      spdy_util_.ConstructSpdyBodyFrame(1, true));
2772  MockWrite writes[] = {
2773    CreateMockWrite(*stream1_syn, 1),
2774  };
2775
2776  scoped_ptr<SpdyFrame>
2777      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2778  scoped_ptr<SpdyFrame>
2779      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2780                                    0,
2781                                    2,
2782                                    1,
2783                                    "http://www.google.com/foo.dat"));
2784  scoped_ptr<SpdyFrame> stream2_rst(
2785      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
2786  MockRead reads[] = {
2787    CreateMockRead(*stream1_reply, 2),
2788    CreateMockRead(*stream2_syn, 3),
2789    CreateMockRead(*stream2_rst, 4),
2790    CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
2791    MockRead(ASYNC, ERR_IO_PENDING, 6),  // Force a pause
2792  };
2793
2794  OrderedSocketData data(reads, arraysize(reads),
2795                         writes, arraysize(writes));
2796  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2797                                     BoundNetLog(), GetParam(), NULL);
2798
2799  helper.RunPreTestSetup();
2800  helper.AddData(&data);
2801
2802  HttpNetworkTransaction* trans = helper.trans();
2803
2804  // Start the transaction with basic parameters.
2805  TestCompletionCallback callback;
2806  int rv = trans->Start(
2807      &CreateGetRequest(), callback.callback(), BoundNetLog());
2808  EXPECT_EQ(ERR_IO_PENDING, rv);
2809  rv = callback.WaitForResult();
2810  EXPECT_EQ(OK, rv);
2811
2812  // Verify that we consumed all test data.
2813  EXPECT_TRUE(data.at_read_eof()) << "Read count: "
2814                                   << data.read_count()
2815                                   << " Read index: "
2816                                   << data.read_index();
2817  EXPECT_TRUE(data.at_write_eof()) << "Write count: "
2818                                    << data.write_count()
2819                                    << " Write index: "
2820                                    << data.write_index();
2821
2822  // Verify the SYN_REPLY.
2823  HttpResponseInfo response = *trans->GetResponseInfo();
2824  EXPECT_TRUE(response.headers.get() != NULL);
2825  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2826}
2827
2828// Verify that we don't leak streams and that we properly send a reset
2829// if the server pushes the same stream twice.
2830TEST_P(SpdyNetworkTransactionTest, ServerPushDuplicate) {
2831  scoped_ptr<SpdyFrame> stream1_syn(
2832      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2833  scoped_ptr<SpdyFrame> stream1_body(
2834      spdy_util_.ConstructSpdyBodyFrame(1, true));
2835  scoped_ptr<SpdyFrame> stream3_rst(
2836      spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR));
2837  MockWrite writes[] = {
2838    CreateMockWrite(*stream1_syn, 1),
2839    CreateMockWrite(*stream3_rst, 5),
2840  };
2841
2842  scoped_ptr<SpdyFrame>
2843      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2844  scoped_ptr<SpdyFrame>
2845      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2846                                    0,
2847                                    2,
2848                                    1,
2849                                    "http://www.google.com/foo.dat"));
2850  const char kPushedData[] = "pushed";
2851  scoped_ptr<SpdyFrame> stream2_body(
2852      spdy_util_.ConstructSpdyBodyFrame(
2853          2, kPushedData, strlen(kPushedData), true));
2854  scoped_ptr<SpdyFrame>
2855      stream3_syn(spdy_util_.ConstructSpdyPush(NULL,
2856                                    0,
2857                                    4,
2858                                    1,
2859                                    "http://www.google.com/foo.dat"));
2860  MockRead reads[] = {
2861    CreateMockRead(*stream1_reply, 2),
2862    CreateMockRead(*stream2_syn, 3),
2863    CreateMockRead(*stream3_syn, 4),
2864    CreateMockRead(*stream1_body, 6, SYNCHRONOUS),
2865    CreateMockRead(*stream2_body, 7),
2866    MockRead(ASYNC, ERR_IO_PENDING, 8),  // Force a pause
2867  };
2868
2869  HttpResponseInfo response;
2870  HttpResponseInfo response2;
2871  std::string expected_push_result("pushed");
2872  OrderedSocketData data(reads, arraysize(reads),
2873                         writes, arraysize(writes));
2874  RunServerPushTest(&data,
2875                    &response,
2876                    &response2,
2877                    expected_push_result);
2878
2879  // Verify the SYN_REPLY.
2880  EXPECT_TRUE(response.headers.get() != NULL);
2881  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2882
2883  // Verify the pushed stream.
2884  EXPECT_TRUE(response2.headers.get() != NULL);
2885  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2886}
2887
2888TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
2889  scoped_ptr<SpdyFrame> stream1_syn(
2890      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2891  scoped_ptr<SpdyFrame> stream1_body(
2892      spdy_util_.ConstructSpdyBodyFrame(1, true));
2893  MockWrite writes[] = {
2894    CreateMockWrite(*stream1_syn, 1),
2895  };
2896
2897  scoped_ptr<SpdyFrame>
2898      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2899  scoped_ptr<SpdyFrame>
2900      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2901                                    0,
2902                                    2,
2903                                    1,
2904                                    "http://www.google.com/foo.dat"));
2905  static const char kPushedData[] = "pushed my darling hello my baby";
2906  scoped_ptr<SpdyFrame> stream2_body_base(
2907      spdy_util_.ConstructSpdyBodyFrame(
2908          2, kPushedData, strlen(kPushedData), true));
2909  const size_t kChunkSize = strlen(kPushedData) / 4;
2910  scoped_ptr<SpdyFrame> stream2_body1(
2911      new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
2912  scoped_ptr<SpdyFrame> stream2_body2(
2913      new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
2914  scoped_ptr<SpdyFrame> stream2_body3(
2915      new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
2916                    kChunkSize, false));
2917  scoped_ptr<SpdyFrame> stream2_body4(
2918      new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
2919                    stream2_body_base->size() - 3 * kChunkSize, false));
2920  MockRead reads[] = {
2921    CreateMockRead(*stream1_reply, 2),
2922    CreateMockRead(*stream2_syn, 3),
2923    CreateMockRead(*stream2_body1, 4),
2924    CreateMockRead(*stream2_body2, 5),
2925    CreateMockRead(*stream2_body3, 6),
2926    CreateMockRead(*stream2_body4, 7),
2927    CreateMockRead(*stream1_body, 8, SYNCHRONOUS),
2928    MockRead(ASYNC, ERR_IO_PENDING, 9),  // Force a pause
2929  };
2930
2931  HttpResponseInfo response;
2932  HttpResponseInfo response2;
2933  std::string expected_push_result("pushed my darling hello my baby");
2934  OrderedSocketData data(reads, arraysize(reads),
2935                         writes, arraysize(writes));
2936  RunServerPushTest(&data, &response, &response2, kPushedData);
2937
2938  // Verify the SYN_REPLY.
2939  EXPECT_TRUE(response.headers.get() != NULL);
2940  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2941
2942  // Verify the pushed stream.
2943  EXPECT_TRUE(response2.headers.get() != NULL);
2944  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2945}
2946
2947TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
2948  scoped_ptr<SpdyFrame> stream1_syn(
2949      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2950  scoped_ptr<SpdyFrame> stream1_body(
2951      spdy_util_.ConstructSpdyBodyFrame(1, true));
2952  MockWrite writes[] = {
2953    CreateMockWrite(*stream1_syn, 1),
2954  };
2955
2956  scoped_ptr<SpdyFrame>
2957      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2958  scoped_ptr<SpdyFrame>
2959      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2960                                    0,
2961                                    2,
2962                                    1,
2963                                    "http://www.google.com/foo.dat"));
2964  static const char kPushedData[] = "pushed my darling hello my baby";
2965  scoped_ptr<SpdyFrame> stream2_body_base(
2966      spdy_util_.ConstructSpdyBodyFrame(
2967          2, kPushedData, strlen(kPushedData), true));
2968  const size_t kChunkSize = strlen(kPushedData) / 4;
2969  scoped_ptr<SpdyFrame> stream2_body1(
2970      new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
2971  scoped_ptr<SpdyFrame> stream2_body2(
2972      new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
2973  scoped_ptr<SpdyFrame> stream2_body3(
2974      new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
2975                    kChunkSize, false));
2976  scoped_ptr<SpdyFrame> stream2_body4(
2977      new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
2978                    stream2_body_base->size() - 3 * kChunkSize, false));
2979  MockRead reads[] = {
2980    CreateMockRead(*stream1_reply, 2),
2981    CreateMockRead(*stream2_syn, 3),
2982    CreateMockRead(*stream2_body1, 4),
2983    CreateMockRead(*stream2_body2, 5),
2984    MockRead(ASYNC, ERR_IO_PENDING, 6),  // Force a pause
2985    CreateMockRead(*stream2_body3, 7),
2986    CreateMockRead(*stream2_body4, 8),
2987    CreateMockRead(*stream1_body.get(), 9, SYNCHRONOUS),
2988    MockRead(ASYNC, ERR_IO_PENDING, 10)  // Force a pause.
2989  };
2990
2991  HttpResponseInfo response;
2992  HttpResponseInfo response2;
2993  OrderedSocketData data(reads, arraysize(reads),
2994                         writes, arraysize(writes));
2995  RunServerPushTest(&data, &response, &response2, kPushedData);
2996
2997  // Verify the SYN_REPLY.
2998  EXPECT_TRUE(response.headers.get() != NULL);
2999  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3000
3001  // Verify the pushed stream.
3002  EXPECT_TRUE(response2.headers.get() != NULL);
3003  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
3004}
3005
3006TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
3007  if (spdy_util_.spdy_version() == SPDY4) {
3008    // PUSH_PROMISE with stream id 0 is connection-level error.
3009    // TODO(baranovich): Test session going away.
3010    return;
3011  }
3012
3013  scoped_ptr<SpdyFrame> stream1_syn(
3014      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3015  scoped_ptr<SpdyFrame> stream1_body(
3016      spdy_util_.ConstructSpdyBodyFrame(1, true));
3017  scoped_ptr<SpdyFrame> stream2_rst(
3018      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
3019  MockWrite writes[] = {
3020    CreateMockWrite(*stream1_syn, 1),
3021    CreateMockWrite(*stream2_rst, 4),
3022  };
3023
3024  scoped_ptr<SpdyFrame>
3025      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3026  scoped_ptr<SpdyFrame>
3027      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
3028                                    0,
3029                                    2,
3030                                    0,
3031                                    "http://www.google.com/foo.dat"));
3032  MockRead reads[] = {
3033    CreateMockRead(*stream1_reply, 2),
3034    CreateMockRead(*stream2_syn, 3),
3035    CreateMockRead(*stream1_body, 4),
3036    MockRead(ASYNC, ERR_IO_PENDING, 5)  // Force a pause
3037  };
3038
3039  OrderedSocketData data(reads, arraysize(reads),
3040                         writes, arraysize(writes));
3041  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3042                                     BoundNetLog(), GetParam(), NULL);
3043
3044  helper.RunPreTestSetup();
3045  helper.AddData(&data);
3046
3047  HttpNetworkTransaction* trans = helper.trans();
3048
3049  // Start the transaction with basic parameters.
3050  TestCompletionCallback callback;
3051  int rv = trans->Start(
3052      &CreateGetRequest(), callback.callback(), BoundNetLog());
3053  EXPECT_EQ(ERR_IO_PENDING, rv);
3054  rv = callback.WaitForResult();
3055  EXPECT_EQ(OK, rv);
3056
3057  // Verify that we consumed all test data.
3058  EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3059                                   << data.read_count()
3060                                   << " Read index: "
3061                                   << data.read_index();
3062  EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3063                                    << data.write_count()
3064                                    << " Write index: "
3065                                    << data.write_index();
3066
3067  // Verify the SYN_REPLY.
3068  HttpResponseInfo response = *trans->GetResponseInfo();
3069  EXPECT_TRUE(response.headers.get() != NULL);
3070  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3071}
3072
3073TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
3074  scoped_ptr<SpdyFrame> stream1_syn(
3075      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3076  scoped_ptr<SpdyFrame> stream1_body(
3077      spdy_util_.ConstructSpdyBodyFrame(1, true));
3078  scoped_ptr<SpdyFrame> stream2_rst(
3079      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM));
3080  MockWrite writes[] = {
3081    CreateMockWrite(*stream1_syn, 1),
3082    CreateMockWrite(*stream2_rst, 4),
3083  };
3084
3085  scoped_ptr<SpdyFrame>
3086      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3087  scoped_ptr<SpdyFrame>
3088      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
3089                                    0,
3090                                    2,
3091                                    9,
3092                                    "http://www.google.com/foo.dat"));
3093  MockRead reads[] = {
3094    CreateMockRead(*stream1_reply, 2),
3095    CreateMockRead(*stream2_syn, 3),
3096    CreateMockRead(*stream1_body, 4),
3097    MockRead(ASYNC, ERR_IO_PENDING, 5),  // Force a pause
3098  };
3099
3100  OrderedSocketData data(reads, arraysize(reads),
3101                         writes, arraysize(writes));
3102  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3103                                     BoundNetLog(), GetParam(), NULL);
3104
3105  helper.RunPreTestSetup();
3106  helper.AddData(&data);
3107
3108  HttpNetworkTransaction* trans = helper.trans();
3109
3110  // Start the transaction with basic parameters.
3111  TestCompletionCallback callback;
3112  int rv = trans->Start(
3113      &CreateGetRequest(), callback.callback(), BoundNetLog());
3114  EXPECT_EQ(ERR_IO_PENDING, rv);
3115  rv = callback.WaitForResult();
3116  EXPECT_EQ(OK, rv);
3117
3118  // Verify that we consumed all test data.
3119  EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3120                                   << data.read_count()
3121                                   << " Read index: "
3122                                   << data.read_index();
3123  EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3124                                    << data.write_count()
3125                                    << " Write index: "
3126                                    << data.write_index();
3127
3128  // Verify the SYN_REPLY.
3129  HttpResponseInfo response = *trans->GetResponseInfo();
3130  EXPECT_TRUE(response.headers.get() != NULL);
3131  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3132}
3133
3134TEST_P(SpdyNetworkTransactionTest, ServerPushNoURL) {
3135  scoped_ptr<SpdyFrame> stream1_syn(
3136      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3137  scoped_ptr<SpdyFrame> stream1_body(
3138      spdy_util_.ConstructSpdyBodyFrame(1, true));
3139  scoped_ptr<SpdyFrame> stream2_rst(
3140      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
3141  MockWrite writes[] = {
3142    CreateMockWrite(*stream1_syn, 1),
3143    CreateMockWrite(*stream2_rst, 4),
3144  };
3145
3146  scoped_ptr<SpdyFrame>
3147      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3148  scoped_ptr<SpdyHeaderBlock> incomplete_headers(new SpdyHeaderBlock());
3149  (*incomplete_headers)["hello"] = "bye";
3150  (*incomplete_headers)[spdy_util_.GetStatusKey()] = "200 OK";
3151  (*incomplete_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
3152  scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
3153      incomplete_headers.Pass(), 2, 1));
3154  MockRead reads[] = {
3155    CreateMockRead(*stream1_reply, 2),
3156    CreateMockRead(*stream2_syn, 3),
3157    CreateMockRead(*stream1_body, 4),
3158    MockRead(ASYNC, ERR_IO_PENDING, 5)  // Force a pause
3159  };
3160
3161  OrderedSocketData data(reads, arraysize(reads),
3162                         writes, arraysize(writes));
3163  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3164                                     BoundNetLog(), GetParam(), NULL);
3165
3166  helper.RunPreTestSetup();
3167  helper.AddData(&data);
3168
3169  HttpNetworkTransaction* trans = helper.trans();
3170
3171  // Start the transaction with basic parameters.
3172  TestCompletionCallback callback;
3173  int rv = trans->Start(
3174      &CreateGetRequest(), callback.callback(), BoundNetLog());
3175  EXPECT_EQ(ERR_IO_PENDING, rv);
3176  rv = callback.WaitForResult();
3177  EXPECT_EQ(OK, rv);
3178  // Verify that we consumed all test data.
3179  EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3180                                   << data.read_count()
3181                                   << " Read index: "
3182                                   << data.read_index();
3183  EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3184                                    << data.write_count()
3185                                    << " Write index: "
3186                                    << data.write_index();
3187
3188  // Verify the SYN_REPLY.
3189  HttpResponseInfo response = *trans->GetResponseInfo();
3190  EXPECT_TRUE(response.headers.get() != NULL);
3191  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3192}
3193
3194// Verify that various SynReply headers parse correctly through the
3195// HTTP layer.
3196TEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) {
3197  struct SynReplyHeadersTests {
3198    int num_headers;
3199    const char* extra_headers[5];
3200    SpdyHeaderBlock expected_headers;
3201  } test_cases[] = {
3202    // This uses a multi-valued cookie header.
3203    { 2,
3204      { "cookie", "val1",
3205        "cookie", "val2",  // will get appended separated by NULL
3206        NULL
3207      },
3208    },
3209    // This is the minimalist set of headers.
3210    { 0,
3211      { NULL },
3212    },
3213    // Headers with a comma separated list.
3214    { 1,
3215      { "cookie", "val1,val2",
3216        NULL
3217      },
3218    }
3219  };
3220
3221  test_cases[0].expected_headers["cookie"] = "val1";
3222  test_cases[0].expected_headers["cookie"] += '\0';
3223  test_cases[0].expected_headers["cookie"] += "val2";
3224  test_cases[0].expected_headers["hello"] = "bye";
3225  test_cases[0].expected_headers["status"] = "200";
3226
3227  test_cases[1].expected_headers["hello"] = "bye";
3228  test_cases[1].expected_headers["status"] = "200";
3229
3230  test_cases[2].expected_headers["cookie"] = "val1,val2";
3231  test_cases[2].expected_headers["hello"] = "bye";
3232  test_cases[2].expected_headers["status"] = "200";
3233
3234  if (spdy_util_.spdy_version() < SPDY4) {
3235    // SPDY4/HTTP2 eliminates use of the :version header.
3236    test_cases[0].expected_headers["version"] = "HTTP/1.1";
3237    test_cases[1].expected_headers["version"] = "HTTP/1.1";
3238    test_cases[2].expected_headers["version"] = "HTTP/1.1";
3239  }
3240
3241  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3242    scoped_ptr<SpdyFrame> req(
3243        spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3244    MockWrite writes[] = { CreateMockWrite(*req) };
3245
3246    scoped_ptr<SpdyFrame> resp(
3247        spdy_util_.ConstructSpdyGetSynReply(test_cases[i].extra_headers,
3248                                 test_cases[i].num_headers,
3249                                 1));
3250    scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3251    MockRead reads[] = {
3252      CreateMockRead(*resp),
3253      CreateMockRead(*body),
3254      MockRead(ASYNC, 0, 0)  // EOF
3255    };
3256
3257    DelayedSocketData data(1, reads, arraysize(reads),
3258                           writes, arraysize(writes));
3259    NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3260                                       BoundNetLog(), GetParam(), NULL);
3261    helper.RunToCompletion(&data);
3262    TransactionHelperResult out = helper.output();
3263
3264    EXPECT_EQ(OK, out.rv);
3265    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3266    EXPECT_EQ("hello!", out.response_data);
3267
3268    scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3269    EXPECT_TRUE(headers.get() != NULL);
3270    void* iter = NULL;
3271    std::string name, value;
3272    SpdyHeaderBlock header_block;
3273    while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3274      if (header_block[name].empty()) {
3275        header_block[name] = value;
3276      } else {
3277        header_block[name] += '\0';
3278        header_block[name] += value;
3279      }
3280    }
3281    EXPECT_EQ(test_cases[i].expected_headers, header_block);
3282  }
3283}
3284
3285// Verify that various SynReply headers parse vary fields correctly
3286// through the HTTP layer, and the response matches the request.
3287TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) {
3288  // Modify the following data to change/add test cases:
3289  struct SynReplyTests {
3290    bool vary_matches;
3291    int num_headers[2];
3292    const char* extra_headers[2][16];
3293  } test_cases[] = {
3294    // Test the case of a multi-valued cookie.  When the value is delimited
3295    // with NUL characters, it needs to be unfolded into multiple headers.
3296    {
3297      true,
3298      { 1, 4 },
3299      { { "cookie",   "val1,val2",
3300          NULL
3301        },
3302        { "vary",     "cookie",
3303          spdy_util_.GetStatusKey(), "200",
3304          spdy_util_.GetPathKey(),      "/index.php",
3305          spdy_util_.GetVersionKey(), "HTTP/1.1",
3306          NULL
3307        }
3308      }
3309    }, {    // Multiple vary fields.
3310      true,
3311      { 2, 5 },
3312      { { "friend",   "barney",
3313          "enemy",    "snaggletooth",
3314          NULL
3315        },
3316        { "vary",     "friend",
3317          "vary",     "enemy",
3318          spdy_util_.GetStatusKey(), "200",
3319          spdy_util_.GetPathKey(),      "/index.php",
3320          spdy_util_.GetVersionKey(), "HTTP/1.1",
3321          NULL
3322        }
3323      }
3324    }, {    // Test a '*' vary field.
3325      false,
3326      { 1, 4 },
3327      { { "cookie",   "val1,val2",
3328          NULL
3329        },
3330        { "vary",     "*",
3331          spdy_util_.GetStatusKey(), "200",
3332          spdy_util_.GetPathKey(),      "/index.php",
3333          spdy_util_.GetVersionKey(), "HTTP/1.1",
3334          NULL
3335        }
3336      }
3337    }, {    // Multiple comma-separated vary fields.
3338      true,
3339      { 2, 4 },
3340      { { "friend",   "barney",
3341          "enemy",    "snaggletooth",
3342          NULL
3343        },
3344        { "vary",     "friend,enemy",
3345          spdy_util_.GetStatusKey(), "200",
3346          spdy_util_.GetPathKey(),      "/index.php",
3347          spdy_util_.GetVersionKey(), "HTTP/1.1",
3348          NULL
3349        }
3350      }
3351    }
3352  };
3353
3354  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3355    // Construct the request.
3356    scoped_ptr<SpdyFrame> frame_req(
3357        spdy_util_.ConstructSpdyGet(test_cases[i].extra_headers[0],
3358                                    test_cases[i].num_headers[0],
3359                                    false, 1, LOWEST, true));
3360
3361    MockWrite writes[] = {
3362      CreateMockWrite(*frame_req),
3363    };
3364
3365    // Construct the reply.
3366    SpdyHeaderBlock reply_headers;
3367    AppendToHeaderBlock(test_cases[i].extra_headers[1],
3368                        test_cases[i].num_headers[1],
3369                        &reply_headers);
3370    scoped_ptr<SpdyFrame> frame_reply(
3371        spdy_util_.ConstructSpdyReply(1, reply_headers));
3372
3373    scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3374    MockRead reads[] = {
3375      CreateMockRead(*frame_reply),
3376      CreateMockRead(*body),
3377      MockRead(ASYNC, 0, 0)  // EOF
3378    };
3379
3380    // Attach the headers to the request.
3381    int header_count = test_cases[i].num_headers[0];
3382
3383    HttpRequestInfo request = CreateGetRequest();
3384    for (int ct = 0; ct < header_count; ct++) {
3385      const char* header_key = test_cases[i].extra_headers[0][ct * 2];
3386      const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1];
3387      request.extra_headers.SetHeader(header_key, header_value);
3388    }
3389
3390    DelayedSocketData data(1, reads, arraysize(reads),
3391                           writes, arraysize(writes));
3392    NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
3393                                       BoundNetLog(), GetParam(), NULL);
3394    helper.RunToCompletion(&data);
3395    TransactionHelperResult out = helper.output();
3396
3397    EXPECT_EQ(OK, out.rv) << i;
3398    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line) << i;
3399    EXPECT_EQ("hello!", out.response_data) << i;
3400
3401    // Test the response information.
3402    EXPECT_TRUE(out.response_info.response_time >
3403                out.response_info.request_time) << i;
3404    base::TimeDelta test_delay = out.response_info.response_time -
3405                                 out.response_info.request_time;
3406    base::TimeDelta min_expected_delay;
3407    min_expected_delay.FromMilliseconds(10);
3408    EXPECT_GT(test_delay.InMillisecondsF(),
3409              min_expected_delay.InMillisecondsF()) << i;
3410    EXPECT_EQ(out.response_info.vary_data.is_valid(),
3411              test_cases[i].vary_matches) << i;
3412
3413    // Check the headers.
3414    scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3415    ASSERT_TRUE(headers.get() != NULL) << i;
3416    void* iter = NULL;
3417    std::string name, value, lines;
3418    while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3419      lines.append(name);
3420      lines.append(": ");
3421      lines.append(value);
3422      lines.append("\n");
3423    }
3424
3425    // Construct the expected header reply string.
3426    std::string expected_reply =
3427        spdy_util_.ConstructSpdyReplyString(reply_headers);
3428    EXPECT_EQ(expected_reply, lines) << i;
3429  }
3430}
3431
3432// Verify that we don't crash on invalid SynReply responses.
3433TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) {
3434  struct InvalidSynReplyTests {
3435    int num_headers;
3436    const char* headers[10];
3437  } test_cases[] = {
3438    // SYN_REPLY missing status header
3439    { 4,
3440      { "cookie", "val1",
3441        "cookie", "val2",
3442        spdy_util_.GetPathKey(), "/index.php",
3443        spdy_util_.GetVersionKey(), "HTTP/1.1",
3444        NULL
3445      },
3446    },
3447    // SYN_REPLY missing version header
3448    { 2,
3449      { "status", "200",
3450        spdy_util_.GetPathKey(), "/index.php",
3451        NULL
3452      },
3453    },
3454    // SYN_REPLY with no headers
3455    { 0, { NULL }, },
3456  };
3457
3458  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3459    scoped_ptr<SpdyFrame> req(
3460        spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3461    scoped_ptr<SpdyFrame> rst(
3462      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
3463    MockWrite writes[] = {
3464      CreateMockWrite(*req),
3465      CreateMockWrite(*rst),
3466    };
3467
3468    // Construct the reply.
3469    SpdyHeaderBlock reply_headers;
3470    AppendToHeaderBlock(
3471        test_cases[i].headers, test_cases[i].num_headers, &reply_headers);
3472    scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyReply(1, reply_headers));
3473    MockRead reads[] = {
3474      CreateMockRead(*resp),
3475      MockRead(ASYNC, 0, 0)  // EOF
3476    };
3477
3478    DelayedSocketData data(1, reads, arraysize(reads),
3479                           writes, arraysize(writes));
3480    NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3481                                       BoundNetLog(), GetParam(), NULL);
3482    helper.RunToCompletion(&data);
3483    TransactionHelperResult out = helper.output();
3484    EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3485  }
3486}
3487
3488// Verify that we don't crash on some corrupt frames.
3489// TODO(jgraettinger): SPDY4 and up treats a header decompression failure as a
3490// connection error. I'd like to backport this behavior to SPDY3 as well.
3491TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
3492  if (spdy_util_.spdy_version() >= SPDY4) {
3493    return;
3494  }
3495  // This is the length field that's too short.
3496  scoped_ptr<SpdyFrame> syn_reply_wrong_length(
3497      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3498  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3499  size_t right_size =
3500      (spdy_util_.spdy_version() < SPDY4) ?
3501      syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize() :
3502      syn_reply_wrong_length->size();
3503  size_t wrong_size = right_size - 4;
3504  test::SetFrameLength(syn_reply_wrong_length.get(),
3505                       wrong_size,
3506                       spdy_util_.spdy_version());
3507
3508  struct SynReplyTests {
3509    const SpdyFrame* syn_reply;
3510  } test_cases[] = {
3511    { syn_reply_wrong_length.get(), },
3512  };
3513
3514  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3515    scoped_ptr<SpdyFrame> req(
3516        spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3517    scoped_ptr<SpdyFrame> rst(
3518        spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
3519    MockWrite writes[] = {
3520      CreateMockWrite(*req),
3521      CreateMockWrite(*rst),
3522    };
3523
3524    scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3525    MockRead reads[] = {
3526      MockRead(ASYNC, test_cases[i].syn_reply->data(), wrong_size),
3527      CreateMockRead(*body),
3528      MockRead(ASYNC, 0, 0)  // EOF
3529    };
3530
3531    DelayedSocketData data(1, reads, arraysize(reads),
3532                           writes, arraysize(writes));
3533    NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3534                                       BoundNetLog(), GetParam(), NULL);
3535    helper.RunToCompletion(&data);
3536    TransactionHelperResult out = helper.output();
3537    EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3538  }
3539}
3540
3541// SPDY4 treats a header decompression failure as a connection-level error.
3542TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionErrorSpdy4) {
3543  if (spdy_util_.spdy_version() < SPDY4) {
3544    return;
3545  }
3546  // This is the length field that's too short.
3547  scoped_ptr<SpdyFrame> syn_reply_wrong_length(
3548      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3549  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3550  size_t right_size =
3551      syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize();
3552  size_t wrong_size = right_size - 4;
3553  test::SetFrameLength(syn_reply_wrong_length.get(),
3554                       wrong_size,
3555                       spdy_util_.spdy_version());
3556
3557  scoped_ptr<SpdyFrame> req(
3558      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3559  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3560      0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3561  MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*goaway)};
3562
3563  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3564  MockRead reads[] = {
3565    MockRead(ASYNC, syn_reply_wrong_length->data(),
3566             syn_reply_wrong_length->size() - 4),
3567  };
3568
3569  DelayedSocketData data(1, reads, arraysize(reads),
3570                         writes, arraysize(writes));
3571  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3572                                     BoundNetLog(), GetParam(), NULL);
3573  helper.RunToCompletion(&data);
3574  TransactionHelperResult out = helper.output();
3575  EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
3576}
3577
3578TEST_P(SpdyNetworkTransactionTest, GoAwayOnDecompressionFailure) {
3579  if (GetParam().protocol < kProtoSPDY4) {
3580    // Decompression failures are a stream error in SPDY3 and above.
3581    return;
3582  }
3583  scoped_ptr<SpdyFrame> req(
3584      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3585  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3586      0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3587  MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*goaway)};
3588
3589  // Read HEADERS with corrupted payload.
3590  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3591  memset(resp->data() + 12, 0xff, resp->size() - 12);
3592  MockRead reads[] = {CreateMockRead(*resp)};
3593
3594  DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
3595  NormalSpdyTransactionHelper helper(
3596      CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
3597  helper.RunToCompletion(&data);
3598  TransactionHelperResult out = helper.output();
3599  EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
3600}
3601
3602TEST_P(SpdyNetworkTransactionTest, GoAwayOnFrameSizeError) {
3603  scoped_ptr<SpdyFrame> req(
3604      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3605  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3606      0, GOAWAY_PROTOCOL_ERROR, "Framer error: 1 (INVALID_CONTROL_FRAME)."));
3607  MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*goaway)};
3608
3609  // Read WINDOW_UPDATE with incorrectly-sized payload.
3610  // TODO(jgraettinger): SpdyFramer signals this as an INVALID_CONTROL_FRAME,
3611  // which is mapped to a protocol error, and not a frame size error.
3612  scoped_ptr<SpdyFrame> bad_window_update(
3613      spdy_util_.ConstructSpdyWindowUpdate(1, 1));
3614  test::SetFrameLength(bad_window_update.get(),
3615                       bad_window_update->size() - 1,
3616                       spdy_util_.spdy_version());
3617  MockRead reads[] = {CreateMockRead(*bad_window_update)};
3618
3619  DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
3620  NormalSpdyTransactionHelper helper(
3621      CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
3622  helper.RunToCompletion(&data);
3623  TransactionHelperResult out = helper.output();
3624  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3625}
3626
3627// Test that we shutdown correctly on write errors.
3628TEST_P(SpdyNetworkTransactionTest, WriteError) {
3629  scoped_ptr<SpdyFrame> req(
3630      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3631  MockWrite writes[] = {
3632      // We'll write 10 bytes successfully
3633      MockWrite(ASYNC, req->data(), 10, 0),
3634      // Followed by ERROR!
3635      MockWrite(ASYNC, ERR_FAILED, 1),
3636      // Session drains and attempts to write a GOAWAY: Another ERROR!
3637      MockWrite(ASYNC, ERR_FAILED, 2),
3638  };
3639
3640  MockRead reads[] = {
3641      MockRead(ASYNC, 0, 3)  // EOF
3642  };
3643
3644  DeterministicSocketData data(reads, arraysize(reads),
3645                               writes, arraysize(writes));
3646
3647  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3648                                     BoundNetLog(), GetParam(), NULL);
3649  helper.SetDeterministic();
3650  helper.RunPreTestSetup();
3651  helper.AddDeterministicData(&data);
3652  EXPECT_TRUE(helper.StartDefaultTest());
3653  data.RunFor(2);
3654  helper.FinishDefaultTest();
3655  EXPECT_TRUE(data.at_write_eof());
3656  EXPECT_TRUE(!data.at_read_eof());
3657  TransactionHelperResult out = helper.output();
3658  EXPECT_EQ(ERR_FAILED, out.rv);
3659}
3660
3661// Test that partial writes work.
3662TEST_P(SpdyNetworkTransactionTest, PartialWrite) {
3663  // Chop the SYN_STREAM frame into 5 chunks.
3664  scoped_ptr<SpdyFrame> req(
3665      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3666  const int kChunks = 5;
3667  scoped_ptr<MockWrite[]> writes(ChopWriteFrame(*req.get(), kChunks));
3668
3669  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3670  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3671  MockRead reads[] = {
3672    CreateMockRead(*resp),
3673    CreateMockRead(*body),
3674    MockRead(ASYNC, 0, 0)  // EOF
3675  };
3676
3677  DelayedSocketData data(kChunks, reads, arraysize(reads),
3678                         writes.get(), kChunks);
3679  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3680                                     BoundNetLog(), GetParam(), NULL);
3681  helper.RunToCompletion(&data);
3682  TransactionHelperResult out = helper.output();
3683  EXPECT_EQ(OK, out.rv);
3684  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3685  EXPECT_EQ("hello!", out.response_data);
3686}
3687
3688// In this test, we enable compression, but get a uncompressed SynReply from
3689// the server.  Verify that teardown is all clean.
3690TEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) {
3691  if (spdy_util_.spdy_version() >= SPDY4) {
3692    // HPACK doesn't use deflate compression.
3693    return;
3694  }
3695  scoped_ptr<SpdyFrame> compressed(
3696      spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, LOWEST, true));
3697  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3698      0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3699  MockWrite writes[] = {CreateMockWrite(*compressed), CreateMockWrite(*goaway)};
3700
3701  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3702  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3703  MockRead reads[] = {
3704    CreateMockRead(*resp),
3705  };
3706
3707  DelayedSocketData data(1, reads, arraysize(reads),
3708                         writes, arraysize(writes));
3709  SpdySessionDependencies* session_deps =
3710      CreateSpdySessionDependencies(GetParam());
3711  session_deps->enable_compression = true;
3712  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3713                                     BoundNetLog(), GetParam(), session_deps);
3714  helper.RunToCompletion(&data);
3715  TransactionHelperResult out = helper.output();
3716  EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
3717  data.Reset();
3718}
3719
3720// Test that the NetLog contains good data for a simple GET request.
3721TEST_P(SpdyNetworkTransactionTest, NetLog) {
3722  static const char* const kExtraHeaders[] = {
3723    "user-agent",   "Chrome",
3724  };
3725  scoped_ptr<SpdyFrame> req(
3726      spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, false, 1, LOWEST, true));
3727  MockWrite writes[] = { CreateMockWrite(*req) };
3728
3729  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3730  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3731  MockRead reads[] = {
3732    CreateMockRead(*resp),
3733    CreateMockRead(*body),
3734    MockRead(ASYNC, 0, 0)  // EOF
3735  };
3736
3737  CapturingBoundNetLog log;
3738
3739  DelayedSocketData data(1, reads, arraysize(reads),
3740                         writes, arraysize(writes));
3741  NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(),
3742                                     DEFAULT_PRIORITY,
3743                                     log.bound(), GetParam(), NULL);
3744  helper.RunToCompletion(&data);
3745  TransactionHelperResult out = helper.output();
3746  EXPECT_EQ(OK, out.rv);
3747  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3748  EXPECT_EQ("hello!", out.response_data);
3749
3750  // Check that the NetLog was filled reasonably.
3751  // This test is intentionally non-specific about the exact ordering of the
3752  // log; instead we just check to make sure that certain events exist, and that
3753  // they are in the right order.
3754  net::CapturingNetLog::CapturedEntryList entries;
3755  log.GetEntries(&entries);
3756
3757  EXPECT_LT(0u, entries.size());
3758  int pos = 0;
3759  pos = net::ExpectLogContainsSomewhere(entries, 0,
3760      net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3761      net::NetLog::PHASE_BEGIN);
3762  pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3763      net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3764      net::NetLog::PHASE_END);
3765  pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3766      net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3767      net::NetLog::PHASE_BEGIN);
3768  pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3769      net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3770      net::NetLog::PHASE_END);
3771  pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3772      net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3773      net::NetLog::PHASE_BEGIN);
3774  pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3775      net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3776      net::NetLog::PHASE_END);
3777
3778  // Check that we logged all the headers correctly
3779  pos = net::ExpectLogContainsSomewhere(
3780      entries, 0,
3781      net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM,
3782      net::NetLog::PHASE_NONE);
3783
3784  base::ListValue* header_list;
3785  ASSERT_TRUE(entries[pos].params.get());
3786  ASSERT_TRUE(entries[pos].params->GetList("headers", &header_list));
3787
3788  std::vector<std::string> expected;
3789  expected.push_back(std::string(spdy_util_.GetHostKey()) + ": www.google.com");
3790  expected.push_back(std::string(spdy_util_.GetPathKey()) + ": /");
3791  expected.push_back(std::string(spdy_util_.GetSchemeKey()) + ": http");
3792  expected.push_back(std::string(spdy_util_.GetMethodKey()) + ": GET");
3793  expected.push_back("user-agent: Chrome");
3794  if (spdy_util_.spdy_version() < SPDY4) {
3795    // SPDY4/HTTP2 eliminates use of the :version header.
3796    expected.push_back(std::string(spdy_util_.GetVersionKey()) + ": HTTP/1.1");
3797  }
3798  EXPECT_EQ(expected.size(), header_list->GetSize());
3799  for (std::vector<std::string>::const_iterator it = expected.begin();
3800       it != expected.end();
3801       ++it) {
3802    base::StringValue header(*it);
3803    EXPECT_NE(header_list->end(), header_list->Find(header)) <<
3804        "Header not found: " << *it;
3805  }
3806}
3807
3808// Since we buffer the IO from the stream to the renderer, this test verifies
3809// that when we read out the maximum amount of data (e.g. we received 50 bytes
3810// on the network, but issued a Read for only 5 of those bytes) that the data
3811// flow still works correctly.
3812TEST_P(SpdyNetworkTransactionTest, BufferFull) {
3813  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3814
3815  scoped_ptr<SpdyFrame> req(
3816      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3817  MockWrite writes[] = { CreateMockWrite(*req) };
3818
3819  // 2 data frames in a single read.
3820  scoped_ptr<SpdyFrame> data_frame_1(
3821      framer.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE));
3822  scoped_ptr<SpdyFrame> data_frame_2(
3823      framer.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE));
3824  const SpdyFrame* data_frames[2] = {
3825    data_frame_1.get(),
3826    data_frame_2.get(),
3827  };
3828  char combined_data_frames[100];
3829  int combined_data_frames_len =
3830      CombineFrames(data_frames, arraysize(data_frames),
3831                    combined_data_frames, arraysize(combined_data_frames));
3832  scoped_ptr<SpdyFrame> last_frame(
3833      framer.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN));
3834
3835  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3836  MockRead reads[] = {
3837    CreateMockRead(*resp),
3838    MockRead(ASYNC, ERR_IO_PENDING),  // Force a pause
3839    MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
3840    MockRead(ASYNC, ERR_IO_PENDING),  // Force a pause
3841    CreateMockRead(*last_frame),
3842    MockRead(ASYNC, 0, 0)  // EOF
3843  };
3844
3845  DelayedSocketData data(1, reads, arraysize(reads),
3846                         writes, arraysize(writes));
3847
3848  TestCompletionCallback callback;
3849
3850  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3851                                     BoundNetLog(), GetParam(), NULL);
3852  helper.RunPreTestSetup();
3853  helper.AddData(&data);
3854  HttpNetworkTransaction* trans = helper.trans();
3855  int rv = trans->Start(
3856      &CreateGetRequest(), callback.callback(), BoundNetLog());
3857  EXPECT_EQ(ERR_IO_PENDING, rv);
3858
3859  TransactionHelperResult out = helper.output();
3860  out.rv = callback.WaitForResult();
3861  EXPECT_EQ(out.rv, OK);
3862
3863  const HttpResponseInfo* response = trans->GetResponseInfo();
3864  EXPECT_TRUE(response->headers.get() != NULL);
3865  EXPECT_TRUE(response->was_fetched_via_spdy);
3866  out.status_line = response->headers->GetStatusLine();
3867  out.response_info = *response;  // Make a copy so we can verify.
3868
3869  // Read Data
3870  TestCompletionCallback read_callback;
3871
3872  std::string content;
3873  do {
3874    // Read small chunks at a time.
3875    const int kSmallReadSize = 3;
3876    scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3877    rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
3878    if (rv == net::ERR_IO_PENDING) {
3879      data.CompleteRead();
3880      rv = read_callback.WaitForResult();
3881    }
3882    if (rv > 0) {
3883      content.append(buf->data(), rv);
3884    } else if (rv < 0) {
3885      NOTREACHED();
3886    }
3887  } while (rv > 0);
3888
3889  out.response_data.swap(content);
3890
3891  // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3892  // MockClientSocketFactory) are still alive.
3893  base::RunLoop().RunUntilIdle();
3894
3895  // Verify that we consumed all test data.
3896  helper.VerifyDataConsumed();
3897
3898  EXPECT_EQ(OK, out.rv);
3899  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3900  EXPECT_EQ("goodbye world", out.response_data);
3901}
3902
3903// Verify that basic buffering works; when multiple data frames arrive
3904// at the same time, ensure that we don't notify a read completion for
3905// each data frame individually.
3906TEST_P(SpdyNetworkTransactionTest, Buffering) {
3907  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3908
3909  scoped_ptr<SpdyFrame> req(
3910      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3911  MockWrite writes[] = { CreateMockWrite(*req) };
3912
3913  // 4 data frames in a single read.
3914  scoped_ptr<SpdyFrame> data_frame(
3915      framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
3916  scoped_ptr<SpdyFrame> data_frame_fin(
3917      framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
3918  const SpdyFrame* data_frames[4] = {
3919    data_frame.get(),
3920    data_frame.get(),
3921    data_frame.get(),
3922    data_frame_fin.get()
3923  };
3924  char combined_data_frames[100];
3925  int combined_data_frames_len =
3926      CombineFrames(data_frames, arraysize(data_frames),
3927                    combined_data_frames, arraysize(combined_data_frames));
3928
3929  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3930  MockRead reads[] = {
3931    CreateMockRead(*resp),
3932    MockRead(ASYNC, ERR_IO_PENDING),  // Force a pause
3933    MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
3934    MockRead(ASYNC, 0, 0)  // EOF
3935  };
3936
3937  DelayedSocketData data(1, reads, arraysize(reads),
3938                         writes, arraysize(writes));
3939
3940  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3941                                     BoundNetLog(), GetParam(), NULL);
3942  helper.RunPreTestSetup();
3943  helper.AddData(&data);
3944  HttpNetworkTransaction* trans = helper.trans();
3945
3946  TestCompletionCallback callback;
3947  int rv = trans->Start(
3948      &CreateGetRequest(), callback.callback(), BoundNetLog());
3949  EXPECT_EQ(ERR_IO_PENDING, rv);
3950
3951  TransactionHelperResult out = helper.output();
3952  out.rv = callback.WaitForResult();
3953  EXPECT_EQ(out.rv, OK);
3954
3955  const HttpResponseInfo* response = trans->GetResponseInfo();
3956  EXPECT_TRUE(response->headers.get() != NULL);
3957  EXPECT_TRUE(response->was_fetched_via_spdy);
3958  out.status_line = response->headers->GetStatusLine();
3959  out.response_info = *response;  // Make a copy so we can verify.
3960
3961  // Read Data
3962  TestCompletionCallback read_callback;
3963
3964  std::string content;
3965  int reads_completed = 0;
3966  do {
3967    // Read small chunks at a time.
3968    const int kSmallReadSize = 14;
3969    scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3970    rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
3971    if (rv == net::ERR_IO_PENDING) {
3972      data.CompleteRead();
3973      rv = read_callback.WaitForResult();
3974    }
3975    if (rv > 0) {
3976      EXPECT_EQ(kSmallReadSize, rv);
3977      content.append(buf->data(), rv);
3978    } else if (rv < 0) {
3979      FAIL() << "Unexpected read error: " << rv;
3980    }
3981    reads_completed++;
3982  } while (rv > 0);
3983
3984  EXPECT_EQ(3, reads_completed);  // Reads are: 14 bytes, 14 bytes, 0 bytes.
3985
3986  out.response_data.swap(content);
3987
3988  // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3989  // MockClientSocketFactory) are still alive.
3990  base::RunLoop().RunUntilIdle();
3991
3992  // Verify that we consumed all test data.
3993  helper.VerifyDataConsumed();
3994
3995  EXPECT_EQ(OK, out.rv);
3996  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3997  EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3998}
3999
4000// Verify the case where we buffer data but read it after it has been buffered.
4001TEST_P(SpdyNetworkTransactionTest, BufferedAll) {
4002  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4003
4004  scoped_ptr<SpdyFrame> req(
4005      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4006  MockWrite writes[] = { CreateMockWrite(*req) };
4007
4008  // 5 data frames in a single read.
4009  scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4010  scoped_ptr<SpdyFrame> data_frame(
4011      framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4012  scoped_ptr<SpdyFrame> data_frame_fin(
4013      framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
4014  const SpdyFrame* frames[5] = {reply.get(), data_frame.get(), data_frame.get(),
4015                                data_frame.get(), data_frame_fin.get()};
4016  char combined_frames[200];
4017  int combined_frames_len =
4018      CombineFrames(frames, arraysize(frames),
4019                    combined_frames, arraysize(combined_frames));
4020
4021  MockRead reads[] = {
4022    MockRead(ASYNC, combined_frames, combined_frames_len),
4023    MockRead(ASYNC, 0, 0)  // EOF
4024  };
4025
4026  DelayedSocketData data(1, reads, arraysize(reads),
4027                         writes, arraysize(writes));
4028
4029  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4030                                     BoundNetLog(), GetParam(), NULL);
4031  helper.RunPreTestSetup();
4032  helper.AddData(&data);
4033  HttpNetworkTransaction* trans = helper.trans();
4034
4035  TestCompletionCallback callback;
4036  int rv = trans->Start(
4037      &CreateGetRequest(), callback.callback(), BoundNetLog());
4038  EXPECT_EQ(ERR_IO_PENDING, rv);
4039
4040  TransactionHelperResult out = helper.output();
4041  out.rv = callback.WaitForResult();
4042  EXPECT_EQ(out.rv, OK);
4043
4044  const HttpResponseInfo* response = trans->GetResponseInfo();
4045  EXPECT_TRUE(response->headers.get() != NULL);
4046  EXPECT_TRUE(response->was_fetched_via_spdy);
4047  out.status_line = response->headers->GetStatusLine();
4048  out.response_info = *response;  // Make a copy so we can verify.
4049
4050  // Read Data
4051  TestCompletionCallback read_callback;
4052
4053  std::string content;
4054  int reads_completed = 0;
4055  do {
4056    // Read small chunks at a time.
4057    const int kSmallReadSize = 14;
4058    scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4059    rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
4060    if (rv > 0) {
4061      EXPECT_EQ(kSmallReadSize, rv);
4062      content.append(buf->data(), rv);
4063    } else if (rv < 0) {
4064      FAIL() << "Unexpected read error: " << rv;
4065    }
4066    reads_completed++;
4067  } while (rv > 0);
4068
4069  EXPECT_EQ(3, reads_completed);
4070
4071  out.response_data.swap(content);
4072
4073  // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4074  // MockClientSocketFactory) are still alive.
4075  base::RunLoop().RunUntilIdle();
4076
4077  // Verify that we consumed all test data.
4078  helper.VerifyDataConsumed();
4079
4080  EXPECT_EQ(OK, out.rv);
4081  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4082  EXPECT_EQ("messagemessagemessagemessage", out.response_data);
4083}
4084
4085// Verify the case where we buffer data and close the connection.
4086TEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
4087  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4088
4089  scoped_ptr<SpdyFrame> req(
4090      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4091  MockWrite writes[] = { CreateMockWrite(*req) };
4092
4093  // All data frames in a single read.
4094  // NOTE: We don't FIN the stream.
4095  scoped_ptr<SpdyFrame> data_frame(
4096      framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4097  const SpdyFrame* data_frames[4] = {
4098    data_frame.get(),
4099    data_frame.get(),
4100    data_frame.get(),
4101    data_frame.get()
4102  };
4103  char combined_data_frames[100];
4104  int combined_data_frames_len =
4105      CombineFrames(data_frames, arraysize(data_frames),
4106                    combined_data_frames, arraysize(combined_data_frames));
4107  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4108  MockRead reads[] = {
4109    CreateMockRead(*resp),
4110    MockRead(ASYNC, ERR_IO_PENDING),  // Force a wait
4111    MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
4112    MockRead(ASYNC, 0, 0)  // EOF
4113  };
4114
4115  DelayedSocketData data(1, reads, arraysize(reads),
4116                         writes, arraysize(writes));
4117
4118  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4119                                     BoundNetLog(), GetParam(), NULL);
4120  helper.RunPreTestSetup();
4121  helper.AddData(&data);
4122  HttpNetworkTransaction* trans = helper.trans();
4123
4124  TestCompletionCallback callback;
4125
4126  int rv = trans->Start(
4127      &CreateGetRequest(), callback.callback(), BoundNetLog());
4128  EXPECT_EQ(ERR_IO_PENDING, rv);
4129
4130  TransactionHelperResult out = helper.output();
4131  out.rv = callback.WaitForResult();
4132  EXPECT_EQ(out.rv, OK);
4133
4134  const HttpResponseInfo* response = trans->GetResponseInfo();
4135  EXPECT_TRUE(response->headers.get() != NULL);
4136  EXPECT_TRUE(response->was_fetched_via_spdy);
4137  out.status_line = response->headers->GetStatusLine();
4138  out.response_info = *response;  // Make a copy so we can verify.
4139
4140  // Read Data
4141  TestCompletionCallback read_callback;
4142
4143  std::string content;
4144  int reads_completed = 0;
4145  do {
4146    // Read small chunks at a time.
4147    const int kSmallReadSize = 14;
4148    scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4149    rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
4150    if (rv == net::ERR_IO_PENDING) {
4151      data.CompleteRead();
4152      rv = read_callback.WaitForResult();
4153    }
4154    if (rv > 0) {
4155      content.append(buf->data(), rv);
4156    } else if (rv < 0) {
4157      // This test intentionally closes the connection, and will get an error.
4158      EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
4159      break;
4160    }
4161    reads_completed++;
4162  } while (rv > 0);
4163
4164  EXPECT_EQ(0, reads_completed);
4165
4166  out.response_data.swap(content);
4167
4168  // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4169  // MockClientSocketFactory) are still alive.
4170  base::RunLoop().RunUntilIdle();
4171
4172  // Verify that we consumed all test data.
4173  helper.VerifyDataConsumed();
4174}
4175
4176// Verify the case where we buffer data and cancel the transaction.
4177TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) {
4178  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4179
4180  scoped_ptr<SpdyFrame> req(
4181      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4182  scoped_ptr<SpdyFrame> rst(
4183      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
4184  MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*rst)};
4185
4186  // NOTE: We don't FIN the stream.
4187  scoped_ptr<SpdyFrame> data_frame(
4188      framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4189
4190  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4191  MockRead reads[] = {
4192    CreateMockRead(*resp),
4193    MockRead(ASYNC, ERR_IO_PENDING),  // Force a wait
4194    CreateMockRead(*data_frame),
4195    MockRead(ASYNC, 0, 0)  // EOF
4196  };
4197
4198  DelayedSocketData data(1, reads, arraysize(reads),
4199                         writes, arraysize(writes));
4200
4201  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4202                                     BoundNetLog(), GetParam(), NULL);
4203  helper.RunPreTestSetup();
4204  helper.AddData(&data);
4205  HttpNetworkTransaction* trans = helper.trans();
4206  TestCompletionCallback callback;
4207
4208  int rv = trans->Start(
4209      &CreateGetRequest(), callback.callback(), BoundNetLog());
4210  EXPECT_EQ(ERR_IO_PENDING, rv);
4211
4212  TransactionHelperResult out = helper.output();
4213  out.rv = callback.WaitForResult();
4214  EXPECT_EQ(out.rv, OK);
4215
4216  const HttpResponseInfo* response = trans->GetResponseInfo();
4217  EXPECT_TRUE(response->headers.get() != NULL);
4218  EXPECT_TRUE(response->was_fetched_via_spdy);
4219  out.status_line = response->headers->GetStatusLine();
4220  out.response_info = *response;  // Make a copy so we can verify.
4221
4222  // Read Data
4223  TestCompletionCallback read_callback;
4224
4225  const int kReadSize = 256;
4226  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kReadSize));
4227  rv = trans->Read(buf.get(), kReadSize, read_callback.callback());
4228  ASSERT_EQ(net::ERR_IO_PENDING, rv) << "Unexpected read: " << rv;
4229
4230  // Complete the read now, which causes buffering to start.
4231  data.CompleteRead();
4232  // Destroy the transaction, causing the stream to get cancelled
4233  // and orphaning the buffered IO task.
4234  helper.ResetTrans();
4235
4236  // Flush the MessageLoop; this will cause the buffered IO task
4237  // to run for the final time.
4238  base::RunLoop().RunUntilIdle();
4239
4240  // Verify that we consumed all test data.
4241  helper.VerifyDataConsumed();
4242}
4243
4244// Test that if the server requests persistence of settings, that we save
4245// the settings in the HttpServerProperties.
4246TEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
4247  if (spdy_util_.spdy_version() >= SPDY4) {
4248    // SPDY4 doesn't support settings persistence.
4249    return;
4250  }
4251  static const SpdyHeaderInfo kSynReplyInfo = {
4252    SYN_REPLY,                              // Syn Reply
4253    1,                                      // Stream ID
4254    0,                                      // Associated Stream ID
4255    ConvertRequestPriorityToSpdyPriority(
4256        LOWEST, spdy_util_.spdy_version()),
4257    kSpdyCredentialSlotUnused,
4258    CONTROL_FLAG_NONE,                      // Control Flags
4259    false,                                  // Compressed
4260    RST_STREAM_INVALID,                     // Status
4261    NULL,                                   // Data
4262    0,                                      // Data Length
4263    DATA_FLAG_NONE                          // Data Flags
4264  };
4265
4266  BoundNetLog net_log;
4267  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4268                                     net_log, GetParam(), NULL);
4269  helper.RunPreTestSetup();
4270
4271  // Verify that no settings exist initially.
4272  HostPortPair host_port_pair("www.google.com", helper.port());
4273  SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4274  EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4275      host_port_pair).empty());
4276
4277  // Construct the request.
4278  scoped_ptr<SpdyFrame> req(
4279      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4280  MockWrite writes[] = { CreateMockWrite(*req) };
4281
4282  // Construct the reply.
4283  scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4284  (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4285  (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
4286  scoped_ptr<SpdyFrame> reply(
4287    spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
4288
4289  const SpdySettingsIds kSampleId1 = SETTINGS_UPLOAD_BANDWIDTH;
4290  unsigned int kSampleValue1 = 0x0a0a0a0a;
4291  const SpdySettingsIds kSampleId2 = SETTINGS_DOWNLOAD_BANDWIDTH;
4292  unsigned int kSampleValue2 = 0x0b0b0b0b;
4293  const SpdySettingsIds kSampleId3 = SETTINGS_ROUND_TRIP_TIME;
4294  unsigned int kSampleValue3 = 0x0c0c0c0c;
4295  scoped_ptr<SpdyFrame> settings_frame;
4296  {
4297    // Construct the SETTINGS frame.
4298    SettingsMap settings;
4299    // First add a persisted setting.
4300    settings[kSampleId1] =
4301        SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue1);
4302    // Next add a non-persisted setting.
4303    settings[kSampleId2] =
4304        SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kSampleValue2);
4305    // Next add another persisted setting.
4306    settings[kSampleId3] =
4307        SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue3);
4308    settings_frame.reset(spdy_util_.ConstructSpdySettings(settings));
4309  }
4310
4311  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4312  MockRead reads[] = {
4313    CreateMockRead(*reply),
4314    CreateMockRead(*body),
4315    CreateMockRead(*settings_frame),
4316    MockRead(ASYNC, 0, 0)  // EOF
4317  };
4318
4319  DelayedSocketData data(1, reads, arraysize(reads),
4320                         writes, arraysize(writes));
4321  helper.AddData(&data);
4322  helper.RunDefaultTest();
4323  helper.VerifyDataConsumed();
4324  TransactionHelperResult out = helper.output();
4325  EXPECT_EQ(OK, out.rv);
4326  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4327  EXPECT_EQ("hello!", out.response_data);
4328
4329  {
4330    // Verify we had two persisted settings.
4331    const SettingsMap& settings_map =
4332        spdy_session_pool->http_server_properties()->GetSpdySettings(
4333            host_port_pair);
4334    ASSERT_EQ(2u, settings_map.size());
4335
4336    // Verify the first persisted setting.
4337    SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4338    EXPECT_TRUE(it1 != settings_map.end());
4339    SettingsFlagsAndValue flags_and_value1 = it1->second;
4340    EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4341    EXPECT_EQ(kSampleValue1, flags_and_value1.second);
4342
4343    // Verify the second persisted setting.
4344    SettingsMap::const_iterator it3 = settings_map.find(kSampleId3);
4345    EXPECT_TRUE(it3 != settings_map.end());
4346    SettingsFlagsAndValue flags_and_value3 = it3->second;
4347    EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value3.first);
4348    EXPECT_EQ(kSampleValue3, flags_and_value3.second);
4349  }
4350}
4351
4352// Test that when there are settings saved that they are sent back to the
4353// server upon session establishment.
4354TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) {
4355  if (spdy_util_.spdy_version() >= SPDY4) {
4356    // SPDY4 doesn't support settings persistence.
4357    return;
4358  }
4359  static const SpdyHeaderInfo kSynReplyInfo = {
4360    SYN_REPLY,                              // Syn Reply
4361    1,                                      // Stream ID
4362    0,                                      // Associated Stream ID
4363    ConvertRequestPriorityToSpdyPriority(
4364        LOWEST, spdy_util_.spdy_version()),
4365    kSpdyCredentialSlotUnused,
4366    CONTROL_FLAG_NONE,                      // Control Flags
4367    false,                                  // Compressed
4368    RST_STREAM_INVALID,                     // Status
4369    NULL,                                   // Data
4370    0,                                      // Data Length
4371    DATA_FLAG_NONE                          // Data Flags
4372  };
4373
4374  BoundNetLog net_log;
4375  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4376                                     net_log, GetParam(), NULL);
4377  helper.RunPreTestSetup();
4378
4379  SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4380
4381  SpdySessionPoolPeer pool_peer(spdy_session_pool);
4382  pool_peer.SetEnableSendingInitialData(true);
4383
4384  // Verify that no settings exist initially.
4385  HostPortPair host_port_pair("www.google.com", helper.port());
4386  EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4387      host_port_pair).empty());
4388
4389  const SpdySettingsIds kSampleId1 = SETTINGS_MAX_CONCURRENT_STREAMS;
4390  unsigned int kSampleValue1 = 0x0a0a0a0a;
4391  const SpdySettingsIds kSampleId2 = SETTINGS_INITIAL_WINDOW_SIZE;
4392  unsigned int kSampleValue2 = 0x0c0c0c0c;
4393
4394  // First add a persisted setting.
4395  spdy_session_pool->http_server_properties()->SetSpdySetting(
4396      host_port_pair,
4397      kSampleId1,
4398      SETTINGS_FLAG_PLEASE_PERSIST,
4399      kSampleValue1);
4400
4401  // Next add another persisted setting.
4402  spdy_session_pool->http_server_properties()->SetSpdySetting(
4403      host_port_pair,
4404      kSampleId2,
4405      SETTINGS_FLAG_PLEASE_PERSIST,
4406      kSampleValue2);
4407
4408  EXPECT_EQ(2u, spdy_session_pool->http_server_properties()->GetSpdySettings(
4409      host_port_pair).size());
4410
4411  // Construct the initial SETTINGS frame.
4412  SettingsMap initial_settings;
4413  initial_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4414      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
4415  scoped_ptr<SpdyFrame> initial_settings_frame(
4416      spdy_util_.ConstructSpdySettings(initial_settings));
4417
4418  // Construct the initial window update.
4419  scoped_ptr<SpdyFrame> initial_window_update(
4420      spdy_util_.ConstructSpdyWindowUpdate(
4421          kSessionFlowControlStreamId,
4422          kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
4423
4424  // Construct the persisted SETTINGS frame.
4425  const SettingsMap& settings =
4426      spdy_session_pool->http_server_properties()->GetSpdySettings(
4427          host_port_pair);
4428  scoped_ptr<SpdyFrame> settings_frame(
4429      spdy_util_.ConstructSpdySettings(settings));
4430
4431  // Construct the request.
4432  scoped_ptr<SpdyFrame> req(
4433      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4434
4435  std::vector<MockWrite> writes;
4436  if (GetParam().protocol == kProtoSPDY4) {
4437    writes.push_back(
4438        MockWrite(ASYNC,
4439                  kHttp2ConnectionHeaderPrefix,
4440                  kHttp2ConnectionHeaderPrefixSize));
4441  }
4442  writes.push_back(CreateMockWrite(*initial_settings_frame));
4443  if (GetParam().protocol >= kProtoSPDY31) {
4444    writes.push_back(CreateMockWrite(*initial_window_update));
4445  };
4446  writes.push_back(CreateMockWrite(*settings_frame));
4447  writes.push_back(CreateMockWrite(*req));
4448
4449  // Construct the reply.
4450  scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4451  (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4452  (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
4453  scoped_ptr<SpdyFrame> reply(
4454    spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
4455
4456  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4457  MockRead reads[] = {
4458    CreateMockRead(*reply),
4459    CreateMockRead(*body),
4460    MockRead(ASYNC, 0, 0)  // EOF
4461  };
4462
4463  DelayedSocketData data(2, reads, arraysize(reads),
4464                         vector_as_array(&writes), writes.size());
4465  helper.AddData(&data);
4466  helper.RunDefaultTest();
4467  helper.VerifyDataConsumed();
4468  TransactionHelperResult out = helper.output();
4469  EXPECT_EQ(OK, out.rv);
4470  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4471  EXPECT_EQ("hello!", out.response_data);
4472
4473  {
4474    // Verify we had two persisted settings.
4475    const SettingsMap& settings_map =
4476        spdy_session_pool->http_server_properties()->GetSpdySettings(
4477            host_port_pair);
4478    ASSERT_EQ(2u, settings_map.size());
4479
4480    // Verify the first persisted setting.
4481    SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4482    EXPECT_TRUE(it1 != settings_map.end());
4483    SettingsFlagsAndValue flags_and_value1 = it1->second;
4484    EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4485    EXPECT_EQ(kSampleValue1, flags_and_value1.second);
4486
4487    // Verify the second persisted setting.
4488    SettingsMap::const_iterator it2 = settings_map.find(kSampleId2);
4489    EXPECT_TRUE(it2 != settings_map.end());
4490    SettingsFlagsAndValue flags_and_value2 = it2->second;
4491    EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value2.first);
4492    EXPECT_EQ(kSampleValue2, flags_and_value2.second);
4493  }
4494}
4495
4496TEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
4497  scoped_ptr<SpdyFrame> req(
4498      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4499  MockWrite writes[] = { CreateMockWrite(*req) };
4500
4501  scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway());
4502  MockRead reads[] = {
4503    CreateMockRead(*go_away),
4504  };
4505
4506  DelayedSocketData data(1, reads, arraysize(reads),
4507                         writes, arraysize(writes));
4508  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4509                                     BoundNetLog(), GetParam(), NULL);
4510  helper.AddData(&data);
4511  helper.RunToCompletion(&data);
4512  TransactionHelperResult out = helper.output();
4513  EXPECT_EQ(ERR_ABORTED, out.rv);
4514}
4515
4516TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) {
4517  scoped_ptr<SpdyFrame> req(
4518      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4519  MockWrite writes[] = { CreateMockWrite(*req) };
4520
4521  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4522  MockRead reads[] = {
4523    CreateMockRead(*resp),
4524    MockRead(SYNCHRONOUS, 0, 0)  // EOF
4525  };
4526
4527  DelayedSocketData data(1, reads, arraysize(reads),
4528                         writes, arraysize(writes));
4529  BoundNetLog log;
4530  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4531                                     log, GetParam(), NULL);
4532  helper.RunPreTestSetup();
4533  helper.AddData(&data);
4534  HttpNetworkTransaction* trans = helper.trans();
4535
4536  TestCompletionCallback callback;
4537  TransactionHelperResult out;
4538  out.rv = trans->Start(&CreateGetRequest(), callback.callback(), log);
4539
4540  EXPECT_EQ(out.rv, ERR_IO_PENDING);
4541  out.rv = callback.WaitForResult();
4542  EXPECT_EQ(out.rv, OK);
4543
4544  const HttpResponseInfo* response = trans->GetResponseInfo();
4545  EXPECT_TRUE(response->headers.get() != NULL);
4546  EXPECT_TRUE(response->was_fetched_via_spdy);
4547  out.rv = ReadTransaction(trans, &out.response_data);
4548  EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv);
4549
4550  // Verify that we consumed all test data.
4551  helper.VerifyDataConsumed();
4552}
4553
4554// Test to make sure we can correctly connect through a proxy.
4555TEST_P(SpdyNetworkTransactionTest, ProxyConnect) {
4556  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4557                                     BoundNetLog(), GetParam(), NULL);
4558  helper.session_deps().reset(CreateSpdySessionDependencies(
4559      GetParam(),
4560      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
4561  helper.SetSession(make_scoped_refptr(
4562      SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
4563  helper.RunPreTestSetup();
4564  HttpNetworkTransaction* trans = helper.trans();
4565
4566  const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4567                           "Host: www.google.com\r\n"
4568                           "Proxy-Connection: keep-alive\r\n\r\n"};
4569  const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4570                           "Host: www.google.com\r\n"
4571                           "Proxy-Connection: keep-alive\r\n\r\n"};
4572  const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4573  scoped_ptr<SpdyFrame> req(
4574      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4575  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4576  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4577
4578  MockWrite writes_SPDYNPN[] = {
4579    MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4580    CreateMockWrite(*req, 2),
4581  };
4582  MockRead reads_SPDYNPN[] = {
4583    MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4584    CreateMockRead(*resp, 3),
4585    CreateMockRead(*body.get(), 4),
4586    MockRead(ASYNC, 0, 0, 5),
4587  };
4588
4589  MockWrite writes_SPDYSSL[] = {
4590    MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0),
4591    CreateMockWrite(*req, 2),
4592  };
4593  MockRead reads_SPDYSSL[] = {
4594    MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4595    CreateMockRead(*resp, 3),
4596    CreateMockRead(*body.get(), 4),
4597    MockRead(ASYNC, 0, 0, 5),
4598  };
4599
4600  MockWrite writes_SPDYNOSSL[] = {
4601    CreateMockWrite(*req, 0),
4602  };
4603
4604  MockRead reads_SPDYNOSSL[] = {
4605    CreateMockRead(*resp, 1),
4606    CreateMockRead(*body.get(), 2),
4607    MockRead(ASYNC, 0, 0, 3),
4608  };
4609
4610  scoped_ptr<OrderedSocketData> data;
4611  switch(GetParam().ssl_type) {
4612    case SPDYNOSSL:
4613      data.reset(new OrderedSocketData(reads_SPDYNOSSL,
4614                                       arraysize(reads_SPDYNOSSL),
4615                                       writes_SPDYNOSSL,
4616                                       arraysize(writes_SPDYNOSSL)));
4617      break;
4618    case SPDYSSL:
4619      data.reset(new OrderedSocketData(reads_SPDYSSL,
4620                                       arraysize(reads_SPDYSSL),
4621                                       writes_SPDYSSL,
4622                                       arraysize(writes_SPDYSSL)));
4623      break;
4624    case SPDYNPN:
4625      data.reset(new OrderedSocketData(reads_SPDYNPN,
4626                                       arraysize(reads_SPDYNPN),
4627                                       writes_SPDYNPN,
4628                                       arraysize(writes_SPDYNPN)));
4629      break;
4630    default:
4631      NOTREACHED();
4632  }
4633
4634  helper.AddData(data.get());
4635  TestCompletionCallback callback;
4636
4637  int rv = trans->Start(
4638      &CreateGetRequest(), callback.callback(), BoundNetLog());
4639  EXPECT_EQ(ERR_IO_PENDING, rv);
4640
4641  rv = callback.WaitForResult();
4642  EXPECT_EQ(0, rv);
4643
4644  // Verify the SYN_REPLY.
4645  HttpResponseInfo response = *trans->GetResponseInfo();
4646  EXPECT_TRUE(response.headers.get() != NULL);
4647  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
4648
4649  std::string response_data;
4650  ASSERT_EQ(OK, ReadTransaction(trans, &response_data));
4651  EXPECT_EQ("hello!", response_data);
4652  helper.VerifyDataConsumed();
4653}
4654
4655// Test to make sure we can correctly connect through a proxy to www.google.com,
4656// if there already exists a direct spdy connection to www.google.com. See
4657// http://crbug.com/49874
4658TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
4659  // When setting up the first transaction, we store the SpdySessionPool so that
4660  // we can use the same pool in the second transaction.
4661  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4662                                     BoundNetLog(), GetParam(), NULL);
4663
4664  // Use a proxy service which returns a proxy fallback list from DIRECT to
4665  // myproxy:70. For this test there will be no fallback, so it is equivalent
4666  // to simply DIRECT. The reason for appending the second proxy is to verify
4667  // that the session pool key used does is just "DIRECT".
4668  help