spdy_network_transaction_unittest.cc revision dc0f95d653279beabeb9817299e2902918ba123e
172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "net/http/http_network_transaction.h"
672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include <string>
83345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include <vector>
93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
10513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "net/base/auth.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_log_unittest.h"
12731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/http/http_network_session_peer.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_transaction_unittest.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/spdy/spdy_http_stream.h"
1572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "net/spdy/spdy_http_utils.h"
163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/spdy/spdy_session.h"
173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/spdy/spdy_session_pool.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/spdy/spdy_test_util.h"
1972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "net/url_request/url_request_test_util.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "testing/platform_test.h"
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//-----------------------------------------------------------------------------
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace net {
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// This is the expected list of advertised protocols from the browser's NPN
273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// list.
283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic const char kExpectedNPNString[] = "\x08http/1.1\x06spdy/2";
293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickenum SpdyNetworkTransactionTestTypes {
313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SPDYNPN,
323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SPDYNOSSL,
33731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  SPDYSSL,
343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick};
353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass SpdyNetworkTransactionTest
363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    : public ::testing::TestWithParam<SpdyNetworkTransactionTestTypes> {
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected:
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void SetUp() {
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // By default, all tests turn off compression.
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EnableCompression(false);
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    google_get_request_initialized_ = false;
423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    google_post_request_initialized_ = false;
43dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    google_chunked_post_request_initialized_ = false;
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void TearDown() {
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Empty the current queue.
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MessageLoop::current()->RunAllPending();
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct TransactionHelperResult {
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int rv;
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string status_line;
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string response_data;
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HttpResponseInfo response_info;
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void EnableCompression(bool enabled) {
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SpdyFramer::set_enable_compression_default(enabled);
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  class StartTransactionCallback;
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  class DeleteSessionCallback;
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // A helper class that handles all the initial npn/ssl setup.
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  class NormalSpdyTransactionHelper {
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   public:
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NormalSpdyTransactionHelper(const HttpRequestInfo& request,
693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                const BoundNetLog& log,
703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                SpdyNetworkTransactionTestTypes test_type)
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        : request_(request),
723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          session_deps_(new SpdySessionDependencies()),
733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          session_(SpdySessionDependencies::SpdyCreateSession(
743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              session_deps_.get())),
753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          log_(log),
763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          test_type_(test_type),
77731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          deterministic_(false),
78731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          spdy_enabled_(true) {
793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            switch (test_type_) {
803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              case SPDYNOSSL:
813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              case SPDYSSL:
823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                port_ = 80;
833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                break;
843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              case SPDYNPN:
853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                port_ = 443;
863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                break;
873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              default:
883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                NOTREACHED();
893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            }
903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          }
913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ~NormalSpdyTransactionHelper() {
933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // Any test which doesn't close the socket by sending it an EOF will
943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // have a valid session left open, which leaks the entire session pool.
953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // This is just fine - in fact, some of our tests intentionally do this
963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // so that we can check consistency of the SpdySessionPool as the test
973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // finishes.  If we had put an EOF on the socket, the SpdySession would
983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // have closed and we wouldn't be able to check the consistency.
993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // Forcefully close existing sessions here.
1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      session()->spdy_session_pool()->CloseAllSessions();
1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    void SetDeterministic() {
1053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          session_deps_.get());
1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      deterministic_ = true;
1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
110731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    void SetSpdyDisabled() {
111731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      spdy_enabled_ = false;
112731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
113731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    void RunPreTestSetup() {
1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (!session_deps_.get())
1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        session_deps_.reset(new SpdySessionDependencies());
1173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (!session_.get())
1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        session_ = SpdySessionDependencies::SpdyCreateSession(
1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            session_deps_.get());
1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      HttpStreamFactory::set_use_alternate_protocols(false);
1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      HttpStreamFactory::set_force_spdy_over_ssl(false);
1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      HttpStreamFactory::set_force_spdy_always(false);
1233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      switch (test_type_) {
1243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        case SPDYNPN:
1253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          session_->mutable_alternate_protocols()->SetAlternateProtocolFor(
1263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              HostPortPair("www.google.com", 80), 443,
1273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              HttpAlternateProtocols::NPN_SPDY_2);
1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          HttpStreamFactory::set_use_alternate_protocols(true);
1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          HttpStreamFactory::set_next_protos(kExpectedNPNString);
1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          break;
1313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        case SPDYNOSSL:
1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          HttpStreamFactory::set_force_spdy_over_ssl(false);
1333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          HttpStreamFactory::set_force_spdy_always(true);
1343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          break;
1353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        case SPDYSSL:
1363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          HttpStreamFactory::set_force_spdy_over_ssl(true);
1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          HttpStreamFactory::set_force_spdy_always(true);
1383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          break;
1393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        default:
1403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          NOTREACHED();
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // We're now ready to use SSL-npn SPDY.
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      trans_.reset(new HttpNetworkTransaction(session_));
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Start the transaction, read some data, finish.
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void RunDefaultTest() {
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      output_.rv = trans_->Start(&request_, &callback, log_);
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // We expect an IO Pending or some sort of error.
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_LT(output_.rv, 0);
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (output_.rv != ERR_IO_PENDING)
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return;
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      output_.rv = callback.WaitForResult();
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (output_.rv != OK) {
1583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        session_->spdy_session_pool()->CloseCurrentSessions();
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return;
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Verify responses.
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const HttpResponseInfo* response = trans_->GetResponseInfo();
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ASSERT_TRUE(response != NULL);
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ASSERT_TRUE(response->headers != NULL);
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
167731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      EXPECT_EQ(spdy_enabled_, response->was_fetched_via_spdy);
168731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      if (test_type_ == SPDYNPN && spdy_enabled_) {
1693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        EXPECT_TRUE(response->was_npn_negotiated);
1703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        EXPECT_TRUE(response->was_alternate_protocol_available);
1713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      } else {
1723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        EXPECT_TRUE(!response->was_npn_negotiated);
1733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        EXPECT_TRUE(!response->was_alternate_protocol_available);
1743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      }
175731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      // If SPDY is not enabled, a HTTP request should not be diverted
176731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      // over a SSL session.
177731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      if (!spdy_enabled_) {
178731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        EXPECT_EQ(request_.url.SchemeIs("https"),
179731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                  response->was_npn_negotiated);
180731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      }
181dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      EXPECT_EQ("192.0.2.33", response->socket_address.host());
182dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      EXPECT_EQ(0, response->socket_address.port());
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      output_.status_line = response->headers->GetStatusLine();
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      output_.response_info = *response;  // Make a copy so we can verify.
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      output_.rv = ReadTransaction(trans_.get(), &output_.response_data);
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Most tests will want to call this function. In particular, the MockReads
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // should end with an empty read, and that read needs to be processed to
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // ensure proper deletion of the spdy_session_pool.
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void VerifyDataConsumed() {
1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      for (DataVector::iterator it = data_vector_.begin();
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          it != data_vector_.end(); ++it) {
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        EXPECT_TRUE((*it)->at_read_eof()) << "Read count: "
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          << (*it)->read_count()
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          << " Read index: "
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          << (*it)->read_index();
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        EXPECT_TRUE((*it)->at_write_eof()) << "Write count: "
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           << (*it)->write_count()
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           << " Write index: "
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           << (*it)->write_index();
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Occasionally a test will expect to error out before certain reads are
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // processed. In that case we want to explicitly ensure that the reads were
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // not processed.
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void VerifyDataNotConsumed() {
2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      for (DataVector::iterator it = data_vector_.begin();
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          it != data_vector_.end(); ++it) {
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        EXPECT_TRUE(!(*it)->at_read_eof()) << "Read count: "
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           << (*it)->read_count()
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           << " Read index: "
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           << (*it)->read_index();
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        EXPECT_TRUE(!(*it)->at_write_eof()) << "Write count: "
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                            << (*it)->write_count()
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                            << " Write index: "
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                            << (*it)->write_index();
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void RunToCompletion(StaticSocketDataProvider* data) {
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      RunPreTestSetup();
2243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      AddData(data);
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      RunDefaultTest();
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      VerifyDataConsumed();
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void AddData(StaticSocketDataProvider* data) {
2303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      DCHECK(!deterministic_);
2313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      data_vector_.push_back(data);
2323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      linked_ptr<SSLSocketDataProvider> ssl_(
2333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          new SSLSocketDataProvider(true, OK));
2343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (test_type_ == SPDYNPN) {
2353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        ssl_->next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        ssl_->next_proto = "spdy/2";
2373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        ssl_->was_npn_negotiated = true;
2383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      }
2393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ssl_vector_.push_back(ssl_);
2403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if(test_type_ == SPDYNPN || test_type_ == SPDYSSL)
2413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        session_deps_->socket_factory->AddSSLSocketDataProvider(ssl_.get());
2423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      session_deps_->socket_factory->AddSocketDataProvider(data);
2433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
2443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    void AddDeterministicData(DeterministicSocketData* data) {
2463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      DCHECK(deterministic_);
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      data_vector_.push_back(data);
2483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      linked_ptr<SSLSocketDataProvider> ssl_(
2493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          new SSLSocketDataProvider(true, OK));
2503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (test_type_ == SPDYNPN) {
2513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        ssl_->next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        ssl_->next_proto = "spdy/2";
2533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        ssl_->was_npn_negotiated = true;
2543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      }
2553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ssl_vector_.push_back(ssl_);
2563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if(test_type_ == SPDYNPN || test_type_ == SPDYSSL)
2573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        session_deps_->deterministic_socket_factory->
2583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            AddSSLSocketDataProvider(ssl_.get());
2593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      session_deps_->deterministic_socket_factory->AddSocketDataProvider(data);
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // This can only be called after RunPreTestSetup. It adds a Data Provider,
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // but not a corresponding SSL data provider
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void AddDataNoSSL(StaticSocketDataProvider* data) {
2653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      DCHECK(!deterministic_);
2663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      session_deps_->socket_factory->AddSocketDataProvider(data);
2673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
2683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    void AddDataNoSSL(DeterministicSocketData* data) {
2693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      DCHECK(deterministic_);
2703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      session_deps_->deterministic_socket_factory->AddSocketDataProvider(data);
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    void SetSession(const scoped_refptr<HttpNetworkSession>& session) {
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      session_ = session;
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HttpNetworkTransaction* trans() { return trans_.get(); }
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void ResetTrans() { trans_.reset(); }
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TransactionHelperResult& output() { return output_; }
2793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const HttpRequestInfo& request() const { return request_; }
2803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const scoped_refptr<HttpNetworkSession>& session() const {
2813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return session_;
2823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
2833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    scoped_ptr<SpdySessionDependencies>& session_deps() {
2843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return session_deps_;
2853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
2863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    int port() const { return port_; }
2873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    SpdyNetworkTransactionTestTypes test_type() const { return test_type_; }
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   private:
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    typedef std::vector<StaticSocketDataProvider*> DataVector;
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    typedef std::vector<linked_ptr<SSLSocketDataProvider> > SSLVector;
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HttpRequestInfo request_;
2933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    scoped_ptr<SpdySessionDependencies> session_deps_;
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_refptr<HttpNetworkSession> session_;
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TransactionHelperResult output_;
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<StaticSocketDataProvider> first_transaction_;
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SSLVector ssl_vector_;
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TestCompletionCallback callback;
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<HttpNetworkTransaction> trans_;
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<HttpNetworkTransaction> trans_http_;
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DataVector data_vector_;
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BoundNetLog& log_;
3033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    SpdyNetworkTransactionTestTypes test_type_;
3043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    int port_;
3053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    bool deterministic_;
306731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    bool spdy_enabled_;
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                             int expected_status);
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void ConnectStatusHelper(const MockRead& status);
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HttpRequestInfo& CreateGetPushRequest() {
3153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    google_get_push_request_.method = "GET";
3163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    google_get_push_request_.url = GURL("http://www.google.com/foo.dat");
3173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    google_get_push_request_.load_flags = 0;
3183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return google_get_push_request_;
3193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
3203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const HttpRequestInfo& CreateGetRequest() {
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!google_get_request_initialized_) {
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      google_get_request_.method = "GET";
3243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      google_get_request_.url = GURL(kDefaultURL);
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      google_get_request_.load_flags = 0;
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      google_get_request_initialized_ = true;
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return google_get_request_;
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  const HttpRequestInfo& CreateGetRequestWithUserAgent() {
3324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    if (!google_get_request_initialized_) {
3334a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      google_get_request_.method = "GET";
3344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      google_get_request_.url = GURL(kDefaultURL);
3354a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      google_get_request_.load_flags = 0;
3364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      google_get_request_.extra_headers.SetHeader("User-Agent", "Chrome");
3374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      google_get_request_initialized_ = true;
3384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    }
3394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    return google_get_request_;
3404a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
3414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
3423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HttpRequestInfo& CreatePostRequest() {
3433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (!google_post_request_initialized_) {
3443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      google_post_request_.method = "POST";
3453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      google_post_request_.url = GURL(kDefaultURL);
3463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      google_post_request_.upload_data = new UploadData();
3473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      google_post_request_.upload_data->AppendBytes(kUploadData,
3483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                    kUploadDataSize);
3493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      google_post_request_initialized_ = true;
3503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
3513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return google_post_request_;
3523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
3533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
354dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const HttpRequestInfo& CreateChunkedPostRequest() {
355dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (!google_chunked_post_request_initialized_) {
356dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      google_chunked_post_request_.method = "POST";
357dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      google_chunked_post_request_.url = GURL(kDefaultURL);
358dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      google_chunked_post_request_.upload_data = new UploadData();
359dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      google_chunked_post_request_.upload_data->set_is_chunked(true);
360dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      google_chunked_post_request_.upload_data->AppendChunk(
361dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          kUploadData, kUploadDataSize, false);
362dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      google_chunked_post_request_.upload_data->AppendChunk(
363dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          kUploadData, kUploadDataSize, true);
364dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      google_chunked_post_request_initialized_ = true;
365dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
366dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return google_chunked_post_request_;
367dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
368dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
3693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Read the result of a particular transaction, knowing that we've got
3703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // multiple transactions in the read pipeline; so as we read, we may have
3713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // to skip over data destined for other transactions while we consume
3723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // the data for |trans|.
3733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int ReadResult(HttpNetworkTransaction* trans,
374201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                 StaticSocketDataProvider* data,
3753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                 std::string* result) {
3763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const int kSize = 3000;
3773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    int bytes_read = 0;
379513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(kSize));
3803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    TestCompletionCallback callback;
3813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    while (true) {
3823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      int rv = trans->Read(buf, kSize, &callback);
3833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (rv == ERR_IO_PENDING) {
3843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        // Multiple transactions may be in the data set.  Keep pulling off
3853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        // reads until we complete our callback.
3863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        while (!callback.have_result()) {
3873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          data->CompleteRead();
3883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          MessageLoop::current()->RunAllPending();
3893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        }
3903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        rv = callback.WaitForResult();
3913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      } else if (rv <= 0) {
3923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        break;
3933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      }
3943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      result->append(buf->data(), rv);
3953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      bytes_read += rv;
3963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
3973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return bytes_read;
3983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
3993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void VerifyStreamsClosed(const NormalSpdyTransactionHelper& helper) {
4013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // This lengthy block is reaching into the pool to dig out the active
4023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // session.  Once we have the session, we verify that the streams are
4033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // all closed and not leaked at this point.
4043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const GURL& url = helper.request().url;
4053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    int port = helper.test_type() == SPDYNPN ? 443 : 80;
4063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    HostPortPair host_port_pair(url.host(), port);
4073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
4083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    BoundNetLog log;
4093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const scoped_refptr<HttpNetworkSession>& session = helper.session();
410731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    SpdySessionPool* pool(session->spdy_session_pool());
4113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_TRUE(pool->HasSession(pair));
412dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    scoped_refptr<SpdySession> spdy_session(pool->Get(pair, log));
4133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ASSERT_TRUE(spdy_session.get() != NULL);
4143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(0u, spdy_session->num_active_streams());
4153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams());
4163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
4173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
418201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  void RunServerPushTest(OrderedSocketData* data,
4193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                         HttpResponseInfo* response,
420201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                         HttpResponseInfo* push_response,
4213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                         std::string& expected) {
4223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    NormalSpdyTransactionHelper helper(CreateGetRequest(),
4233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                       BoundNetLog(), GetParam());
4243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    helper.RunPreTestSetup();
425201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    helper.AddData(data);
4263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    HttpNetworkTransaction* trans = helper.trans();
4283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Start the transaction with basic parameters.
4303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    TestCompletionCallback callback;
4313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
4323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(ERR_IO_PENDING, rv);
4333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    rv = callback.WaitForResult();
4343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Request the pushed path.
4363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    scoped_ptr<HttpNetworkTransaction> trans2(
4373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        new HttpNetworkTransaction(helper.session()));
4383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    rv = trans2->Start(&CreateGetPushRequest(), &callback, BoundNetLog());
4393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(ERR_IO_PENDING, rv);
4403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MessageLoop::current()->RunAllPending();
4413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // The data for the pushed path may be coming in more than 1 packet. Compile
4433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // the results into a single string.
4443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Read the server push body.
4463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    std::string result2;
4473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ReadResult(trans2.get(), data, &result2);
4483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Read the response body.
4493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    std::string result;
4503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ReadResult(trans, data, &result);
4513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Verify that we consumed all test data.
4533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_TRUE(data->at_read_eof());
4543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_TRUE(data->at_write_eof());
4553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Verify that the received push data is same as the expected push data.
4573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(result2.compare(expected), 0) << "Received data: "
4583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                            << result2
4593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                            << "||||| Expected data: "
4603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                            << expected;
4613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Verify the SYN_REPLY.
4633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Copy the response info, because trans goes away.
4643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    *response = *trans->GetResponseInfo();
465201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    *push_response = *trans2->GetResponseInfo();
4663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    VerifyStreamsClosed(helper);
4683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
4693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool google_get_request_initialized_;
4723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool google_post_request_initialized_;
473dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  bool google_chunked_post_request_initialized_;
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpRequestInfo google_get_request_;
4753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo google_post_request_;
476dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  HttpRequestInfo google_chunked_post_request_;
4773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo google_get_push_request_;
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//-----------------------------------------------------------------------------
4813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// All tests are run with three different connection types: SPDY after NPN
4823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// negotiation, SPDY without SSL, and SPDY with SSL.
4833345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickINSTANTIATE_TEST_CASE_P(Spdy,
4843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        SpdyNetworkTransactionTest,
4853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        ::testing::Values(SPDYNOSSL, SPDYSSL, SPDYNPN));
4863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Verify HttpNetworkTransaction constructor.
4893345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, Constructor) {
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SpdySessionDependencies session_deps;
491513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_refptr<HttpNetworkSession> session(
492513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      SpdySessionDependencies::SpdyCreateSession(&session_deps));
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4963345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, Get) {
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Construct the request.
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
5133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunToCompletion(data.get());
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("hello!", out.response_data);
519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5213345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) {
5223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (RequestPriority p = HIGHEST; p < NUM_PRIORITIES;
5233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       p = RequestPriority(p+1)) {
5243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Construct the request.
5253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, p));
5263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockWrite writes[] = { CreateMockWrite(*req) };
5273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
5283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const int spdy_prio = reinterpret_cast<spdy::SpdySynStreamControlFrame*>(
5293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        req.get())->priority();
5303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // this repeats the RequestPriority-->SpdyPriority mapping from
5313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
5323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // sure it's being done right.
5333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    switch(p) {
5343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      case HIGHEST:
5353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        EXPECT_EQ(0, spdy_prio);
5363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        break;
5373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      case MEDIUM:
5383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        EXPECT_EQ(1, spdy_prio);
5393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        break;
5403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      case LOW:
5413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      case LOWEST:
5423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        EXPECT_EQ(2, spdy_prio);
5433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        break;
5443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      case IDLE:
5453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        EXPECT_EQ(3, spdy_prio);
5463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        break;
5473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      default:
5483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        FAIL();
5493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
5503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
5513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
5523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
5533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead reads[] = {
5543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      CreateMockRead(*resp),
5553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      CreateMockRead(*body),
5563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      MockRead(true, 0, 0)  // EOF
5573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    };
5583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
5593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    scoped_refptr<DelayedSocketData> data(
5603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        new DelayedSocketData(1, reads, arraysize(reads),
5613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                              writes, arraysize(writes)));
5623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    HttpRequestInfo http_req = CreateGetRequest();
5633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    http_req.priority = p;
5643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
5653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    NormalSpdyTransactionHelper helper(http_req, BoundNetLog(), GetParam());
5663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    helper.RunToCompletion(data.get());
5673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    TransactionHelperResult out = helper.output();
5683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(OK, out.rv);
5693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
5703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ("hello!", out.response_data);
5713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
5723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
5733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Start three gets simultaniously; making sure that multiplexed
575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// streams work properly.
576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This can't use the TransactionHelper method, since it only
578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// handles a single transaction, and finishes them as soon
579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// as it launches them.
580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(gavinp): create a working generalized TransactionHelper that
582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// can allow multiple streams in flight.
583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5843345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ThreeGets) {
585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req3(ConstructSpdyGet(NULL, 0, false, 5, LOWEST));
596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 5));
597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body3(ConstructSpdyBodyFrame(5, false));
598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> fbody3(ConstructSpdyBodyFrame(5, true));
599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
600dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MockWrite writes[] = {
601dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockWrite(*req),
602dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockWrite(*req2),
603dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockWrite(*req3),
604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp, 1),
607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp2, 4),
609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body2),
610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp3, 7),
611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body3),
612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*fbody),
614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*fbody2),
615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*fbody3),
616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0),  // EOF
618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<OrderedSocketData> data(
620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new OrderedSocketData(reads, arraysize(reads),
621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
6223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data_placeholder(
6233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(NULL, 0, NULL, 0));
624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BoundNetLog log;
626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out;
6273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
6283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
6293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
6303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
6313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // We require placeholder data because three get requests are sent out, so
6323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // there needs to be three sets of SSL connection data.
6333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data_placeholder.get());
6343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data_placeholder.get());
6353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<HttpNetworkTransaction> trans1(
6363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new HttpNetworkTransaction(helper.session()));
6373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<HttpNetworkTransaction> trans2(
6383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new HttpNetworkTransaction(helper.session()));
6393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<HttpNetworkTransaction> trans3(
6403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new HttpNetworkTransaction(helper.session()));
6413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback1;
6433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback2;
6443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback3;
6453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo httpreq1 = CreateGetRequest();
6473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo httpreq2 = CreateGetRequest();
6483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo httpreq3 = CreateGetRequest();
6493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans1->Start(&httpreq1, &callback1, log);
6513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(ERR_IO_PENDING, out.rv);
6523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans2->Start(&httpreq2, &callback2, log);
6533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(ERR_IO_PENDING, out.rv);
6543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans3->Start(&httpreq3, &callback3, log);
6553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(ERR_IO_PENDING, out.rv);
6563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = callback1.WaitForResult();
6583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(OK, out.rv);
6593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = callback3.WaitForResult();
6603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(OK, out.rv);
6613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
6633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response1->headers != NULL);
6643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response1->was_fetched_via_spdy);
6653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.status_line = response1->headers->GetStatusLine();
6663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.response_info = *response1;
6673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  trans2->GetResponseInfo();
6693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = ReadTransaction(trans1.get(), &out.response_data);
6713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("hello!hello!", out.response_data);
677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
679dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST_P(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
680dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
681dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
682dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
683dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
684dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
685dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
686dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
687dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
688dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
689dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
690dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MockWrite writes[] = {
691dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockWrite(*req),
692dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockWrite(*req2),
693dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  };
694dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MockRead reads[] = {
695dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*resp, 1),
696dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*body),
697dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*resp2, 4),
698dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*body2),
699dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*fbody),
700dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*fbody2),
701dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    MockRead(true, 0, 0),  // EOF
702dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  };
703dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_refptr<OrderedSocketData> data(
704dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      new OrderedSocketData(reads, arraysize(reads),
705dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                            writes, arraysize(writes)));
706dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
707dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MockConnect never_finishing_connect(true, ERR_IO_PENDING);
708dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
709dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_refptr<OrderedSocketData> data_placeholder(
710dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      new OrderedSocketData(NULL, 0, NULL, 0));
711dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  data_placeholder->set_connect_data(never_finishing_connect);
712dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
713dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  BoundNetLog log;
714dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  TransactionHelperResult out;
715dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  NormalSpdyTransactionHelper helper(CreateGetRequest(),
716dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                     BoundNetLog(), GetParam());
717dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  helper.RunPreTestSetup();
718dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  helper.AddData(data.get());
719dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // We require placeholder data because two get requests are sent out, so
720dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // there needs to be two sets of SSL connection data.
721dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  helper.AddData(data_placeholder.get());
722dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<HttpNetworkTransaction> trans1(
723dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      new HttpNetworkTransaction(helper.session()));
724dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<HttpNetworkTransaction> trans2(
725dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      new HttpNetworkTransaction(helper.session()));
726dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
727dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  TestCompletionCallback callback1;
728dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  TestCompletionCallback callback2;
729dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
730dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  HttpRequestInfo httpreq1 = CreateGetRequest();
731dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  HttpRequestInfo httpreq2 = CreateGetRequest();
732dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
733dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.rv = trans1->Start(&httpreq1, &callback1, log);
734dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ASSERT_EQ(ERR_IO_PENDING, out.rv);
735dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.rv = trans2->Start(&httpreq2, &callback2, log);
736dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ASSERT_EQ(ERR_IO_PENDING, out.rv);
737dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
738dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.rv = callback1.WaitForResult();
739dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ASSERT_EQ(OK, out.rv);
740dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.rv = callback2.WaitForResult();
741dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ASSERT_EQ(OK, out.rv);
742dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
743dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
744dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(response1->headers != NULL);
745dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(response1->was_fetched_via_spdy);
746dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.status_line = response1->headers->GetStatusLine();
747dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.response_info = *response1;
748dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.rv = ReadTransaction(trans1.get(), &out.response_data);
749dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(OK, out.rv);
750dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
751dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ("hello!hello!", out.response_data);
752dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
753dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
754dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(response2->headers != NULL);
755dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(response2->was_fetched_via_spdy);
756dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.status_line = response2->headers->GetStatusLine();
757dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.response_info = *response2;
758dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.rv = ReadTransaction(trans2.get(), &out.response_data);
759dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(OK, out.rv);
760dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
761dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ("hello!hello!", out.response_data);
762dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
763dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  helper.VerifyDataConsumed();
764dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
765dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
766dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST_P(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
767dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
768dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
769dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
770dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
771dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
772dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
773dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
774dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
775dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
776dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
777dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MockWrite writes[] = {
778dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockWrite(*req),
779dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockWrite(*req2),
780dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  };
781dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MockRead reads[] = {
782dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*resp, 1),
783dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*body),
784dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*resp2, 4),
785dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*body2),
786dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*fbody),
787dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*fbody2),
788dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    MockRead(true, 0, 0),  // EOF
789dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  };
790dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_refptr<OrderedSocketData> preconnect_data(
791dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      new OrderedSocketData(reads, arraysize(reads),
792dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                            writes, arraysize(writes)));
793dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
794dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MockConnect never_finishing_connect(true, ERR_IO_PENDING);
795dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
796dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_refptr<OrderedSocketData> data_placeholder(
797dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      new OrderedSocketData(NULL, 0, NULL, 0));
798dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  data_placeholder->set_connect_data(never_finishing_connect);
799dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
800dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  BoundNetLog log;
801dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  TransactionHelperResult out;
802dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  NormalSpdyTransactionHelper helper(CreateGetRequest(),
803dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                     BoundNetLog(), GetParam());
804dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  helper.RunPreTestSetup();
805dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  helper.AddData(preconnect_data.get());
806dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // We require placeholder data because 3 connections are attempted (first is
807dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // the preconnect, 2nd and 3rd are the never finished connections.
808dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  helper.AddData(data_placeholder.get());
809dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  helper.AddData(data_placeholder.get());
810dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
811dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<HttpNetworkTransaction> trans1(
812dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      new HttpNetworkTransaction(helper.session()));
813dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<HttpNetworkTransaction> trans2(
814dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      new HttpNetworkTransaction(helper.session()));
815dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
816dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  TestCompletionCallback callback1;
817dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  TestCompletionCallback callback2;
818dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
819dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  HttpRequestInfo httpreq = CreateGetRequest();
820dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
821dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Preconnect the first.
822dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SSLConfig preconnect_ssl_config;
823dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  helper.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config);
824dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  HttpStreamFactory* http_stream_factory =
825dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      helper.session()->http_stream_factory();
826dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (http_stream_factory->next_protos()) {
827dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    preconnect_ssl_config.next_protos = *http_stream_factory->next_protos();
828dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
829dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
830dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  http_stream_factory->PreconnectStreams(
831dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      1, httpreq, preconnect_ssl_config, log);
832dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
833dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.rv = trans1->Start(&httpreq, &callback1, log);
834dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ASSERT_EQ(ERR_IO_PENDING, out.rv);
835dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.rv = trans2->Start(&httpreq, &callback2, log);
836dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ASSERT_EQ(ERR_IO_PENDING, out.rv);
837dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
838dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.rv = callback1.WaitForResult();
839dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ASSERT_EQ(OK, out.rv);
840dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.rv = callback2.WaitForResult();
841dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ASSERT_EQ(OK, out.rv);
842dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
843dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
844dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(response1->headers != NULL);
845dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(response1->was_fetched_via_spdy);
846dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.status_line = response1->headers->GetStatusLine();
847dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.response_info = *response1;
848dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.rv = ReadTransaction(trans1.get(), &out.response_data);
849dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(OK, out.rv);
850dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
851dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ("hello!hello!", out.response_data);
852dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
853dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
854dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(response2->headers != NULL);
855dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(response2->was_fetched_via_spdy);
856dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.status_line = response2->headers->GetStatusLine();
857dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.response_info = *response2;
858dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.rv = ReadTransaction(trans2.get(), &out.response_data);
859dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(OK, out.rv);
860dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
861dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ("hello!hello!", out.response_data);
862dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
863dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  helper.VerifyDataConsumed();
864dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
865dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Similar to ThreeGets above, however this test adds a SETTINGS
867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// frame.  The SETTINGS frame is read during the IO loop waiting on
868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the first transaction completion, and sets a maximum concurrent
869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// stream limit of 1.  This means that our IO loop exists after the
870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// second transaction completes, so we can assert on read_index().
8713345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
872c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Construct the request.
873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req3(ConstructSpdyGet(NULL, 0, false, 5, LOWEST));
884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 5));
885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body3(ConstructSpdyBodyFrame(5, false));
886c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> fbody3(ConstructSpdyBodyFrame(5, true));
887c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdySettings settings;
889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SettingsFlagsAndId id(0);
890c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  id.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS);
891c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const size_t max_concurrent_streams = 1;
892c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
893c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  settings.push_back(spdy::SpdySetting(id, max_concurrent_streams));
894c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
896c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req),
897c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         CreateMockWrite(*req2),
898c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         CreateMockWrite(*req3),
899c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
9013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*settings_frame, 1),
902c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
903c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*fbody),
9053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp2, 7),
906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body2),
907c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*fbody2),
9083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp3, 12),
909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body3),
910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*fbody3),
911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0),  // EOF
913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<OrderedSocketData> data(
916c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new OrderedSocketData(reads, arraysize(reads),
917c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
9183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data_placeholder(
9193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(NULL, 0, NULL, 0));
920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BoundNetLog log;
922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out;
923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
9243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
9253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
9263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
9273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
9283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // We require placeholder data because three get requests are sent out, so
9293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // there needs to be three sets of SSL connection data.
9303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data_placeholder.get());
9313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data_placeholder.get());
9323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    scoped_ptr<HttpNetworkTransaction> trans1(
9333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        new HttpNetworkTransaction(helper.session()));
9343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    scoped_ptr<HttpNetworkTransaction> trans2(
9353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        new HttpNetworkTransaction(helper.session()));
9363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    scoped_ptr<HttpNetworkTransaction> trans3(
9373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        new HttpNetworkTransaction(helper.session()));
938c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
939c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TestCompletionCallback callback1;
940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TestCompletionCallback callback2;
941c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TestCompletionCallback callback3;
942c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
943c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HttpRequestInfo httpreq1 = CreateGetRequest();
944c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HttpRequestInfo httpreq2 = CreateGetRequest();
945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HttpRequestInfo httpreq3 = CreateGetRequest();
946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.rv = trans1->Start(&httpreq1, &callback1, log);
948c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ASSERT_EQ(out.rv, ERR_IO_PENDING);
949c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // run transaction 1 through quickly to force a read of our SETTINGS
950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // frame
951c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.rv = callback1.WaitForResult();
9523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ASSERT_EQ(OK, out.rv);
953c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
954c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.rv = trans2->Start(&httpreq2, &callback2, log);
955c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ASSERT_EQ(out.rv, ERR_IO_PENDING);
956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.rv = trans3->Start(&httpreq3, &callback3, log);
957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ASSERT_EQ(out.rv, ERR_IO_PENDING);
958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.rv = callback2.WaitForResult();
959c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ASSERT_EQ(OK, out.rv);
960c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(7U, data->read_index());  // i.e. the third trans was queued
961c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
962c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.rv = callback3.WaitForResult();
963c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ASSERT_EQ(OK, out.rv);
964c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
965c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const HttpResponseInfo* response1 = trans1->GetResponseInfo();
9663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ASSERT_TRUE(response1 != NULL);
967c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(response1->headers != NULL);
968c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(response1->was_fetched_via_spdy);
969c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.status_line = response1->headers->GetStatusLine();
970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.response_info = *response1;
971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.rv = ReadTransaction(trans1.get(), &out.response_data);
972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(OK, out.rv);
973c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ("hello!hello!", out.response_data);
975c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const HttpResponseInfo* response2 = trans2->GetResponseInfo();
977c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.status_line = response2->headers->GetStatusLine();
978c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.response_info = *response2;
979c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.rv = ReadTransaction(trans2.get(), &out.response_data);
980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(OK, out.rv);
981c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ("hello!hello!", out.response_data);
983c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const HttpResponseInfo* response3 = trans3->GetResponseInfo();
985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.status_line = response3->headers->GetStatusLine();
986c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.response_info = *response3;
987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.rv = ReadTransaction(trans3.get(), &out.response_data);
988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(OK, out.rv);
989c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
990c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ("hello!hello!", out.response_data);
9913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
9923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    helper.VerifyDataConsumed();
993c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
996c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
997c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Similar to ThreeGetsWithMaxConcurrent above, however this test adds
998c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// a fourth transaction.  The third and fourth transactions have
999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// different data ("hello!" vs "hello!hello!") and because of the
1000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// user specified priority, we expect to see them inverted in
1001c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the response from the server.
10023345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
1003c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Construct the request.
1004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
1007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
1008c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1009c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
1010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
1011c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
1012c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
1013c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1014c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req4(
1015c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ConstructSpdyGet(NULL, 0, false, 5, HIGHEST));
1016c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp4(ConstructSpdyGetSynReply(NULL, 0, 5));
1017c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> fbody4(ConstructSpdyBodyFrame(5, true));
1018c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1019c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req3(ConstructSpdyGet(NULL, 0, false, 7, LOWEST));
1020c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 7));
1021c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body3(ConstructSpdyBodyFrame(7, false));
1022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> fbody3(ConstructSpdyBodyFrame(7, true));
1023c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1024c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1025c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdySettings settings;
1026c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SettingsFlagsAndId id(0);
1027c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  id.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS);
1028c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const size_t max_concurrent_streams = 1;
1029c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1030c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  settings.push_back(spdy::SpdySetting(id, max_concurrent_streams));
1031c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
1032c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1033c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req),
10343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req2),
10353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req4),
10363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req3),
1037c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
1038c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
10393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*settings_frame, 1),
1040c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
1041c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
1042c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*fbody),
10433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp2, 7),
1044c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body2),
1045c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*fbody2),
10463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp4, 13),
1047c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*fbody4),
10483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp3, 16),
1049c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body3),
1050c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*fbody3),
1051c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1052c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0),  // EOF
1053c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
1054c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1055c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<OrderedSocketData> data(
1056c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new OrderedSocketData(reads, arraysize(reads),
10573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        writes, arraysize(writes)));
10583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data_placeholder(
10593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(NULL, 0, NULL, 0));
1060c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1061c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BoundNetLog log;
1062c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out;
10633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
10643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      BoundNetLog(), GetParam());
10653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
10663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
10673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // We require placeholder data because four get requests are sent out, so
10683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // there needs to be four sets of SSL connection data.
10693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data_placeholder.get());
10703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data_placeholder.get());
10713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data_placeholder.get());
10723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<HttpNetworkTransaction> trans1(
10733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new HttpNetworkTransaction(helper.session()));
10743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<HttpNetworkTransaction> trans2(
10753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new HttpNetworkTransaction(helper.session()));
10763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<HttpNetworkTransaction> trans3(
10773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new HttpNetworkTransaction(helper.session()));
10783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<HttpNetworkTransaction> trans4(
10793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new HttpNetworkTransaction(helper.session()));
10803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
10813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback1;
10823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback2;
10833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback3;
10843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback4;
10853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
10863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo httpreq1 = CreateGetRequest();
10873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo httpreq2 = CreateGetRequest();
10883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo httpreq3 = CreateGetRequest();
10893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo httpreq4 = CreateGetRequest();
10903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  httpreq4.priority = HIGHEST;
10913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
10923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans1->Start(&httpreq1, &callback1, log);
10933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(ERR_IO_PENDING, out.rv);
10943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // run transaction 1 through quickly to force a read of our SETTINGS
10953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // frame
10963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = callback1.WaitForResult();
10973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(OK, out.rv);
10983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
10993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans2->Start(&httpreq2, &callback2, log);
11003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(ERR_IO_PENDING, out.rv);
11013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans3->Start(&httpreq3, &callback3, log);
11023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(ERR_IO_PENDING, out.rv);
11033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans4->Start(&httpreq4, &callback4, log);
11043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(ERR_IO_PENDING, out.rv);
11053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
11063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = callback2.WaitForResult();
11073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(OK, out.rv);
11083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(data->read_index(), 7U);  // i.e. the third & fourth trans queued
11093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
11103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = callback3.WaitForResult();
11113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(OK, out.rv);
11123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
11133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
11143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response1->headers != NULL);
11153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response1->was_fetched_via_spdy);
11163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.status_line = response1->headers->GetStatusLine();
11173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.response_info = *response1;
11183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = ReadTransaction(trans1.get(), &out.response_data);
11193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, out.rv);
11203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
11213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("hello!hello!", out.response_data);
1122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
11233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
11243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.status_line = response2->headers->GetStatusLine();
11253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.response_info = *response2;
11263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = ReadTransaction(trans2.get(), &out.response_data);
11273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, out.rv);
11283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
11293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("hello!hello!", out.response_data);
1130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
11313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // notice: response3 gets two hellos, response4 gets one
11323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // hello, so we know dequeuing priority was respected.
11333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HttpResponseInfo* response3 = trans3->GetResponseInfo();
11343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.status_line = response3->headers->GetStatusLine();
11353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.response_info = *response3;
11363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = ReadTransaction(trans3.get(), &out.response_data);
1137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
11383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
11393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("hello!hello!", out.response_data);
1140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
11413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = callback4.WaitForResult();
11423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, out.rv);
11433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HttpResponseInfo* response4 = trans4->GetResponseInfo();
11443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.status_line = response4->headers->GetStatusLine();
11453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.response_info = *response4;
11463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = ReadTransaction(trans4.get(), &out.response_data);
11473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, out.rv);
11483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
11493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("hello!", out.response_data);
11503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
11513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, out.rv);
1152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Similar to ThreeGetsMaxConcurrrent above, however, this test
1155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// deletes a session in the middle of the transaction to insure
1156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// that we properly remove pendingcreatestream objects from
1157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the spdy_session
11583345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
1159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Construct the request.
1160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
1163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
1164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
1166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
1167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
1168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
1169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdySettings settings;
1171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SettingsFlagsAndId id(0);
1172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  id.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS);
1173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const size_t max_concurrent_streams = 1;
1174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  settings.push_back(spdy::SpdySetting(id, max_concurrent_streams));
1176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
1177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req),
11793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req2),
1180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
1181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
11823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*settings_frame, 1),
1183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
1184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
1185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*fbody),
11863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp2, 7),
1187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body2),
1188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*fbody2),
1189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0),  // EOF
1190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
1191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<OrderedSocketData> data(
1193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new OrderedSocketData(reads, arraysize(reads),
11943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        writes, arraysize(writes)));
11953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data_placeholder(
11963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(NULL, 0, NULL, 0));
1197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BoundNetLog log;
1199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out;
12003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
12013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      BoundNetLog(), GetParam());
12023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
12033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
12043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // We require placeholder data because three get requests are sent out, so
12053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // there needs to be three sets of SSL connection data.
12063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data_placeholder.get());
12073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data_placeholder.get());
12083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<HttpNetworkTransaction> trans1(
12093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new HttpNetworkTransaction(helper.session()));
12103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<HttpNetworkTransaction> trans2(
12113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new HttpNetworkTransaction(helper.session()));
12123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<HttpNetworkTransaction> trans3(
12133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new HttpNetworkTransaction(helper.session()));
12143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
12153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback1;
12163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback2;
12173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback3;
12183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
12193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo httpreq1 = CreateGetRequest();
12203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo httpreq2 = CreateGetRequest();
12213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo httpreq3 = CreateGetRequest();
12223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
12233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans1->Start(&httpreq1, &callback1, log);
12243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(out.rv, ERR_IO_PENDING);
12253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // run transaction 1 through quickly to force a read of our SETTINGS
12263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // frame
12273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = callback1.WaitForResult();
12283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(OK, out.rv);
12293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
12303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans2->Start(&httpreq2, &callback2, log);
12313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(out.rv, ERR_IO_PENDING);
12323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans3->Start(&httpreq3, &callback3, log);
12333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  delete trans3.release();
12343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(out.rv, ERR_IO_PENDING);
12353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = callback2.WaitForResult();
12363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(OK, out.rv);
12373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
12383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(8U, data->read_index());
12393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
12403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
12413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(response1 != NULL);
12423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response1->headers != NULL);
12433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response1->was_fetched_via_spdy);
12443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.status_line = response1->headers->GetStatusLine();
12453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.response_info = *response1;
12463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = ReadTransaction(trans1.get(), &out.response_data);
12473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, out.rv);
12483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
12493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("hello!hello!", out.response_data);
1250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
12513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
12523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(response2 != NULL);
12533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.status_line = response2->headers->GetStatusLine();
12543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.response_info = *response2;
12553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = ReadTransaction(trans2.get(), &out.response_data);
12563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, out.rv);
12573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
12583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("hello!hello!", out.response_data);
12593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
12603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, out.rv);
12613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
12633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// The KillerCallback will delete the transaction on error as part of the
12643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// callback.
12653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass KillerCallback : public TestCompletionCallback {
12663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick public:
12673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  explicit KillerCallback(HttpNetworkTransaction* transaction)
12683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      : transaction_(transaction) {}
1269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
12703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual void RunWithParams(const Tuple1<int>& params) {
12713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (params.a < 0)
12723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      delete transaction_;
12733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    TestCompletionCallback::RunWithParams(params);
12743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
12763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick private:
12773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* transaction_;
12783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick};
1279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
12803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
12813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// closes the socket while we have a pending transaction waiting for
12823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// a pending stream creation.  http://crbug.com/52901
12833345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
12843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Construct the request.
12853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
12863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
12873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
12883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> fin_body(ConstructSpdyBodyFrame(1, true));
1289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
12903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
12913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
12923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
12933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  spdy::SpdySettings settings;
12943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  spdy::SettingsFlagsAndId id(0);
12953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  id.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS);
12963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const size_t max_concurrent_streams = 1;
12973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
12983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  settings.push_back(spdy::SpdySetting(id, max_concurrent_streams));
12993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
13003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
13013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = { CreateMockWrite(*req),
13023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req2),
13033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
13043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
13053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*settings_frame, 1),
13063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp),
13073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body),
13083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*fin_body),
13093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp2, 7),
13103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_CONNECTION_RESET, 0),  // Abort!
13113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
13123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
13133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data(
13143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(reads, arraysize(reads),
13153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        writes, arraysize(writes)));
13163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data_placeholder(
13173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(NULL, 0, NULL, 0));
13183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
13193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  BoundNetLog log;
13203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TransactionHelperResult out;
13213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
13223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      BoundNetLog(), GetParam());
13233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
13243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
13253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // We require placeholder data because three get requests are sent out, so
13263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // there needs to be three sets of SSL connection data.
13273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data_placeholder.get());
13283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data_placeholder.get());
13293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction trans1(helper.session());
13303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction trans2(helper.session());
13313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans3(new HttpNetworkTransaction(helper.session()));
13323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
13333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback1;
13343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback2;
13353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  KillerCallback callback3(trans3);
13363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
13373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo httpreq1 = CreateGetRequest();
13383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo httpreq2 = CreateGetRequest();
13393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo httpreq3 = CreateGetRequest();
13403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
13413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans1.Start(&httpreq1, &callback1, log);
13423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(out.rv, ERR_IO_PENDING);
13433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // run transaction 1 through quickly to force a read of our SETTINGS
13443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // frame
13453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = callback1.WaitForResult();
13463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(OK, out.rv);
13473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
13483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans2.Start(&httpreq2, &callback2, log);
13493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(out.rv, ERR_IO_PENDING);
13503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans3->Start(&httpreq3, &callback3, log);
13513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(out.rv, ERR_IO_PENDING);
13523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = callback3.WaitForResult();
13533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(ERR_ABORTED, out.rv);
13543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
13553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(6U, data->read_index());
13563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
13573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HttpResponseInfo* response1 = trans1.GetResponseInfo();
13583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(response1 != NULL);
13593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response1->headers != NULL);
13603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response1->was_fetched_via_spdy);
13613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.status_line = response1->headers->GetStatusLine();
13623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.response_info = *response1;
13633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = ReadTransaction(&trans1, &out.response_data);
1364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
1365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
13663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HttpResponseInfo* response2 = trans2.GetResponseInfo();
13673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(response2 != NULL);
13683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.status_line = response2->headers->GetStatusLine();
13693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.response_info = *response2;
13703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = ReadTransaction(&trans2, &out.response_data);
13713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_CONNECTION_RESET, out.rv);
13723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
13733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
1374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
13763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Test that a simple PUT request works.
13773345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, Put) {
13783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Setup the request
13793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo request;
13803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.method = "PUT";
13813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.url = GURL("http://www.google.com/");
13823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
13833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const SpdyHeaderInfo kSynStartHeader = {
13843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::SYN_STREAM,             // Kind = Syn
13853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    1,                            // Stream ID
13863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0,                            // Associated stream ID
13873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    net::ConvertRequestPriorityToSpdyPriority(LOWEST),  // Priority
13883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::CONTROL_FLAG_FIN,       // Control Flags
13893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    false,                        // Compressed
13903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::INVALID,                // Status
13913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    NULL,                         // Data
13923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0,                            // Length
13933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::DATA_FLAG_NONE          // Data Flags
13943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
13953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char* const kPutHeaders[] = {
13963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "method", "PUT",
13973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "url", "/",
13983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "host", "www.google.com",
13993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "scheme", "http",
14003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "version", "HTTP/1.1",
14013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "content-length", "0"
14023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
14033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPacket(kSynStartHeader, NULL, 0,
1404201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    kPutHeaders, arraysize(kPutHeaders) / 2));
14053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
14063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req)
14073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
14083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
14093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
14103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const SpdyHeaderInfo kSynReplyHeader = {
14113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::SYN_REPLY,              // Kind = SynReply
14123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    1,                            // Stream ID
14133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0,                            // Associated stream ID
14143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    net::ConvertRequestPriorityToSpdyPriority(LOWEST),  // Priority
14153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::CONTROL_FLAG_NONE,      // Control Flags
14163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    false,                        // Compressed
14173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::INVALID,                // Status
14183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    NULL,                         // Data
14193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0,                            // Length
14203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::DATA_FLAG_NONE          // Data Flags
14213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
14223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const char* const kStandardGetHeaders[] = {
14233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "status", "200",
14243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "version", "HTTP/1.1"
14253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "content-length", "1234"
14263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
14273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPacket(kSynReplyHeader,
1428201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      NULL, 0, kStandardGetHeaders, arraysize(kStandardGetHeaders) / 2));
14293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
14303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp),
14313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body),
14323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0)  // EOF
14333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
14343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
14353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<DelayedSocketData> data(
14363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new DelayedSocketData(1, reads, arraysize(reads),
14373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes, arraysize(writes)));
14383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(request,
14393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
14403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunToCompletion(data.get());
14413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TransactionHelperResult out = helper.output();
14423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
14433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, out.rv);
14443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
14453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
14473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Test that a simple HEAD request works.
14483345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, Head) {
1449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Setup the request
1450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpRequestInfo request;
14513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.method = "HEAD";
1452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request.url = GURL("http://www.google.com/");
1453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
14543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const SpdyHeaderInfo kSynStartHeader = {
14553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::SYN_STREAM,             // Kind = Syn
14563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    1,                            // Stream ID
14573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0,                            // Associated stream ID
14583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    net::ConvertRequestPriorityToSpdyPriority(LOWEST),  // Priority
14593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::CONTROL_FLAG_FIN,       // Control Flags
14603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    false,                        // Compressed
14613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::INVALID,                // Status
14623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    NULL,                         // Data
14633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0,                            // Length
14643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::DATA_FLAG_NONE          // Data Flags
14653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
14663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char* const kHeadHeaders[] = {
14673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "method", "HEAD",
14683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "url", "/",
14693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "host", "www.google.com",
14703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "scheme", "http",
14713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "version", "HTTP/1.1",
14723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "content-length", "0"
14733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
14743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPacket(kSynStartHeader, NULL, 0,
1475201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    kHeadHeaders, arraysize(kHeadHeaders) / 2));
14763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
14773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req)
14783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
14793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
14803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
14813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const SpdyHeaderInfo kSynReplyHeader = {
14823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::SYN_REPLY,              // Kind = SynReply
14833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    1,                            // Stream ID
14843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0,                            // Associated stream ID
14853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    net::ConvertRequestPriorityToSpdyPriority(LOWEST),  // Priority
14863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::CONTROL_FLAG_NONE,      // Control Flags
14873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    false,                        // Compressed
14883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::INVALID,                // Status
14893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    NULL,                         // Data
14903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0,                            // Length
14913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::DATA_FLAG_NONE          // Data Flags
14923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
14933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const char* const kStandardGetHeaders[] = {
14943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "status", "200",
14953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "version", "HTTP/1.1"
14963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "content-length", "1234"
14973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
14983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPacket(kSynReplyHeader,
1499201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      NULL, 0, kStandardGetHeaders, arraysize(kStandardGetHeaders) / 2));
15003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
15013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp),
15023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body),
15033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0)  // EOF
15043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
15053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
15063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<DelayedSocketData> data(
15073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new DelayedSocketData(1, reads, arraysize(reads),
15083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes, arraysize(writes)));
15093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(request,
15103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
15113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunToCompletion(data.get());
15123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TransactionHelperResult out = helper.output();
15133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
15143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, out.rv);
15153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
15163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
15173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
15183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Test that a simple POST works.
15193345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, Post) {
15203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(kUploadDataSize, NULL, 0));
1521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = {
1523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockWrite(*req),
1524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockWrite(*body),  // POST upload frame
1525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
1526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
1528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
1529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
1530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
1531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
1532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
1533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
1535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(2, reads, arraysize(reads),
1536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
15373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreatePostRequest(),
15383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
15393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunToCompletion(data.get());
15403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TransactionHelperResult out = helper.output();
15413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, out.rv);
15423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
15433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("hello!", out.response_data);
15443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
15453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1546dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Test that a chunked POST works.
1547dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST_P(SpdyNetworkTransactionTest, ChunkedPost) {
1548dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  UploadDataStream::set_merge_chunks(false);
1549dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0));
1550dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> chunk1(ConstructSpdyBodyFrame(1, false));
1551dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> chunk2(ConstructSpdyBodyFrame(1, true));
1552dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MockWrite writes[] = {
1553dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockWrite(*req),
1554dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockWrite(*chunk1),
1555dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockWrite(*chunk2),
1556dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  };
1557dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1558dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
1559dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MockRead reads[] = {
1560dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*resp),
1561dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*chunk1),
1562dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*chunk2),
1563dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    MockRead(true, 0, 0)  // EOF
1564dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  };
1565dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1566dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_refptr<DelayedSocketData> data(
1567dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      new DelayedSocketData(2, reads, arraysize(reads),
1568dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                            writes, arraysize(writes)));
1569dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
1570dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                     BoundNetLog(), GetParam());
1571dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  helper.RunToCompletion(data.get());
1572dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  TransactionHelperResult out = helper.output();
1573dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(OK, out.rv);
1574dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1575dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ("hello!hello!", out.response_data);
1576dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
1577dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
15783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Test that a POST without any post data works.
15793345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, NullPost) {
15803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Setup the request
15813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo request;
15823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.method = "POST";
15833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.url = GURL("http://www.google.com/");
15843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Create an empty UploadData.
15853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.upload_data = NULL;
15863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
15873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // When request.upload_data is NULL for post, content-length is
15883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // expected to be 0.
15893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(0, NULL, 0));
15903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Set the FIN bit since there will be no body.
15913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  req->set_flags(spdy::CONTROL_FLAG_FIN);
15923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
15933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req),
15943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
15953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
15963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
15973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
15983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
15993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp),
16003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body),
16013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0)  // EOF
16023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
16033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
16043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<DelayedSocketData> data(
16053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new DelayedSocketData(1, reads, arraysize(reads),
16063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes, arraysize(writes)));
16073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(request,
16093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
1610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunToCompletion(data.get());
1611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
1612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
1613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("hello!", out.response_data);
1615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test that a simple POST works.
16183345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, EmptyPost) {
1619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Setup the request
1620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpRequestInfo request;
1621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request.method = "POST";
1622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request.url = GURL("http://www.google.com/");
1623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Create an empty UploadData.
1624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request.upload_data = new UploadData();
1625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
16263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Http POST Content-Length is using UploadDataStream::size().
16273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // It is the same as request.upload_data->GetContentLength().
16283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<UploadDataStream> stream(UploadDataStream::Create(
16293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      request.upload_data, NULL));
16303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(request.upload_data->GetContentLength(), stream->size());
16313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
16323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
16333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      req(ConstructSpdyPost(request.upload_data->GetContentLength(), NULL, 0));
1634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Set the FIN bit since there will be no body.
1635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  req->set_flags(spdy::CONTROL_FLAG_FIN);
1636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = {
1637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockWrite(*req),
1638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
1639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
1641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
1643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
1644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
1645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
1646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
1647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
1649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
1650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
1651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(request,
16533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
1654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunToCompletion(data.get());
1655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
1656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
1657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("hello!", out.response_data);
1659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// While we're doing a post, the server sends back a SYN_REPLY.
16623345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, PostWithEarlySynReply) {
1663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const char upload[] = { "hello!" };
1664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Setup the request
1666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpRequestInfo request;
1667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request.method = "POST";
1668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request.url = GURL("http://www.google.com/");
1669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request.upload_data = new UploadData();
1670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request.upload_data->AppendBytes(upload, sizeof(upload));
1671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
16723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Http POST Content-Length is using UploadDataStream::size().
16733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // It is the same as request.upload_data->GetContentLength().
16743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<UploadDataStream> stream(UploadDataStream::Create(
16753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      request.upload_data, NULL));
16763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(request.upload_data->GetContentLength(), stream->size());
16773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> stream_reply(ConstructSpdyPostSynReply(NULL, 0));
16783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> stream_body(ConstructSpdyBodyFrame(1, true));
1679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
16803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream_reply, 2),
16813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream_body, 3),
1682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(false, 0, 0)  // EOF
1683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
1684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
16863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new DelayedSocketData(0, reads, arraysize(reads), NULL, 0));
1687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(request,
16883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
1689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunPreTestSetup();
16903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
1691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunDefaultTest();
16923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
16933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
16953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_SYN_REPLY_NOT_RECEIVED, out.rv);
16963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
16973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
16983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// The client upon cancellation tries to send a RST_STREAM frame. The mock
16993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// socket causes the TCP write to return zero. This test checks that the client
17003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// tries to queue up the RST_STREAM frame again.
17013345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
17023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
17033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> rst(
17043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyRstStream(1, spdy::CANCEL));
17053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
17063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req.get(), 0, false),
17073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockWrite(false, 0, 0, 2),
17083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*rst.get(), 3, false),
17093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
17103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
17113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
17123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
1713731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    CreateMockRead(*resp.get(), 1, true),
1714731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    MockRead(true, 0, 0, 4)  // EOF
17153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
17163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
17173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<DeterministicSocketData> data(
17183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new DeterministicSocketData(reads, arraysize(reads),
17193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes, arraysize(writes)));
17203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
17213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
17223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.SetDeterministic();
17233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
17243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddDeterministicData(data.get());
17253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans = helper.trans();
17263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
17273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
17283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
17293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_IO_PENDING, rv);
17303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
17313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->SetStop(2);
17323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->Run();
17333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.ResetTrans();
17343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->SetStop(20);
17353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->Run();
17363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
17373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
1738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test that the transaction doesn't crash when we don't have a reply.
17413345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ResponseWithoutSynReply) {
1742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
1744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
1745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
1746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
1747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
1749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads), NULL, 0));
1750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
17513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
1752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunToCompletion(data.get());
1753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
1754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_SYN_REPLY_NOT_RECEIVED, out.rv);
1755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test that the transaction doesn't crash when we get two replies on the same
1758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// stream ID. See http://crbug.com/45639.
17593345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
1760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
1762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
1766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
1767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
1768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
1769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
1770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
1771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
1773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
1774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
1775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
17773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
1778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunPreTestSetup();
17793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
1780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
1782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback callback;
1784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
1785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
1786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = callback.WaitForResult();
1787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, rv);
1788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const HttpResponseInfo* response = trans->GetResponseInfo();
17903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(response != NULL);
1791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->headers != NULL);
1792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->was_fetched_via_spdy);
1793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string response_data;
1794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = ReadTransaction(trans, &response_data);
1795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
1796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.VerifyDataConsumed();
1798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
18003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Test that sent data frames and received WINDOW_UPDATE frames change
18013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// the send_window_size_ correctly.
18023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
18033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// WINDOW_UPDATE is different than most other frames in that it can arrive
18043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// while the client is still sending the request body.  In order to enforce
18053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// this scenario, we feed a couple of dummy frames and give a delay of 0 to
18063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// socket data provider, so that initial read that is done as soon as the
18073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// stream is created, succeeds and schedules another read.  This way reads
18083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// and writes are interleaved; after doing a full frame write, SpdyStream
18093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// will break out of DoLoop and will read and process a WINDOW_UPDATE.
18103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
18113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// since request has not been completely written, therefore we feed
18123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// enough number of WINDOW_UPDATEs to finish the first read and cause a
18133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// write, leading to a complete write of request body; after that we send
18143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// a reply with a body, to cause a graceful shutdown.
18153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
18163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// TODO(agayev): develop a socket data provider where both, reads and
18173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// writes are ordered so that writing tests like these are easy and rewrite
18183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// all these tests using it.  Right now we are working around the
18193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// limitations as described above and it's not deterministic, tests may
18203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// fail under specific circumstances.
18213345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) {
18223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SpdySession::set_flow_control(true);
18233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
18243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static int kFrameCount = 2;
18253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<std::string> content(
18263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new std::string(kMaxSpdyFrameChunkSize, 'a'));
18273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(
18283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      kMaxSpdyFrameChunkSize * kFrameCount, NULL, 0));
18293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body(
18303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyBodyFrame(1, content->c_str(), content->size(), false));
18313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body_end(
18323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyBodyFrame(1, content->c_str(), content->size(), true));
1833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = {
1835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockWrite(*req),
1836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockWrite(*body),
18373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*body_end),
1838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
1839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const int kDeltaWindowSize = 0xff;
18413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const int kDeltaCount = 4;
1842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> window_update(
1843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
18443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> window_update_dummy(
18453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
18463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
1847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
18483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*window_update_dummy),
18493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*window_update_dummy),
18503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*window_update_dummy),
18513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*window_update),     // Four updates, therefore window
18523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*window_update),     // size should increase by
18533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*window_update),     // kDeltaWindowSize * 4
1854c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*window_update),
18553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp),
18563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body_end),
1857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
1858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
1859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
18613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new DelayedSocketData(0, reads, arraysize(reads),
1862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
1863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
18643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Setup the request
18653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo request;
18663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.method = "POST";
18673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.url = GURL(kDefaultURL);
18683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.upload_data = new UploadData();
18693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (int i = 0; i < kFrameCount; ++i)
18703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    request.upload_data->AppendBytes(content->c_str(), content->size());
1871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
18723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(request, BoundNetLog(), GetParam());
18733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
18743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
1875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
18763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans = helper.trans();
18773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
18783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
18793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
1880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
1882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = callback.WaitForResult();
1883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, rv);
1884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
18853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
18863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(stream != NULL);
18873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(stream->stream() != NULL);
1888201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(static_cast<int>(spdy::kSpdyStreamInitialWindowSize) +
18893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            kDeltaWindowSize * kDeltaCount -
18903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            kMaxSpdyFrameChunkSize * kFrameCount,
18913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            stream->stream()->send_window_size());
18923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
18933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SpdySession::set_flow_control(false);
1894c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
18963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Test that received data frames and sent WINDOW_UPDATE frames change
18973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// the recv_window_size_ correctly.
18983345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) {
18993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SpdySession::set_flow_control(true);
1900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
19013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
19023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> window_update(
19033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyWindowUpdate(1, kUploadDataSize));
1904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
19053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
19063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req),
19073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*window_update),
19083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
1909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
19103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(
19113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyGetSynReply(NULL, 0, 1));
19123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body_no_fin(
19133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyBodyFrame(1, false));
19143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body_fin(
19153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyBodyFrame(1, NULL, 0, true));
19163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
19173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp),
19183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body_no_fin),
19193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 0),  // Force a pause
19203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body_fin),
19213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 0),  // Force a pause
19223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0)  // EOF
19233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
19243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<DelayedSocketData> data(
19263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new DelayedSocketData(1, reads, arraysize(reads),
19273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes, arraysize(writes)));
19283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
19303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
19313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
19323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
19333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans = helper.trans();
19343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
19363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
19373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_IO_PENDING, rv);
19393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  rv = callback.WaitForResult();
19403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, rv);
19413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SpdyHttpStream* stream =
19433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      static_cast<SpdyHttpStream*>(trans->stream_.get());
19443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(stream != NULL);
19453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(stream->stream() != NULL);
19463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1947201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(
1948201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      static_cast<int>(spdy::kSpdyStreamInitialWindowSize) - kUploadDataSize,
1949201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream->stream()->recv_window_size());
19503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HttpResponseInfo* response = trans->GetResponseInfo();
19523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(response != NULL);
19533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(response->headers != NULL);
19543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
19553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response->was_fetched_via_spdy);
19563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Issue a read which will cause a WINDOW_UPDATE to be sent and window
19583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // size increased to default.
1959513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kUploadDataSize));
19603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  rv = trans->Read(buf, kUploadDataSize, NULL);
19613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(kUploadDataSize, rv);
19623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string content(buf->data(), buf->data()+kUploadDataSize);
19633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_STREQ(kUploadData, content.c_str());
19643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Schedule the reading of empty data frame with FIN
19663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->CompleteRead();
19673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Force write of WINDOW_UPDATE which was scheduled during the above
19693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // read.
19703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MessageLoop::current()->RunAllPending();
19713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Read EOF.
19733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->CompleteRead();
19743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
19763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SpdySession::set_flow_control(false);
19773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
19783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Test that WINDOW_UPDATE frame causing overflow is handled correctly.  We
19803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// use the same trick as in the above test to enforce our scenario.
19813345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
19823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SpdySession::set_flow_control(true);
19833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // number of full frames we hope to write (but will not, used to
19853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // set content-length header correctly)
19863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static int kFrameCount = 3;
19873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<std::string> content(
19893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new std::string(kMaxSpdyFrameChunkSize, 'a'));
19903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(
19913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      kMaxSpdyFrameChunkSize * kFrameCount, NULL, 0));
19923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body(
19933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyBodyFrame(1, content->c_str(), content->size(), false));
1994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> rst(
1995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ConstructSpdyRstStream(1, spdy::FLOW_CONTROL_ERROR));
19963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // We're not going to write a data frame with FIN, we'll receive a bad
19983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
1999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = {
2000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockWrite(*req),
2001c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockWrite(*body),
2002c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockWrite(*rst),
2003c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
2004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
20053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const int kDeltaWindowSize = 0x7fffffff;  // cause an overflow
2006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> window_update(
2007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
20083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> window_update2(
20093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
2010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> reply(ConstructSpdyPostSynReply(NULL, 0));
20113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2012c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
20133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*window_update2),
20143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*window_update2),
2015c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*window_update),
20163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*window_update),
20173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*window_update),
20183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 0),  // Wait for the RST to be written.
2019c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
2020c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
2021c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
20233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new DelayedSocketData(0, reads, arraysize(reads),
2024c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
2025c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
20263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Setup the request
20273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo request;
20283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.method = "POST";
20293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.url = GURL("http://www.google.com/");
20303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.upload_data = new UploadData();
20313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (int i = 0; i < kFrameCount; ++i)
20323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    request.upload_data->AppendBytes(content->c_str(), content->size());
20333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
20343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(request,
20353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
20363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
20373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
2038c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
20393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans = helper.trans();
2040c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
20413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
20423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
2043c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2044c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
2045c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = callback.WaitForResult();
2046c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
2047c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
20483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->CompleteRead();
2049c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
20503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(helper.session() != NULL);
20513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(helper.session()->spdy_session_pool() != NULL);
20523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.session()->spdy_session_pool()->CloseAllSessions();
20533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
20543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
20553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SpdySession::set_flow_control(false);
2056c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
2057c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
20583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Test that after hitting a send window size of 0, the write process
20593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// stalls and upon receiving WINDOW_UPDATE frame write resumes.
20603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
20613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// This test constructs a POST request followed by enough data frames
20623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// containing 'a' that would make the window size 0, followed by another
20633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// data frame containing default content (which is "hello!") and this frame
20643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// also contains a FIN flag.  DelayedSocketData is used to enforce all
20653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// writes go through before a read could happen.  However, the last frame
20663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// ("hello!")  is not supposed to go through since by the time its turn
20673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// arrives, window size is 0.  At this point MessageLoop::Run() called via
20683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// callback would block.  Therefore we call MessageLoop::RunAllPending()
20693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// which returns after performing all possible writes.  We use DCHECKS to
20703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// ensure that last data frame is still there and stream has stalled.
20713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// After that, next read is artifically enforced, which causes a
20723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// WINDOW_UPDATE to be read and I/O process resumes.
20733345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) {
20743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SpdySession::set_flow_control(true);
20753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
20763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Number of frames we need to send to zero out the window size: data
20773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // frames plus SYN_STREAM plus the last data frame; also we need another
20783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // data frame that we will send once the WINDOW_UPDATE is received,
20793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // therefore +3.
2080201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  size_t nwrites =
2081201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      spdy::kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
20823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
20833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Calculate last frame's size; 0 size data frame is legal.
2084201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  size_t last_frame_size =
2085201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      spdy::kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
20863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
20873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Construct content for a data frame of maximum size.
20883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<std::string> content(
20893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new std::string(kMaxSpdyFrameChunkSize, 'a'));
20903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
20913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(
2092201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      spdy::kSpdyStreamInitialWindowSize + kUploadDataSize, NULL, 0));
20933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
20943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Full frames.
20953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body1(
20963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyBodyFrame(1, content->c_str(), content->size(), false));
20973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
20983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Last frame to zero out the window size.
20993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body2(
21003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyBodyFrame(1, content->c_str(), last_frame_size, false));
21013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Data frame to be sent once WINDOW_UPDATE frame is received.
21033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body3(ConstructSpdyBodyFrame(1, true));
21043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Fill in mock writes.
21063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_array<MockWrite> writes(new MockWrite[nwrites]);
21073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  size_t i = 0;
21083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  writes[i] = CreateMockWrite(*req);
21093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (i = 1; i < nwrites-2; i++)
21103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    writes[i] = CreateMockWrite(*body1);
21113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  writes[i++] = CreateMockWrite(*body2);
21123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  writes[i] = CreateMockWrite(*body3);
21133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Construct read frame, give enough space to upload the rest of the
21153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // data.
21163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> window_update(
21173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyWindowUpdate(1, kUploadDataSize));
21183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> reply(ConstructSpdyPostSynReply(NULL, 0));
21193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
21203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*window_update),
21213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*window_update),
21223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*reply),
21233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body2),
21243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body3),
21253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0)  // EOF
21263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
21273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Force all writes to happen before any read, last write will not
21293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // actually queue a frame, due to window size being 0.
21303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<DelayedSocketData> data(
21313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new DelayedSocketData(nwrites, reads, arraysize(reads),
21323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes.get(), nwrites));
21333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo request;
21353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.method = "POST";
21363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.url = GURL("http://www.google.com/");
21373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.upload_data = new UploadData();
21383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<std::string> upload_data(
2139201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      new std::string(spdy::kSpdyStreamInitialWindowSize, 'a'));
21403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  upload_data->append(kUploadData, kUploadDataSize);
21413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.upload_data->AppendBytes(upload_data->c_str(), upload_data->size());
21423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(request,
21433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
21443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
21453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
21463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans = helper.trans();
21483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
21503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
21513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_IO_PENDING, rv);
21523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MessageLoop::current()->RunAllPending(); // Write as much as we can.
21543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
21563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(stream != NULL);
21573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(stream->stream() != NULL);
21583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(0, stream->stream()->send_window_size());
21593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_FALSE(stream->request_body_stream_->eof());
21603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->ForceNextRead();   // Read in WINDOW_UPDATE frame.
21623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  rv = callback.WaitForResult();
21633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
21643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SpdySession::set_flow_control(false);
21663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
21673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21683345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, CancelledTransaction) {
2169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Construct the request.
2170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = {
2172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockWrite(*req),
2173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
2174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
2177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
2178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // This following read isn't used by the test, except during the
2179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // RunAllPending() call at the end since the SpdySession survives the
2180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // HttpNetworkTransaction and still tries to continue Read()'ing.  Any
2181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // MockRead will do here.
2182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
2183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
2184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  StaticSocketDataProvider data(reads, arraysize(reads),
2186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                writes, arraysize(writes));
2187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
21893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
2190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunPreTestSetup();
21913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(&data);
2192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
2193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback callback;
2195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
2196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
2197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.ResetTrans();  // Cancel the transaction.
2198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
2200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // MockClientSocketFactory) are still alive.
2201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->RunAllPending();
2202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.VerifyDataNotConsumed();
2203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
2204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
22053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Verify that the client sends a Rst Frame upon cancelling the stream.
22063345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
22073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
22083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> rst(
22093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyRstStream(1, spdy::CANCEL));
22103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
22113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req, 0, false),
22123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*rst, 2, false),
22133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
22143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
22153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
22163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
2217731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    CreateMockRead(*resp, 1, true),
2218731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    MockRead(true, 0, 0, 3)  // EOF
22193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
22203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
22213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<DeterministicSocketData> data(
22223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new DeterministicSocketData(reads, arraysize(reads),
22233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes, arraysize(writes)));
22243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
22253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
22263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(),
22273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     GetParam());
22283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.SetDeterministic();
22293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
22303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddDeterministicData(data.get());
22313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans = helper.trans();
22323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
22333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
22343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
22353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
22363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_IO_PENDING, rv);
22373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
22383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->SetStop(2);
22393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->Run();
22403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.ResetTrans();
22413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->SetStop(20);
22423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->Run();
22433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
22443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
22453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
22463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SpdyNetworkTransactionTest::StartTransactionCallback
2248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : public CallbackRunner< Tuple1<int> > {
2249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
2250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  explicit StartTransactionCallback(
22513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      const scoped_refptr<HttpNetworkSession>& session,
2252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NormalSpdyTransactionHelper& helper)
2253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : session_(session), helper_(helper) {}
2254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We try to start another transaction, which should succeed.
2256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void RunWithParams(const Tuple1<int>& params) {
2257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<HttpNetworkTransaction> trans(
2258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        new HttpNetworkTransaction(session_));
2259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TestCompletionCallback callback;
2260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HttpRequestInfo request;
2261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    request.method = "GET";
2262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    request.url = GURL("http://www.google.com/");
2263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    request.load_flags = 0;
2264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int rv = trans->Start(&request, &callback, BoundNetLog());
2265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(ERR_IO_PENDING, rv);
2266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    rv = callback.WaitForResult();
2267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
2268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
22703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const scoped_refptr<HttpNetworkSession>& session_;
2271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper& helper_;
2272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
2273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Verify that the client can correctly deal with the user callback attempting
2275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// to start another transaction on a session that is closing down. See
2276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// http://crbug.com/47455
22773345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
2278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
2280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes2[] = { CreateMockWrite(*req) };
2281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The indicated length of this packet is longer than its actual length. When
2283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the session receives an empty packet after this one, it shuts down the
2284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // session, and calls the read callback with the incomplete data.
2285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const uint8 kGetBodyFrame2[] = {
2286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0x00, 0x00, 0x00, 0x01,
2287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0x01, 0x00, 0x00, 0x07,
2288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    'h', 'e', 'l', 'l', 'o', '!',
2289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
2290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
22913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
22923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
22933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp, 2),
22943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 3),  // Force a pause
22953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame2),
22963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick             arraysize(kGetBodyFrame2), 4),
22973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 5),  // Force a pause
22983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0, 6),  // EOF
22993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
23003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads2[] = {
23013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp, 2),
23023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0, 3),  // EOF
23033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
23043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
23053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data(
23063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(reads, arraysize(reads),
23073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes, arraysize(writes)));
23083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<DelayedSocketData> data2(
23093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new DelayedSocketData(1, reads2, arraysize(reads2),
23103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes2, arraysize(writes2)));
23113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
23123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
23133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
23143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
23153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
23163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data2.get());
23173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans = helper.trans();
23183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
23193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Start the transaction with basic parameters.
23203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
23213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
23223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_IO_PENDING, rv);
23233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  rv = callback.WaitForResult();
23243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
23253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  StartTransactionCallback callback2(helper.session(), helper);
23263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const int kSize = 3000;
2327513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
23283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  rv = trans->Read(buf, kSize, &callback2);
23293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // This forces an err_IO_pending, which sets the callback.
23303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->CompleteRead();
23313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // This finishes the read.
23323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->CompleteRead();
23333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
23343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
23353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
23363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass SpdyNetworkTransactionTest::DeleteSessionCallback
23373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    : public CallbackRunner< Tuple1<int> > {
23383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick public:
23393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  explicit DeleteSessionCallback(NormalSpdyTransactionHelper& helper) :
23403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      helper_(helper) {}
23413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
23423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // We kill the transaction, which deletes the session and stream.
23433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual void RunWithParams(const Tuple1<int>& params) {
23443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    helper_.ResetTrans();
23453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
23463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
23473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick private:
23483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper& helper_;
23493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick};
23503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
23513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Verify that the client can correctly deal with the user callback deleting the
23523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// transaction. Failures will usually be valgrind errors. See
23533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// http://crbug.com/46925
23543345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
23553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
23563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = { CreateMockWrite(*req) };
23573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
23583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
23593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
23603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
23613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp.get(), 2),
23623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 3),  // Force a pause
23633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body.get(), 4),
23643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0, 5),  // EOF
23653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
23663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
23673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data(
23683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(reads, arraysize(reads),
23693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes, arraysize(writes)));
23703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
23713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
23723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
23733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
23743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
23753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans = helper.trans();
23763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
23773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Start the transaction with basic parameters.
23783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
23793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
23803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_IO_PENDING, rv);
23813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  rv = callback.WaitForResult();
23823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
23833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Setup a user callback which will delete the session, and clear out the
23843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // memory holding the stream object. Note that the callback deletes trans.
23853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DeleteSessionCallback callback2(helper);
23863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const int kSize = 3000;
2387513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
23883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  rv = trans->Read(buf, kSize, &callback2);
23893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(ERR_IO_PENDING, rv);
23903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->CompleteRead();
23913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
23923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Finish running rest of tasks.
23933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MessageLoop::current()->RunAllPending();
23943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
23953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
23963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
23973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Send a spdy request to www.google.com that gets redirected to www.foo.com.
23983345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, RedirectGetRequest) {
239921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // These are headers which the net::URLRequest tacks on.
24003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char* const kExtraHeaders[] = {
24013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "accept-charset",
24023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "",
24033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "accept-encoding",
24043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "gzip,deflate",
24053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "accept-language",
24063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "",
24073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
24083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const SpdyHeaderInfo kSynStartHeader = make_spdy_header(spdy::SYN_STREAM);
24093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char* const kStandardGetHeaders[] = {
24103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "host",
24113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "www.google.com",
24123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "method",
24133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "GET",
24143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "scheme",
24153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "http",
24163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "url",
24173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "/",
24183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "user-agent",
24193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "",
24203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "version",
24213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "HTTP/1.1"
24223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
24233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char* const kStandardGetHeaders2[] = {
24243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "host",
24253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "www.foo.com",
24263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "method",
24273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "GET",
24283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "scheme",
24293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "http",
24303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "url",
24313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "/index.php",
24323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "user-agent",
24333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "",
24343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "version",
24353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "HTTP/1.1"
24363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
24373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
24383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Setup writes/reads to www.google.com
24393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPacket(
2440201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      kSynStartHeader, kExtraHeaders, arraysize(kExtraHeaders) / 2,
2441201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      kStandardGetHeaders, arraysize(kStandardGetHeaders) / 2));
24423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyPacket(
2443201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      kSynStartHeader, kExtraHeaders, arraysize(kExtraHeaders) / 2,
2444201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      kStandardGetHeaders2, arraysize(kStandardGetHeaders2) / 2));
24453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReplyRedirect(1));
24463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
24473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req, 1),
24483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
24493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
24503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp, 2),
24513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0, 3)  // EOF
24523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
24533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
24543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Setup writes/reads to www.foo.com
24553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 1));
24563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(1, true));
24573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes2[] = {
24583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req2, 1),
24593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
24603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads2[] = {
24613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp2, 2),
24623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body2, 3),
24633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0, 4)  // EOF
24643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
24653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data(
24663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(reads, arraysize(reads),
24673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes, arraysize(writes)));
24683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data2(
24693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(reads2, arraysize(reads2),
24703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes2, arraysize(writes2)));
24713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
24723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
24733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpStreamFactory::set_force_spdy_over_ssl(false);
24743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpStreamFactory::set_force_spdy_always(true);
24753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestDelegate d;
24763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  {
247721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    net::URLRequest r(GURL("http://www.google.com/"), &d);
24783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    SpdyURLRequestContext* spdy_url_request_context =
24793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        new SpdyURLRequestContext();
24803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    r.set_context(spdy_url_request_context);
24813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy_url_request_context->socket_factory().
24823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        AddSocketDataProvider(data.get());
24833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy_url_request_context->socket_factory().
24843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        AddSocketDataProvider(data2.get());
24853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
24863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    d.set_quit_on_redirect(true);
24873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    r.Start();
24883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MessageLoop::current()->Run();
24893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
24903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(1, d.received_redirect_count());
24913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
24923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    r.FollowDeferredRedirect();
24933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MessageLoop::current()->Run();
24943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(1, d.response_started_count());
24953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_FALSE(d.received_data_before_response());
249672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    EXPECT_EQ(net::URLRequestStatus::SUCCESS, r.status().status());
24973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    std::string contents("hello!");
24983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(contents, d.data_received());
24993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
25003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data->at_read_eof());
25013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data->at_write_eof());
25023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data2->at_read_eof());
25033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data2->at_write_eof());
25043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
25053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
25063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Send a spdy request to www.google.com. Get a pushed stream that redirects to
25073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// www.foo.com.
25083345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, RedirectServerPush) {
250921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // These are headers which the net::URLRequest tacks on.
25103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char* const kExtraHeaders[] = {
25113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "accept-charset",
25123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "",
25133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "accept-encoding",
25143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "gzip,deflate",
25153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "accept-language",
25163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "",
25173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
25183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const SpdyHeaderInfo kSynStartHeader = make_spdy_header(spdy::SYN_STREAM);
25193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char* const kStandardGetHeaders[] = {
25203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "host",
25213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "www.google.com",
25223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "method",
25233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "GET",
25243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "scheme",
25253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "http",
25263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "url",
25273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "/",
25283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "user-agent",
25293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "",
25303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "version",
25313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "HTTP/1.1"
25323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
25333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char* const kStandardGetHeaders2[] = {
25343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "host",
25353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "www.foo.com",
25363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "method",
25373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "GET",
25383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "scheme",
25393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "http",
25403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "url",
25413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "/index.php",
25423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "user-agent",
25433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "",
25443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "version",
25453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "HTTP/1.1"
25463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
25473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
25483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Setup writes/reads to www.google.com
2549201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame> req(
2550201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      ConstructSpdyPacket(kSynStartHeader,
2551201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                          kExtraHeaders,
2552201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                          arraysize(kExtraHeaders) / 2,
2553201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                          kStandardGetHeaders,
2554201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                          arraysize(kStandardGetHeaders) / 2));
2555201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame> req2(
2556201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      ConstructSpdyPacket(kSynStartHeader,
2557201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                          kExtraHeaders,
2558201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                          arraysize(kExtraHeaders) / 2,
2559201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                          kStandardGetHeaders2,
2560201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                          arraysize(kStandardGetHeaders2) / 2));
25613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2562201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame> rep(
2563201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      ConstructSpdyPush(NULL,
2564201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                        0,
2565201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                        2,
2566201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                        1,
2567201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                        "http://www.google.com/foo.dat",
2568201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                        "301 Moved Permanently",
2569201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                        "http://www.foo.com/index.php"));
25703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
25713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
25723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req, 1),
25733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
25743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
25753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp, 2),
25763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*rep, 3),
25773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body, 4),
25783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 5),  // Force a pause
25793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0, 6)  // EOF
25803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
25813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
25823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Setup writes/reads to www.foo.com
25833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 1));
25843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(1, true));
25853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes2[] = {
25863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req2, 1),
25873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
25883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads2[] = {
25893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp2, 2),
25903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body2, 3),
25913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0, 5)  // EOF
25923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
25933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data(
25943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(reads, arraysize(reads),
25953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes, arraysize(writes)));
25963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data2(
25973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(reads2, arraysize(reads2),
25983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes2, arraysize(writes2)));
25993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
26003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
26013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpStreamFactory::set_force_spdy_over_ssl(false);
26023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpStreamFactory::set_force_spdy_always(true);
26033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestDelegate d;
26043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestDelegate d2;
26053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<SpdyURLRequestContext> spdy_url_request_context(
26063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new SpdyURLRequestContext());
26073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  {
260821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    net::URLRequest r(GURL("http://www.google.com/"), &d);
26093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    r.set_context(spdy_url_request_context);
26103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy_url_request_context->socket_factory().
26113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        AddSocketDataProvider(data.get());
26123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
26133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    r.Start();
26143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MessageLoop::current()->Run();
26153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
26163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(0, d.received_redirect_count());
26173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    std::string contents("hello!");
26183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(contents, d.data_received());
26193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
262021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    net::URLRequest r2(GURL("http://www.google.com/foo.dat"), &d2);
26213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    r2.set_context(spdy_url_request_context);
26223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy_url_request_context->socket_factory().
26233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        AddSocketDataProvider(data2.get());
26243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
26253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    d2.set_quit_on_redirect(true);
26263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    r2.Start();
26273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MessageLoop::current()->Run();
26283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(1, d2.received_redirect_count());
26293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
26303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    r2.FollowDeferredRedirect();
26313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MessageLoop::current()->Run();
26323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(1, d2.response_started_count());
26333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_FALSE(d2.received_data_before_response());
263472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    EXPECT_EQ(net::URLRequestStatus::SUCCESS, r2.status().status());
26353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    std::string contents2("hello!");
26363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(contents2, d2.data_received());
26373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
26383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->CompleteRead();
26393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data2->CompleteRead();
26403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data->at_read_eof());
26413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data->at_write_eof());
26423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data2->at_read_eof());
26433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data2->at_write_eof());
26443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
26453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
26463345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
26473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const unsigned char kPushBodyFrame[] = {
26483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0x00, 0x00, 0x00, 0x02,                                      // header, ID
26493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0x01, 0x00, 0x00, 0x06,                                      // FIN, length
26503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed"
26513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
26523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
26533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
26543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
26553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_body(ConstructSpdyBodyFrame(1, true));
26563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
26573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*stream1_syn, 1),
26583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
26593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
26603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
26613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
26623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
2663201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_syn(ConstructSpdyPush(NULL,
2664201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    0,
2665201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    2,
2666201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    1,
2667201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    "http://www.google.com/foo.dat"));
26683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
26693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_reply, 2),
26703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream2_syn, 3),
26713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_body, 4, false),
26723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame),
26733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick             arraysize(kPushBodyFrame), 5),
26743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 6),  // Force a pause
26753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
26763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
26773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response;
26783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response2;
26793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string expected_push_result("pushed");
2680201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_refptr<OrderedSocketData> data(new OrderedSocketData(
2681201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      reads,
2682201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(reads),
2683201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      writes,
2684201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(writes)));
2685201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  RunServerPushTest(data.get(),
2686201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    &response,
2687201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    &response2,
2688201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    expected_push_result);
26893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
26903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the SYN_REPLY.
26913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response.headers != NULL);
26923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
26933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
26943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the pushed stream.
26953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response2.headers != NULL);
26963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
26973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
26983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
26993345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
27003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const unsigned char kPushBodyFrame[] = {
27013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0x00, 0x00, 0x00, 0x02,                                      // header, ID
27023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0x01, 0x00, 0x00, 0x06,                                      // FIN, length
27033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed"
27043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
27053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
27063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
27073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
27083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*stream1_syn, 1),
27093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
27103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
27113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
27123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
27133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
2714201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_syn(ConstructSpdyPush(NULL,
2715201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    0,
2716201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    2,
2717201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    1,
2718201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    "http://www.google.com/foo.dat"));
27193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
27203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_body(ConstructSpdyBodyFrame(1, true));
27213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
27223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_reply, 2),
27233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream2_syn, 3),
27243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame),
27253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick             arraysize(kPushBodyFrame), 5),
27263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_body, 4, false),
27273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 6),  // Force a pause
27283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
27293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
27303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response;
27313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response2;
27323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string expected_push_result("pushed");
2733201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_refptr<OrderedSocketData> data(new OrderedSocketData(
2734201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      reads,
2735201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(reads),
2736201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      writes,
2737201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(writes)));
2738201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  RunServerPushTest(data.get(),
2739201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    &response,
2740201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    &response2,
2741201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    expected_push_result);
27423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
27433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the SYN_REPLY.
27443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response.headers != NULL);
27453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
27463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
27473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the pushed stream.
27483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response2.headers != NULL);
27493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
27503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
27513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
27523345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ServerPushServerAborted) {
27533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
27543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
27553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
27563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_body(ConstructSpdyBodyFrame(1, true));
27573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
27583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*stream1_syn, 1),
27593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
27603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
27613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
27623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
27633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
2764201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_syn(ConstructSpdyPush(NULL,
2765201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    0,
2766201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    2,
2767201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    1,
2768201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    "http://www.google.com/foo.dat"));
27693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
27703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    stream2_rst(ConstructSpdyRstStream(2, spdy::PROTOCOL_ERROR));
27713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
27723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_reply, 2),
27733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream2_syn, 3),
27743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream2_rst, 4),
27753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_body, 5, false),
27763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 6),  // Force a pause
27773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
27783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
27793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data(
27803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(reads, arraysize(reads),
27813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes, arraysize(writes)));
27823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
27833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
27843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
27853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
27863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
27873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
27883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans = helper.trans();
27893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
27903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Start the transaction with basic parameters.
27913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
27923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
27933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_IO_PENDING, rv);
27943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  rv = callback.WaitForResult();
27953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, rv);
27963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
27973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify that we consumed all test data.
27983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data->at_read_eof()) << "Read count: "
27993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   << data->read_count()
28003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   << " Read index: "
28013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   << data->read_index();
28023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data->at_write_eof()) << "Write count: "
28033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                    << data->write_count()
28043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                    << " Write index: "
28053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                    << data->write_index();
28063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
28073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the SYN_REPLY.
28083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response = *trans->GetResponseInfo();
28093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response.headers != NULL);
28103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
28113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
28123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
28133345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ServerPushDuplicate) {
28143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify that we don't leak streams and that we properly send a reset
28153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // if the server pushes the same stream twice.
28163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const unsigned char kPushBodyFrame[] = {
28173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0x00, 0x00, 0x00, 0x02,                                      // header, ID
28183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0x01, 0x00, 0x00, 0x06,                                      // FIN, length
28193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed"
28203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
28213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
28223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
28233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
28243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
28253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_body(ConstructSpdyBodyFrame(1, true));
28263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
28273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream3_rst(ConstructSpdyRstStream(4, spdy::PROTOCOL_ERROR));
28283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
28293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*stream1_syn, 1),
28303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*stream3_rst, 5),
28313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
28323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
28333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
28343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
28353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
2836201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_syn(ConstructSpdyPush(NULL,
2837201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    0,
2838201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    2,
2839201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    1,
2840201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    "http://www.google.com/foo.dat"));
28413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
2842201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream3_syn(ConstructSpdyPush(NULL,
2843201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    0,
2844201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    4,
2845201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    1,
2846201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    "http://www.google.com/foo.dat"));
28473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
28483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_reply, 2),
28493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream2_syn, 3),
28503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream3_syn, 4),
28513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_body, 6, false),
28523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame),
28533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick             arraysize(kPushBodyFrame), 7),
28543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 8),  // Force a pause
28553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
28563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
28573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response;
28583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response2;
28593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string expected_push_result("pushed");
2860201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_refptr<OrderedSocketData> data(new OrderedSocketData(
2861201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      reads,
2862201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(reads),
2863201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      writes,
2864201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(writes)));
2865201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  RunServerPushTest(data.get(),
2866201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    &response,
2867201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    &response2,
2868201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    expected_push_result);
28693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
28703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the SYN_REPLY.
28713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response.headers != NULL);
28723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
28733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
28743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the pushed stream.
28753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response2.headers != NULL);
28763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
28773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
28783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
28793345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
28803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const unsigned char kPushBodyFrame1[] = {
28813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0x00, 0x00, 0x00, 0x02,                                      // header, ID
28823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0x01, 0x00, 0x00, 0x1F,                                      // FIN, length
28833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed"
28843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
28853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const char kPushBodyFrame2[] = " my darling";
28863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const char kPushBodyFrame3[] = " hello";
28873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const char kPushBodyFrame4[] = " my baby";
28883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
28893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
28903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
28913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
28923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_body(ConstructSpdyBodyFrame(1, true));
28933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
28943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*stream1_syn, 1),
28953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
28963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
28973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
28983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
28993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
2900201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_syn(ConstructSpdyPush(NULL,
2901201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    0,
2902201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    2,
2903201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    1,
2904201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    "http://www.google.com/foo.dat"));
29053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
29063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_reply, 2),
29073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream2_syn, 3),
29083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame1),
29093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick             arraysize(kPushBodyFrame1), 4),
29103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame2),
29113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick             arraysize(kPushBodyFrame2) - 1, 5),
29123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame3),
29133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick             arraysize(kPushBodyFrame3) - 1, 6),
29143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame4),
29153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick             arraysize(kPushBodyFrame4) - 1, 7),
29163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_body, 8, false),
29173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 9),  // Force a pause
29183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
29193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
29203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response;
29213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response2;
29223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string expected_push_result("pushed my darling hello my baby");
2923201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_refptr<OrderedSocketData> data(new OrderedSocketData(
2924201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      reads,
2925201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(reads),
2926201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      writes,
2927201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(writes)));
2928201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  RunServerPushTest(data.get(),
2929201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    &response,
2930201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    &response2,
2931201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    expected_push_result);
29323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
29333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the SYN_REPLY.
29343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response.headers != NULL);
29353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
29363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
29373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the pushed stream.
29383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response2.headers != NULL);
29393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
29403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
29413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
29423345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
29433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const unsigned char kPushBodyFrame1[] = {
29443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0x00, 0x00, 0x00, 0x02,                                      // header, ID
29453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0x01, 0x00, 0x00, 0x1F,                                      // FIN, length
29463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed"
29473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
29483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const char kPushBodyFrame2[] = " my darling";
29493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const char kPushBodyFrame3[] = " hello";
29503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const char kPushBodyFrame4[] = " my baby";
29513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
29523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
29533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
29543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
29553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_body(ConstructSpdyBodyFrame(1, true));
29563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
29573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*stream1_syn, 1),
29583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
29593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
29603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
29613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
29623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
2963201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_syn(ConstructSpdyPush(NULL,
2964201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    0,
2965201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    2,
2966201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    1,
2967201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    "http://www.google.com/foo.dat"));
29683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
29693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_reply, 2),
29703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream2_syn, 3),
29713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame1),
29723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick             arraysize(kPushBodyFrame1), 4),
29733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame2),
29743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick             arraysize(kPushBodyFrame2) - 1, 5),
29753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 6),  // Force a pause
29763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame3),
29773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick             arraysize(kPushBodyFrame3) - 1, 7),
29783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame4),
29793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick             arraysize(kPushBodyFrame4) - 1, 8),
29803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_body.get(), 9, false),
29813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 10)  // Force a pause.
29823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
29833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
29843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response;
29853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response2;
29863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string expected_push_result("pushed my darling hello my baby");
2987201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_refptr<OrderedSocketData> data(new OrderedSocketData(
2988201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      reads,
2989201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(reads),
2990201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      writes,
2991201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(writes)));
2992201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  RunServerPushTest(data.get(),
2993201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    &response,
2994201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    &response2,
2995201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    expected_push_result);
29963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
29973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the SYN_REPLY.
29983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response.headers != NULL);
29993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
30003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
30013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the pushed stream.
30023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response2.headers != NULL);
30033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
30043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
30053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
30063345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
30073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
30083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
30093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
30103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_body(ConstructSpdyBodyFrame(1, true));
30113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
30123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream2_rst(ConstructSpdyRstStream(2, spdy::INVALID_STREAM));
30133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
30143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*stream1_syn, 1),
30153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*stream2_rst, 4),
30163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
30173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
30183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
30193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
30203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
3021201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_syn(ConstructSpdyPush(NULL,
3022201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    0,
3023201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    2,
3024201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    0,
3025201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    "http://www.google.com/foo.dat"));
30263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
30273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_reply, 2),
30283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream2_syn, 3),
30293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_body, 4),
30303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 5)  // Force a pause
30313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
30323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
30333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data(
30343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(reads, arraysize(reads),
30353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes, arraysize(writes)));
30363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
30373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
30383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
30393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
30403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
30413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
30423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans = helper.trans();
30433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
30443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Start the transaction with basic parameters.
30453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
30463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
30473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_IO_PENDING, rv);
30483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  rv = callback.WaitForResult();
30493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, rv);
30503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
30513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify that we consumed all test data.
30523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data->at_read_eof()) << "Read count: "
30533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   << data->read_count()
30543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   << " Read index: "
30553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   << data->read_index();
30563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data->at_write_eof()) << "Write count: "
30573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                    << data->write_count()
30583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                    << " Write index: "
30593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                    << data->write_index();
30603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
30613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the SYN_REPLY.
30623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response = *trans->GetResponseInfo();
30633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response.headers != NULL);
30643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
30653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
30663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
30673345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
30683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
30693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
30703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
30713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_body(ConstructSpdyBodyFrame(1, true));
30723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
30733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream2_rst(ConstructSpdyRstStream(2, spdy::INVALID_ASSOCIATED_STREAM));
30743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
30753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*stream1_syn, 1),
30763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*stream2_rst, 4),
30773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
30783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
30793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
30803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
30813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
3082201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_syn(ConstructSpdyPush(NULL,
3083201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    0,
3084201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    2,
3085201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    9,
3086201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    "http://www.google.com/foo.dat"));
3087c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
30883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_reply, 2),
30893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream2_syn, 3),
30903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_body, 4),
3091c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, ERR_IO_PENDING, 5),  // Force a pause
3092c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3093c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3094c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<OrderedSocketData> data(
3095c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new OrderedSocketData(reads, arraysize(reads),
3096c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
3097c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
30983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
30993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunPreTestSetup();
31013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
31023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
3104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Start the transaction with basic parameters.
3106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback callback;
31073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
3108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
3109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = callback.WaitForResult();
31103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, rv);
3111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
31123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify that we consumed all test data.
31133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data->at_read_eof()) << "Read count: "
31143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   << data->read_count()
31153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   << " Read index: "
31163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   << data->read_index();
31173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data->at_write_eof()) << "Write count: "
31183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                    << data->write_count()
31193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                    << " Write index: "
31203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                    << data->write_index();
31213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
31223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the SYN_REPLY.
31233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response = *trans->GetResponseInfo();
31243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response.headers != NULL);
31253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
3127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
31283345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ServerPushNoURL) {
31293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
31303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
31313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
31323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_body(ConstructSpdyBodyFrame(1, true));
31333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
31343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream2_rst(ConstructSpdyRstStream(2, spdy::PROTOCOL_ERROR));
31353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
31363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*stream1_syn, 1),
31373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*stream2_rst, 4),
31383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
3139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
31403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
31413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
31423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
31433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream2_syn(ConstructSpdyPush(NULL, 0, 2, 1));
3144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
31453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_reply, 2),
31463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream2_syn, 3),
31473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_body, 4),
31483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 5)  // Force a pause
3149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<OrderedSocketData> data(
3152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new OrderedSocketData(reads, arraysize(reads),
3153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
3154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
31553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
31563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunPreTestSetup();
31583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
31593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
3161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Start the transaction with basic parameters.
3163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback callback;
31643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
3165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
3166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = callback.WaitForResult();
31673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, rv);
31683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify that we consumed all test data.
31693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data->at_read_eof()) << "Read count: "
31703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   << data->read_count()
31713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   << " Read index: "
31723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   << data->read_index();
31733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data->at_write_eof()) << "Write count: "
31743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                    << data->write_count()
31753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                    << " Write index: "
31763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                    << data->write_index();
31773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
31783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the SYN_REPLY.
31793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response = *trans->GetResponseInfo();
31803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response.headers != NULL);
31813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
3183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Verify that various SynReply headers parse correctly through the
3185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// HTTP layer.
31863345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) {
3187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct SynReplyHeadersTests {
3188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int num_headers;
3189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const char* extra_headers[5];
3190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const char* expected_headers;
3191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } test_cases[] = {
3192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // This uses a multi-valued cookie header.
3193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { 2,
3194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { "cookie", "val1",
3195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "cookie", "val2",  // will get appended separated by NULL
3196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NULL
3197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      },
3198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "cookie: val1\n"
3199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "cookie: val2\n"
3200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "hello: bye\n"
3201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "status: 200\n"
3202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "version: HTTP/1.1\n"
3203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
3204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // This is the minimalist set of headers.
3205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { 0,
3206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { NULL },
3207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "hello: bye\n"
3208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "status: 200\n"
3209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "version: HTTP/1.1\n"
3210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
3211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Headers with a comma separated list.
3212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { 1,
3213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { "cookie", "val1,val2",
3214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NULL
3215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      },
3216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "cookie: val1,val2\n"
3217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "hello: bye\n"
3218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "status: 200\n"
3219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "version: HTTP/1.1\n"
3220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
3221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<spdy::SpdyFrame> req(
3225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockWrite writes[] = { CreateMockWrite(*req) };
3227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<spdy::SpdyFrame> resp(
3229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ConstructSpdyGetSynReply(test_cases[i].extra_headers,
3230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 test_cases[i].num_headers,
3231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 1));
3232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead reads[] = {
3234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CreateMockRead(*resp),
3235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CreateMockRead(*body),
3236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      MockRead(true, 0, 0)  // EOF
3237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    };
3238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_refptr<DelayedSocketData> data(
3240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        new DelayedSocketData(1, reads, arraysize(reads),
3241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              writes, arraysize(writes)));
3242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NormalSpdyTransactionHelper helper(CreateGetRequest(),
32433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                       BoundNetLog(), GetParam());
3244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    helper.RunToCompletion(data.get());
3245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TransactionHelperResult out = helper.output();
3246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(OK, out.rv);
3248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ("hello!", out.response_data);
3250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(headers.get() != NULL);
3253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void* iter = NULL;
3254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string name, value, lines;
3255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      lines.append(name);
3257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      lines.append(": ");
3258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      lines.append(value);
3259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      lines.append("\n");
3260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
3261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(std::string(test_cases[i].expected_headers), lines);
3262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
3263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
3264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Verify that various SynReply headers parse vary fields correctly
3266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// through the HTTP layer, and the response matches the request.
32673345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) {
3268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const SpdyHeaderInfo syn_reply_info = {
3269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SYN_REPLY,                              // Syn Reply
3270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    1,                                            // Stream ID
3271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0,                                            // Associated Stream ID
32723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    net::ConvertRequestPriorityToSpdyPriority(LOWEST),
32733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                  // Priority
3274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::CONTROL_FLAG_NONE,                      // Control Flags
3275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    false,                                        // Compressed
3276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::INVALID,                                // Status
3277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NULL,                                         // Data
3278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0,                                            // Data Length
3279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::DATA_FLAG_NONE                          // Data Flags
3280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Modify the following data to change/add test cases:
3282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct SynReplyTests {
3283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const SpdyHeaderInfo* syn_reply;
3284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool vary_matches;
3285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int num_headers[2];
3286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const char* extra_headers[2][16];
3287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } test_cases[] = {
3288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Test the case of a multi-valued cookie.  When the value is delimited
3289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // with NUL characters, it needs to be unfolded into multiple headers.
3290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    {
3291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &syn_reply_info,
3292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      true,
3293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { 1, 4 },
3294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { { "cookie",   "val1,val2",
3295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NULL
3296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        },
3297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        { "vary",     "cookie",
3298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "status",   "200",
3299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "url",      "/index.php",
3300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "version",  "HTTP/1.1",
3301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NULL
3302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
3303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
3304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }, {    // Multiple vary fields.
3305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &syn_reply_info,
3306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      true,
3307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { 2, 5 },
3308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { { "friend",   "barney",
3309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "enemy",    "snaggletooth",
3310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NULL
3311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        },
3312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        { "vary",     "friend",
3313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "vary",     "enemy",
3314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "status",   "200",
3315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "url",      "/index.php",
3316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "version",  "HTTP/1.1",
3317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NULL
3318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
3319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
3320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }, {    // Test a '*' vary field.
3321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &syn_reply_info,
3322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      false,
3323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { 1, 4 },
3324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { { "cookie",   "val1,val2",
3325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NULL
3326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        },
3327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        { "vary",     "*",
3328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "status",   "200",
3329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "url",      "/index.php",
3330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "version",  "HTTP/1.1",
3331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NULL
3332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
3333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
3334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }, {    // Multiple comma-separated vary fields.
3335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &syn_reply_info,
3336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      true,
3337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { 2, 4 },
3338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { { "friend",   "barney",
3339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "enemy",    "snaggletooth",
3340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NULL
3341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        },
3342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        { "vary",     "friend,enemy",
3343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "status",   "200",
3344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "url",      "/index.php",
3345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "version",  "HTTP/1.1",
3346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NULL
3347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
3348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
3349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
3350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Construct the request.
3354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<spdy::SpdyFrame> frame_req(
3355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ConstructSpdyGet(test_cases[i].extra_headers[0],
3356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       test_cases[i].num_headers[0],
3357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       false, 1, LOWEST));
3358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockWrite writes[] = {
3360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CreateMockWrite(*frame_req),
3361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    };
3362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Construct the reply.
3364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<spdy::SpdyFrame> frame_reply(
3365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ConstructSpdyPacket(*test_cases[i].syn_reply,
3366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          test_cases[i].extra_headers[1],
3367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          test_cases[i].num_headers[1],
3368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          NULL,
3369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          0));
3370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead reads[] = {
3373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CreateMockRead(*frame_reply),
3374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CreateMockRead(*body),
3375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      MockRead(true, 0, 0)  // EOF
3376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    };
3377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Attach the headers to the request.
3379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int header_count = test_cases[i].num_headers[0];
3380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HttpRequestInfo request = CreateGetRequest();
3382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (int ct = 0; ct < header_count; ct++) {
3383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const char* header_key = test_cases[i].extra_headers[0][ct * 2];
3384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1];
3385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      request.extra_headers.SetHeader(header_key, header_value);
3386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
3387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_refptr<DelayedSocketData> data(
3389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        new DelayedSocketData(1, reads, arraysize(reads),
3390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              writes, arraysize(writes)));
3391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NormalSpdyTransactionHelper helper(request,
33923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                       BoundNetLog(), GetParam());
3393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    helper.RunToCompletion(data.get());
3394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TransactionHelperResult out = helper.output();
3395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(OK, out.rv) << i;
3397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line) << i;
3398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ("hello!", out.response_data) << i;
3399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Test the response information.
3401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(out.response_info.response_time >
3402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                out.response_info.request_time) << i;
3403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    base::TimeDelta test_delay = out.response_info.response_time -
3404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 out.response_info.request_time;
3405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    base::TimeDelta min_expected_delay;
3406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    min_expected_delay.FromMilliseconds(10);
3407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_GT(test_delay.InMillisecondsF(),
3408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              min_expected_delay.InMillisecondsF()) << i;
3409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(out.response_info.vary_data.is_valid(),
3410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              test_cases[i].vary_matches) << i;
3411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Check the headers.
3413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ASSERT_TRUE(headers.get() != NULL) << i;
3415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void* iter = NULL;
3416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string name, value, lines;
3417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      lines.append(name);
3419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      lines.append(": ");
3420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      lines.append(value);
3421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      lines.append("\n");
3422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
3423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Construct the expected header reply string.
3425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    char reply_buffer[256] = "";
3426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ConstructSpdyReplyString(test_cases[i].extra_headers[1],
3427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             test_cases[i].num_headers[1],
3428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             reply_buffer,
3429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             256);
3430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(std::string(reply_buffer), lines) << i;
3432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
3433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
3434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Verify that we don't crash on invalid SynReply responses.
34363345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, InvalidSynReply) {
3437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const SpdyHeaderInfo kSynStartHeader = {
3438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SYN_REPLY,              // Kind = SynReply
3439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    1,                            // Stream ID
3440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0,                            // Associated stream ID
34413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    net::ConvertRequestPriorityToSpdyPriority(LOWEST),
34423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                  // Priority
3443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::CONTROL_FLAG_NONE,      // Control Flags
3444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    false,                        // Compressed
3445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::INVALID,                // Status
3446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NULL,                         // Data
3447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0,                            // Length
3448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::DATA_FLAG_NONE          // Data Flags
3449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct InvalidSynReplyTests {
3452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int num_headers;
3453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const char* headers[10];
3454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } test_cases[] = {
3455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // SYN_REPLY missing status header
3456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { 4,
3457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { "cookie", "val1",
3458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "cookie", "val2",
3459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "url", "/index.php",
3460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "version", "HTTP/1.1",
3461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NULL
3462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      },
3463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
3464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // SYN_REPLY missing version header
3465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { 2,
3466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { "status", "200",
3467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "url", "/index.php",
3468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NULL
3469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      },
3470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
3471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // SYN_REPLY with no headers
3472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { 0, { NULL }, },
3473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<spdy::SpdyFrame> req(
3477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockWrite writes[] = {
3479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CreateMockWrite(*req),
3480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    };
3481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<spdy::SpdyFrame> resp(
3483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ConstructSpdyPacket(kSynStartHeader,
3484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            NULL, 0,
3485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            test_cases[i].headers,
3486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            test_cases[i].num_headers));
3487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead reads[] = {
3489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CreateMockRead(*resp),
3490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CreateMockRead(*body),
3491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      MockRead(true, 0, 0)  // EOF
3492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    };
3493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_refptr<DelayedSocketData> data(
3495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        new DelayedSocketData(1, reads, arraysize(reads),
3496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              writes, arraysize(writes)));
3497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NormalSpdyTransactionHelper helper(CreateGetRequest(),
34983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                       BoundNetLog(), GetParam());
3499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    helper.RunToCompletion(data.get());
3500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TransactionHelperResult out = helper.output();
3501201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    EXPECT_EQ(ERR_INCOMPLETE_SPDY_HEADERS, out.rv);
3502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
3503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
3504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Verify that we don't crash on some corrupt frames.
350672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenTEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
350772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // This is the length field that's too short.
350872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  scoped_ptr<spdy::SpdyFrame> syn_reply_wrong_length(
3509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ConstructSpdyGetSynReply(NULL, 0, 1));
351072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  syn_reply_wrong_length->set_length(syn_reply_wrong_length->length() - 4);
3511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct SynReplyTests {
3513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const spdy::SpdyFrame* syn_reply;
3514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } test_cases[] = {
351572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    { syn_reply_wrong_length.get(), },
3516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<spdy::SpdyFrame> req(
3520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockWrite writes[] = {
3522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CreateMockWrite(*req),
3523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      MockWrite(true, 0, 0)  // EOF
3524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    };
3525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead reads[] = {
3528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CreateMockRead(*test_cases[i].syn_reply),
3529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CreateMockRead(*body),
3530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      MockRead(true, 0, 0)  // EOF
3531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    };
3532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_refptr<DelayedSocketData> data(
3534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        new DelayedSocketData(1, reads, arraysize(reads),
3535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              writes, arraysize(writes)));
3536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NormalSpdyTransactionHelper helper(CreateGetRequest(),
35373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                       BoundNetLog(), GetParam());
3538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    helper.RunToCompletion(data.get());
3539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TransactionHelperResult out = helper.output();
3540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
3542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
3543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test that we shutdown correctly on write errors.
35453345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, WriteError) {
3546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = {
3548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We'll write 10 bytes successfully
3549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockWrite(true, req->data(), 10),
3550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Followed by ERROR!
3551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockWrite(true, ERR_FAILED),
3552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
3555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(2, NULL, 0,
3556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
3557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
35583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
3559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunToCompletion(data.get());
3560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
3561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_FAILED, out.rv);
3562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  data->Reset();
3563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
3564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test that partial writes work.
35663345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, PartialWrite) {
3567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Chop the SYN_STREAM frame into 5 chunks.
3568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const int kChunks = 5;
3570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_array<MockWrite> writes(ChopWriteFrame(*req.get(), kChunks));
3571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
3573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
3575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
3576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
3577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
3578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
3581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(kChunks, reads, arraysize(reads),
3582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes.get(), kChunks));
3583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
35843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
3585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunToCompletion(data.get());
3586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
3587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
3588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("hello!", out.response_data);
3590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
3591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// In this test, we enable compression, but get a uncompressed SynReply from
3593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the server.  Verify that teardown is all clean.
35943345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) {
3595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // For this test, we turn on the normal compression.
3596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EnableCompression(true);
3597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> compressed(
3599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ConstructSpdyGet(NULL, 0, true, 1, LOWEST));
36003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> rst(
36013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyRstStream(1, spdy::PROTOCOL_ERROR));
3602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = {
3603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockWrite(*compressed),
36043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*rst),
3605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
3608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
3610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
3611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
36123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0)
3613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
3616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
3617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
3618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
36193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
3620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunToCompletion(data.get());
3621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
36223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  data->Reset();
3624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EnableCompression(false);
3626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
3627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test that the NetLog contains good data for a simple GET request.
36293345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, NetLog) {
36304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  static const char* const kExtraHeaders[] = {
36314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    "user-agent",   "Chrome",
36324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  };
36334a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(kExtraHeaders, 1, false, 1,
36344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                                                   LOWEST));
3635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
3636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
3638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
3640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
3641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
3642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
3643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net::CapturingBoundNetLog log(net::CapturingNetLog::kUnbounded);
3646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
3648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
3649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
36504a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(),
36513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     log.bound(), GetParam());
3652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunToCompletion(data.get());
3653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
3654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
3655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("hello!", out.response_data);
3657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Check that the NetLog was filled reasonably.
3659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This test is intentionally non-specific about the exact ordering of the
3660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // log; instead we just check to make sure that certain events exist, and that
3661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // they are in the right order.
366221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  net::CapturingNetLog::EntryList entries;
366321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  log.GetEntries(&entries);
366421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
366521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  EXPECT_LT(0u, entries.size());
3666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int pos = 0;
366721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  pos = net::ExpectLogContainsSomewhere(entries, 0,
36683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      net::NetLog::PHASE_BEGIN);
367021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
36713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      net::NetLog::PHASE_END);
367321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
36743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      net::NetLog::PHASE_BEGIN);
367621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
36773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      net::NetLog::PHASE_END);
367921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
36803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      net::NetLog::PHASE_BEGIN);
368221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
36833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      net::NetLog::PHASE_END);
36854a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
36864a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // Check that we logged all the headers correctly
36874a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  pos = net::ExpectLogContainsSomewhere(
368821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      entries, 0,
36894a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM,
36904a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      net::NetLog::PHASE_NONE);
369121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  CapturingNetLog::Entry entry = entries[pos];
36924a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  NetLogSpdySynParameter* request_params =
36934a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      static_cast<NetLogSpdySynParameter*>(entry.extra_parameters.get());
36944a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  spdy::SpdyHeaderBlock* headers =
36954a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      request_params->GetHeaders().get();
36964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
36974a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  spdy::SpdyHeaderBlock expected;
36984a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  expected["host"] = "www.google.com";
36994a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  expected["url"] = "/";
37004a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  expected["scheme"] = "http";
37014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  expected["version"] = "HTTP/1.1";
37024a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  expected["method"] = "GET";
37034a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  expected["user-agent"] = "Chrome";
37044a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ(expected.size(), headers->size());
37054a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  spdy::SpdyHeaderBlock::const_iterator end = expected.end();
37064a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  for (spdy::SpdyHeaderBlock::const_iterator it = expected.begin();
37074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      it != end;
37084a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      ++it) {
37094a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    EXPECT_EQ(it->second, (*headers)[it->first]);
37104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
3711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
3712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Since we buffer the IO from the stream to the renderer, this test verifies
3714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// that when we read out the maximum amount of data (e.g. we received 50 bytes
3715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// on the network, but issued a Read for only 5 of those bytes) that the data
3716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// flow still works correctly.
37173345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, BufferFull) {
3718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdyFramer framer;
3719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
3722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // 2 data frames in a single read.
3724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> data_frame_1(
3725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      framer.CreateDataFrame(1, "goodby", 6, spdy::DATA_FLAG_NONE));
3726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> data_frame_2(
3727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      framer.CreateDataFrame(1, "e worl", 6, spdy::DATA_FLAG_NONE));
3728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const spdy::SpdyFrame* data_frames[2] = {
3729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame_1.get(),
3730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame_2.get(),
3731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  char combined_data_frames[100];
3733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int combined_data_frames_len =
3734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CombineFrames(data_frames, arraysize(data_frames),
3735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    combined_data_frames, arraysize(combined_data_frames));
3736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> last_frame(
3737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      framer.CreateDataFrame(1, "d", 1, spdy::DATA_FLAG_FIN));
3738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
3740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
3741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
3742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, ERR_IO_PENDING),  // Force a pause
3743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, combined_data_frames, combined_data_frames_len),
3744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, ERR_IO_PENDING),  // Force a pause
3745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*last_frame),
3746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
3747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
3750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
3751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
3752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback callback;
3755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
37573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
3758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunPreTestSetup();
37593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
3760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
3761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
3762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
3763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
3765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.rv = callback.WaitForResult();
3766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(out.rv, OK);
3767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const HttpResponseInfo* response = trans->GetResponseInfo();
3769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->headers != NULL);
3770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->was_fetched_via_spdy);
3771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.status_line = response->headers->GetStatusLine();
3772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.response_info = *response;  // Make a copy so we can verify.
3773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Read Data
3775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback read_callback;
3776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string content;
3778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  do {
3779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Read small chunks at a time.
3780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const int kSmallReadSize = 3;
3781513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    rv = trans->Read(buf, kSmallReadSize, &read_callback);
3783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (rv == net::ERR_IO_PENDING) {
3784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      data->CompleteRead();
3785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      rv = read_callback.WaitForResult();
3786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
3787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (rv > 0) {
3788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      content.append(buf->data(), rv);
3789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else if (rv < 0) {
3790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED();
3791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
3792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } while (rv > 0);
3793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.response_data.swap(content);
3795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // MockClientSocketFactory) are still alive.
3798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->RunAllPending();
3799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Verify that we consumed all test data.
3801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.VerifyDataConsumed();
3802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
3804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("goodbye world", out.response_data);
3806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
3807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
38083345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ConnectFailureFallbackToHttp) {
3809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockConnect connects[]  = {
3810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockConnect(true, ERR_NAME_NOT_RESOLVED),
3811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockConnect(false, ERR_NAME_NOT_RESOLVED),
3812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockConnect(true, ERR_INTERNET_DISCONNECTED),
3813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockConnect(false, ERR_INTERNET_DISCONNECTED)
3814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3815c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t index = 0; index < arraysize(connects); ++index) {
3817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<spdy::SpdyFrame> req(
3818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockWrite writes[] = {
3820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CreateMockWrite(*req),
3821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      MockWrite(true, 0, 0)  // EOF
3822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    };
3823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
3825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead reads[] = {
3827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CreateMockRead(*resp),
3828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CreateMockRead(*body),
3829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      MockRead(true, 0, 0)  // EOF
3830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    };
3831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_refptr<DelayedSocketData> data(
3833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        new DelayedSocketData(connects[index], 1, reads, arraysize(reads),
3834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              writes, arraysize(writes)));
3835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NormalSpdyTransactionHelper helper(CreateGetRequest(),
38363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                       BoundNetLog(), GetParam());
3837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    helper.RunPreTestSetup();
38383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    helper.AddData(data.get());
3839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Set up http fallback data.
3841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead http_fallback_data[] = {
3842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      MockRead("HTTP/1.1 200 OK\r\n\r\n"),
3843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      MockRead("hello world!!!"),
3844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      MockRead(true, OK),
3845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    };
3846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<StaticSocketDataProvider> http_fallback(
3848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          new StaticSocketDataProvider(http_fallback_data,
3849c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                       arraysize(http_fallback_data),
3850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                       NULL, 0));
3851c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    helper.AddDataNoSSL(http_fallback.get());
3852c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HttpNetworkTransaction* trans = helper.trans();
3853c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TestCompletionCallback callback;
3854c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
3856c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(rv, ERR_IO_PENDING);
3857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    rv = callback.WaitForResult();
3858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const HttpResponseInfo* response = trans->GetResponseInfo();
38593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (GetParam() == SPDYNOSSL || GetParam() == SPDYSSL) {
38603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ASSERT_TRUE(response == NULL);
38613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return;
38623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
38633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (GetParam() != SPDYNPN)
38643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NOTREACHED();
3865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ASSERT_TRUE(response != NULL);
3866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ASSERT_TRUE(response->headers != NULL);
3867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string response_data;
3869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    rv = ReadTransaction(trans, &response_data);
3870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(OK, rv);
3871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3872c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(!response->was_fetched_via_spdy);
3873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(!response->was_npn_negotiated);
3874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(response->was_alternate_protocol_available);
3875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(http_fallback->at_read_eof());
3876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(0u, data->read_index());
3877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(0u, data->write_index());
3878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ("hello world!!!", response_data);
3879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
3880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
3881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Verify that basic buffering works; when multiple data frames arrive
3883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// at the same time, ensure that we don't notify a read completion for
3884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// each data frame individually.
38853345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, Buffering) {
3886c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdyFramer framer;
3887c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
3890c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3891c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // 4 data frames in a single read.
3892c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> data_frame(
3893c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE));
3894c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> data_frame_fin(
3895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_FIN));
3896c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const spdy::SpdyFrame* data_frames[4] = {
3897c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame.get(),
3898c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame.get(),
3899c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame.get(),
3900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame_fin.get()
3901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3902c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  char combined_data_frames[100];
3903c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int combined_data_frames_len =
3904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CombineFrames(data_frames, arraysize(data_frames),
3905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    combined_data_frames, arraysize(combined_data_frames));
3906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3907c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
3908c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
3909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
3910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, ERR_IO_PENDING),  // Force a pause
3911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, combined_data_frames, combined_data_frames_len),
3912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
3913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
3916c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
3917c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
3918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3919c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
39203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
3921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunPreTestSetup();
39223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
3923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
3924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback callback;
3926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
3927c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
3928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
3930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.rv = callback.WaitForResult();
3931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(out.rv, OK);
3932c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const HttpResponseInfo* response = trans->GetResponseInfo();
3934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->headers != NULL);
3935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->was_fetched_via_spdy);
3936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.status_line = response->headers->GetStatusLine();
3937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.response_info = *response;  // Make a copy so we can verify.
3938c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3939c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Read Data
3940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback read_callback;
3941c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3942c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string content;
3943c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int reads_completed = 0;
3944c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  do {
3945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Read small chunks at a time.
3946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const int kSmallReadSize = 14;
3947513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3948c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    rv = trans->Read(buf, kSmallReadSize, &read_callback);
3949c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (rv == net::ERR_IO_PENDING) {
3950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      data->CompleteRead();
3951c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      rv = read_callback.WaitForResult();
3952c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
3953c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (rv > 0) {
3954c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_EQ(kSmallReadSize, rv);
3955c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      content.append(buf->data(), rv);
3956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else if (rv < 0) {
3957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      FAIL() << "Unexpected read error: " << rv;
3958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
3959c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    reads_completed++;
3960c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } while (rv > 0);
3961c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3962c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(3, reads_completed);  // Reads are: 14 bytes, 14 bytes, 0 bytes.
3963c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3964c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.response_data.swap(content);
3965c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3966c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3967c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // MockClientSocketFactory) are still alive.
3968c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->RunAllPending();
3969c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Verify that we consumed all test data.
3971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.VerifyDataConsumed();
3972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3973c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
3974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3975c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
3977c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3978c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Verify the case where we buffer data but read it after it has been buffered.
39793345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, BufferedAll) {
3980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdyFramer framer;
3981c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3983c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
3984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // 5 data frames in a single read.
3986c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> syn_reply(
3987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ConstructSpdyGetSynReply(NULL, 0, 1));
3988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  syn_reply->set_flags(spdy::CONTROL_FLAG_NONE);  // turn off FIN bit
3989c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> data_frame(
3990c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE));
3991c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> data_frame_fin(
3992c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_FIN));
3993c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const spdy::SpdyFrame* frames[5] = {
3994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    syn_reply.get(),
3995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame.get(),
3996c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame.get(),
3997c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame.get(),
3998c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame_fin.get()
3999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
4000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  char combined_frames[200];
4001c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int combined_frames_len =
4002c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CombineFrames(frames, arraysize(frames),
4003c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    combined_frames, arraysize(combined_frames));
4004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
4006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, combined_frames, combined_frames_len),
4007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
4008c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
4009c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
4011c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
4012c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
4013c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4014c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
40153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
4016c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunPreTestSetup();
40173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
4018c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
4019c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4020c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback callback;
4021c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
4022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
4023c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4024c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
4025c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.rv = callback.WaitForResult();
4026c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(out.rv, OK);
4027c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4028c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const HttpResponseInfo* response = trans->GetResponseInfo();
4029c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->headers != NULL);
4030c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->was_fetched_via_spdy);
4031c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.status_line = response->headers->GetStatusLine();
4032c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.response_info = *response;  // Make a copy so we can verify.
4033c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4034c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Read Data
4035c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback read_callback;
4036c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4037c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string content;
4038c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int reads_completed = 0;
4039c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  do {
4040c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Read small chunks at a time.
4041c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const int kSmallReadSize = 14;
4042513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4043c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    rv = trans->Read(buf, kSmallReadSize, &read_callback);
4044c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (rv > 0) {
4045c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_EQ(kSmallReadSize, rv);
4046c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      content.append(buf->data(), rv);
4047c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else if (rv < 0) {
4048c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      FAIL() << "Unexpected read error: " << rv;
4049c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
4050c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    reads_completed++;
4051c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } while (rv > 0);
4052c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4053c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(3, reads_completed);
4054c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4055c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.response_data.swap(content);
4056c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4057c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4058c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // MockClientSocketFactory) are still alive.
4059c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->RunAllPending();
4060c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4061c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Verify that we consumed all test data.
4062c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.VerifyDataConsumed();
4063c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4064c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
4065c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4066c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("messagemessagemessagemessage", out.response_data);
4067c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
4068c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4069c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Verify the case where we buffer data and close the connection.
40703345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
4071c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdyFramer framer;
4072c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4073c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4074c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
4075c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4076c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // All data frames in a single read.
4077c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // NOTE: We don't FIN the stream.
4078c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> data_frame(
4079c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE));
4080c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const spdy::SpdyFrame* data_frames[4] = {
4081c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame.get(),
4082c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame.get(),
4083c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame.get(),
4084c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame.get()
4085c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
4086c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  char combined_data_frames[100];
4087c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int combined_data_frames_len =
4088c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CombineFrames(data_frames, arraysize(data_frames),
4089c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    combined_data_frames, arraysize(combined_data_frames));
4090c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4091c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
4092c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
4093c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, ERR_IO_PENDING),  // Force a wait
4094c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, combined_data_frames, combined_data_frames_len),
4095c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
4096c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
4097c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4098c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
4099c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
4100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
4101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
41033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
4104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunPreTestSetup();
41053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
4106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
4107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback callback;
4109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
4111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
4112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
4114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.rv = callback.WaitForResult();
4115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(out.rv, OK);
4116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const HttpResponseInfo* response = trans->GetResponseInfo();
4118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->headers != NULL);
4119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->was_fetched_via_spdy);
4120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.status_line = response->headers->GetStatusLine();
4121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.response_info = *response;  // Make a copy so we can verify.
4122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Read Data
4124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback read_callback;
4125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string content;
4127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int reads_completed = 0;
4128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  do {
4129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Read small chunks at a time.
4130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const int kSmallReadSize = 14;
4131513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    rv = trans->Read(buf, kSmallReadSize, &read_callback);
4133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (rv == net::ERR_IO_PENDING) {
4134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      data->CompleteRead();
4135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      rv = read_callback.WaitForResult();
4136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
4137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (rv > 0) {
4138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      content.append(buf->data(), rv);
4139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else if (rv < 0) {
4140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // This test intentionally closes the connection, and will get an error.
4141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
4142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
4143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
4144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    reads_completed++;
4145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } while (rv > 0);
4146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(0, reads_completed);
4148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.response_data.swap(content);
4150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // MockClientSocketFactory) are still alive.
4153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->RunAllPending();
4154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Verify that we consumed all test data.
4156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.VerifyDataConsumed();
4157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
4158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Verify the case where we buffer data and cancel the transaction.
41603345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, BufferedCancelled) {
4161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdyFramer framer;
4162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
4165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // NOTE: We don't FIN the stream.
4167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> data_frame(
4168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE));
4169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
4172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
4173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, ERR_IO_PENDING),  // Force a wait
4174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*data_frame),
4175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
4176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
4177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
4179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
4180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
4181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
41833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
4184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunPreTestSetup();
41853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
4186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
4187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback callback;
4188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
4190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
4191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
4193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.rv = callback.WaitForResult();
4194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(out.rv, OK);
4195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const HttpResponseInfo* response = trans->GetResponseInfo();
4197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->headers != NULL);
4198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->was_fetched_via_spdy);
4199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.status_line = response->headers->GetStatusLine();
4200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.response_info = *response;  // Make a copy so we can verify.
4201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Read Data
4203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback read_callback;
4204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  do {
4206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const int kReadSize = 256;
4207513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kReadSize));
4208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    rv = trans->Read(buf, kReadSize, &read_callback);
4209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (rv == net::ERR_IO_PENDING) {
4210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Complete the read now, which causes buffering to start.
4211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      data->CompleteRead();
4212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Destroy the transaction, causing the stream to get cancelled
4213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // and orphaning the buffered IO task.
4214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      helper.ResetTrans();
4215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
4216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
4217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We shouldn't get here in this test.
4218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    FAIL() << "Unexpected read: " << rv;
4219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } while (rv > 0);
4220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Flush the MessageLoop; this will cause the buffered IO task
4222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // to run for the final time.
4223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->RunAllPending();
4224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Verify that we consumed all test data.
4226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.VerifyDataConsumed();
4227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
4228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test that if the server requests persistence of settings, that we save
4230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the settings in the SpdySettingsStorage.
42313345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
4232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const SpdyHeaderInfo kSynReplyInfo = {
4233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SYN_REPLY,                              // Syn Reply
4234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    1,                                            // Stream ID
4235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0,                                            // Associated Stream ID
42363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    net::ConvertRequestPriorityToSpdyPriority(LOWEST),
42373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                  // Priority
4238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::CONTROL_FLAG_NONE,                      // Control Flags
4239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    false,                                        // Compressed
4240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::INVALID,                                // Status
4241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NULL,                                         // Data
4242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0,                                            // Data Length
4243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::DATA_FLAG_NONE                          // Data Flags
4244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
4245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const char* const kExtraHeaders[] = {
4246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "status",   "200",
4247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "version",  "HTTP/1.1"
4248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
4249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
42513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
42523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
4253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Verify that no settings exist initially.
42553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HostPortPair host_port_pair("www.google.com", helper.port());
4256dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4257dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(spdy_session_pool->spdy_settings().Get(host_port_pair).empty());
4258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Construct the request.
4260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
4262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Construct the reply.
4264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> reply(
4265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ConstructSpdyPacket(kSynReplyInfo,
4266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        kExtraHeaders,
4267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        arraysize(kExtraHeaders) / 2,
4268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        NULL,
4269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        0));
4270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  unsigned int kSampleId1 = 0x1;
4272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  unsigned int kSampleValue1 = 0x0a0a0a0a;
4273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  unsigned int kSampleId2 = 0x2;
4274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  unsigned int kSampleValue2 = 0x0b0b0b0b;
4275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  unsigned int kSampleId3 = 0xababab;
4276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  unsigned int kSampleValue3 = 0x0c0c0c0c;
4277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> settings_frame;
4278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
4279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Construct the SETTINGS frame.
4280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SpdySettings settings;
4281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SettingsFlagsAndId setting(0);
4282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // First add a persisted setting
4283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST);
4284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    setting.set_id(kSampleId1);
4285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    settings.push_back(std::make_pair(setting, kSampleValue1));
4286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Next add a non-persisted setting
4287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    setting.set_flags(0);
4288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    setting.set_id(kSampleId2);
4289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    settings.push_back(std::make_pair(setting, kSampleValue2));
4290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Next add another persisted setting
4291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST);
4292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    setting.set_id(kSampleId3);
4293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    settings.push_back(std::make_pair(setting, kSampleValue3));
4294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    settings_frame.reset(ConstructSpdySettings(settings));
4295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
4296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
4299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*reply),
4300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
4301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*settings_frame),
4302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
4303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
4304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
4306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
4307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
43083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
43093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunDefaultTest();
43103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
4311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
4312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
4313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("hello!", out.response_data);
4315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
4317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Verify we had two persisted settings.
4318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SpdySettings saved_settings =
4319dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        spdy_session_pool->spdy_settings().Get(host_port_pair);
4320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ASSERT_EQ(2u, saved_settings.size());
4321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Verify the first persisted setting.
4323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SpdySetting setting = saved_settings.front();
4324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    saved_settings.pop_front();
4325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags());
4326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(kSampleId1, setting.first.id());
4327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(kSampleValue1, setting.second);
4328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Verify the second persisted setting.
4330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    setting = saved_settings.front();
4331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    saved_settings.pop_front();
4332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags());
4333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(kSampleId3, setting.first.id());
4334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(kSampleValue3, setting.second);
4335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
4336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
4337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test that when there are settings saved that they are sent back to the
4339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// server upon session establishment.
43403345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, SettingsPlayback) {
4341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const SpdyHeaderInfo kSynReplyInfo = {
4342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SYN_REPLY,                              // Syn Reply
4343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    1,                                            // Stream ID
4344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0,                                            // Associated Stream ID
43453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    net::ConvertRequestPriorityToSpdyPriority(LOWEST),
43463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                  // Priority
4347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::CONTROL_FLAG_NONE,                      // Control Flags
4348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    false,                                        // Compressed
4349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::INVALID,                                // Status
4350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NULL,                                         // Data
4351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0,                                            // Data Length
4352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::DATA_FLAG_NONE                          // Data Flags
4353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
4354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const char* kExtraHeaders[] = {
4355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "status",   "200",
4356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "version",  "HTTP/1.1"
4357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
4358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
43603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
43613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
4362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Verify that no settings exist initially.
43643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HostPortPair host_port_pair("www.google.com", helper.port());
4365dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4366dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(spdy_session_pool->spdy_settings().Get(host_port_pair).empty());
4367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  unsigned int kSampleId1 = 0x1;
4369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  unsigned int kSampleValue1 = 0x0a0a0a0a;
4370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  unsigned int kSampleId2 = 0xababab;
4371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  unsigned int kSampleValue2 = 0x0c0c0c0c;
4372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Manually insert settings into the SpdySettingsStorage here.
4373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
4374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SpdySettings settings;
4375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SettingsFlagsAndId setting(0);
4376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // First add a persisted setting
4377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST);
4378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    setting.set_id(kSampleId1);
4379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    settings.push_back(std::make_pair(setting, kSampleValue1));
4380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Next add another persisted setting
4381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST);
4382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    setting.set_id(kSampleId2);
4383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    settings.push_back(std::make_pair(setting, kSampleValue2));
4384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4385dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    spdy_session_pool->mutable_spdy_settings()->Set(host_port_pair, settings);
4386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
4387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4388dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(2u, spdy_session_pool->spdy_settings().Get(host_port_pair).size());
4389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Construct the SETTINGS frame.
4391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const spdy::SpdySettings& settings =
4392dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      spdy_session_pool->spdy_settings().Get(host_port_pair);
4393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
4394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Construct the request.
4396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = {
4399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockWrite(*settings_frame),
4400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockWrite(*req),
4401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
4402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Construct the reply.
4404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> reply(
4405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ConstructSpdyPacket(kSynReplyInfo,
4406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        kExtraHeaders,
4407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        arraysize(kExtraHeaders) / 2,
4408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        NULL,
4409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        0));
4410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
4413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*reply),
4414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
4415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
4416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
4417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
4419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(2, reads, arraysize(reads),
4420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
44213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
44223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunDefaultTest();
44233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
4424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
4425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
4426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("hello!", out.response_data);
4428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
4430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Verify we had two persisted settings.
4431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SpdySettings saved_settings =
4432dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        spdy_session_pool->spdy_settings().Get(host_port_pair);
4433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ASSERT_EQ(2u, saved_settings.size());
4434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Verify the first persisted setting.
4436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SpdySetting setting = saved_settings.front();
4437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    saved_settings.pop_front();
4438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags());
4439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(kSampleId1, setting.first.id());
4440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(kSampleValue1, setting.second);
4441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Verify the second persisted setting.
4443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    setting = saved_settings.front();
4444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    saved_settings.pop_front();
4445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags());
4446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(kSampleId2, setting.first.id());
4447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(kSampleValue2, setting.second);
4448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
4449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
4450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
44513345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
4452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
4454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> go_away(ConstructSpdyGoAway());
4456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
4457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*go_away),
44583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0),  // EOF
4459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
4460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
4462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
4463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
4464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
44653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
44663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data);
4467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunToCompletion(data.get());
4468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
44693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_ABORTED, out.rv);
4470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
4471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
44723345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) {
4473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
4475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
4478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
4479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(false, 0, 0)  // EOF
4480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
4481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
4483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
4484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
4485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BoundNetLog log;
4486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
44873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     log, GetParam());
4488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunPreTestSetup();
44893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
4490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
4491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback callback;
4493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out;
4494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.rv = trans->Start(&CreateGetRequest(), &callback, log);
4495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(out.rv, ERR_IO_PENDING);
4497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.rv = callback.WaitForResult();
4498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(out.rv, OK);
4499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const HttpResponseInfo* response = trans->GetResponseInfo();
4501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->headers != NULL);
4502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->was_fetched_via_spdy);
4503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.rv = ReadTransaction(trans, &out.response_data);
4504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv);
4505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Verify that we consumed all test data.
4507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.VerifyDataConsumed();
4508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
4509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
45103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Test to make sure we can correctly connect through a proxy.
45113345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ProxyConnect) {
45123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
45133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
45143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.session_deps().reset(new SpdySessionDependencies(
45153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
4516513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  helper.SetSession(make_scoped_refptr(
4517513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
45183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
45193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans = helper.trans();
45203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
45213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
45223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                           "Host: www.google.com\r\n"
45233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                           "Proxy-Connection: keep-alive\r\n\r\n"};
45243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
45253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                           "Host: www.google.com\r\n"
45263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                           "Proxy-Connection: keep-alive\r\n\r\n"};
45273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
45283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
45293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
45303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
45313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
45323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes_SPDYNPN[] = {
45333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockWrite(false, kConnect443, arraysize(kConnect443) - 1, 0),
45343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req, 2),
45353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
45363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads_SPDYNPN[] = {
45373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(false, kHTTP200, arraysize(kHTTP200) - 1, 1),
45383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp, 3),
45393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body.get(), 4),
45403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0, 5),
45413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
45423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
45433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes_SPDYSSL[] = {
45443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockWrite(false, kConnect80, arraysize(kConnect80) - 1, 0),
45453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req, 2),
45463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
45473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads_SPDYSSL[] = {
45483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(false, kHTTP200, arraysize(kHTTP200) - 1, 1),
45493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp, 3),
45503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body.get(), 4),
45513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0, 5),
45523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
45533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
45543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes_SPDYNOSSL[] = {
45553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req, 0),
45563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
45573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
45583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads_SPDYNOSSL[] = {
45593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp, 1),
45603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body.get(), 2),
45613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0, 3),
45623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
45633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
45643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data;
45653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  switch(GetParam()) {
45663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case SPDYNOSSL:
45673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      data = new OrderedSocketData(reads_SPDYNOSSL,
45683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   arraysize(reads_SPDYNOSSL),
45693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   writes_SPDYNOSSL,
45703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   arraysize(writes_SPDYNOSSL));
45713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      break;
45723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case SPDYSSL:
45733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      data = new OrderedSocketData(reads_SPDYSSL, arraysize(reads_SPDYSSL),
45743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   writes_SPDYSSL, arraysize(writes_SPDYSSL));
45753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      break;
45763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case SPDYNPN:
45773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      data = new OrderedSocketData(reads_SPDYNPN, arraysize(reads_SPDYNPN),
45783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   writes_SPDYNPN, arraysize(writes_SPDYNPN));
45793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      break;
45803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    default:
45813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NOTREACHED();
45823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
45833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
45843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
45853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
45863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
45873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
45883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_IO_PENDING, rv);
45893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
45903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  rv = callback.WaitForResult();
45913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(0, rv);
45923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
45933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the SYN_REPLY.
45943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response = *trans->GetResponseInfo();
45953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response.headers != NULL);
45963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
45973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
45983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string response_data;
45993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(OK, ReadTransaction(trans, &response_data));
46003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("hello!", response_data);
46013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
46023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
46033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
46043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Test to make sure we can correctly connect through a proxy to www.google.com,
46053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// if there already exists a direct spdy connection to www.google.com. See
46063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// http://crbug.com/49874
46073345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
46083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // When setting up the first transaction, we store the SpdySessionPool so that
46093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // we can use the same pool in the second transaction.
46103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
46113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
46123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
46133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Use a proxy service which returns a proxy fallback list from DIRECT to
46143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // myproxy:70. For this test there will be no fallback, so it is equivalent
46153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // to simply DIRECT. The reason for appending the second proxy is to verify
46163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // that the session pool key used does is just "DIRECT".
46173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.session_deps().reset(new SpdySessionDependencies(
46183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
4619513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  helper.SetSession(make_scoped_refptr(
4620513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
46213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4622731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
46233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
46243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
46253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Construct and send a simple GET request.
46263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
46273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
46283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req, 1),
46293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
46303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
46313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
46323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
46333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
46343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp, 2),
46353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body, 3),
46363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 4),  // Force a pause
46373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 5)  // EOF
46383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
46393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data(
46403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(reads, arraysize(reads),
46413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes, arraysize(writes)));
46423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
46433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans = helper.trans();
46443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
46453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
46463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TransactionHelperResult out;
46473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
46483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
46493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(out.rv, ERR_IO_PENDING);
46503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = callback.WaitForResult();
46513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(out.rv, OK);
46523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
46533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HttpResponseInfo* response = trans->GetResponseInfo();
46543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response->headers != NULL);
46553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response->was_fetched_via_spdy);
46563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = ReadTransaction(trans, &out.response_data);
46573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, out.rv);
46583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.status_line = response->headers->GetStatusLine();
46593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
46603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("hello!", out.response_data);
46613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
46623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Check that the SpdySession is still in the SpdySessionPool.
46633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HostPortPair host_port_pair("www.google.com", helper.port());
46643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HostPortProxyPair session_pool_key_direct(
46653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      host_port_pair, ProxyServer::Direct());
46663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(spdy_session_pool->HasSession(session_pool_key_direct));
46673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HostPortProxyPair session_pool_key_proxy(
46683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      host_port_pair,
46693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP));
46703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_FALSE(spdy_session_pool->HasSession(session_pool_key_proxy));
46713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
46723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Set up data for the proxy connection.
46733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
46743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                           "Host: www.google.com\r\n"
46753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                           "Proxy-Connection: keep-alive\r\n\r\n"};
46763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
46773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                           "Host: www.google.com\r\n"
46783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                           "Proxy-Connection: keep-alive\r\n\r\n"};
46793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
46803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(
46813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      "http://www.google.com/foo.dat", false, 1, LOWEST));
46823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 1));
46833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(1, true));
46843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
46853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes_SPDYNPN[] = {
46863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockWrite(false, kConnect443, arraysize(kConnect443) - 1, 0),
46873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req2, 2),
46883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
46893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads_SPDYNPN[] = {
46903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(false, kHTTP200, arraysize(kHTTP200) - 1, 1),
46913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp2, 3),
46923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body2, 4),
46933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 5)  // EOF
46943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
46953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
46963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes_SPDYNOSSL[] = {
46973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req2, 0),
46983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
46993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads_SPDYNOSSL[] = {
47003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp2, 1),
47013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body2, 2),
47023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 3)  // EOF
47033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
47043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
47053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes_SPDYSSL[] = {
47063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockWrite(false, kConnect80, arraysize(kConnect80) - 1, 0),
47073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req2, 2),
47083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
47093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads_SPDYSSL[] = {
47103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(false, kHTTP200, arraysize(kHTTP200) - 1, 1),
47113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp2, 3),
47123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body2, 4),
47133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0, 5),
47143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
47153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
47163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data_proxy;
47173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  switch(GetParam()) {
47183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case SPDYNPN:
47193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      data_proxy = new OrderedSocketData(reads_SPDYNPN,
47203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                         arraysize(reads_SPDYNPN),
47213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                         writes_SPDYNPN,
47223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                         arraysize(writes_SPDYNPN));
47233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      break;
47243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case SPDYNOSSL:
47253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      data_proxy = new OrderedSocketData(reads_SPDYNOSSL,
47263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                         arraysize(reads_SPDYNOSSL),
47273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                         writes_SPDYNOSSL,
47283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                         arraysize(writes_SPDYNOSSL));
47293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      break;
47303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case SPDYSSL:
47313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      data_proxy = new OrderedSocketData(reads_SPDYSSL,
47323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                         arraysize(reads_SPDYSSL),
47333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                         writes_SPDYSSL,
47343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                         arraysize(writes_SPDYSSL));
47353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      break;
47363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    default:
47373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NOTREACHED();
47383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
47393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
47403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Create another request to www.google.com, but this time through a proxy.
47413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo request_proxy;
47423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request_proxy.method = "GET";
47433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request_proxy.url = GURL("http://www.google.com/foo.dat");
47443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request_proxy.load_flags = 0;
4745731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  scoped_ptr<SpdySessionDependencies> ssd_proxy(new SpdySessionDependencies());
47463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Ensure that this transaction uses the same SpdySessionPool.
4747513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_refptr<HttpNetworkSession> session_proxy(
4748513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      SpdySessionDependencies::SpdyCreateSession(ssd_proxy.get()));
47493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper_proxy(request_proxy,
47503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                           BoundNetLog(), GetParam());
4751731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  HttpNetworkSessionPeer session_peer(session_proxy);
4752731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  session_peer.SetProxyService(
4753731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
47543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper_proxy.session_deps().swap(ssd_proxy);
47553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper_proxy.SetSession(session_proxy);
47563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper_proxy.RunPreTestSetup();
47573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper_proxy.AddData(data_proxy.get());
47583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
47593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans_proxy = helper_proxy.trans();
47603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback_proxy;
47613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans_proxy->Start(&request_proxy, &callback_proxy, BoundNetLog());
47623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_IO_PENDING, rv);
47633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  rv = callback_proxy.WaitForResult();
47643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(0, rv);
47653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
47663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo();
47673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response_proxy.headers != NULL);
47683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response_proxy.headers->GetStatusLine());
47693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
47703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string response_data;
47713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(OK, ReadTransaction(trans_proxy, &response_data));
47723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("hello!", response_data);
47733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
47743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->CompleteRead();
47753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper_proxy.VerifyDataConsumed();
47763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
47773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
47783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
47793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// on a new connection, if the connection was previously known to be good.
47803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// This can happen when a server reboots without saying goodbye, or when
47813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// we're behind a NAT that masked the RST.
47823345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
47833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
47843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
47853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
47863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp),
47873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body),
47883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING),
47893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_CONNECTION_RESET),
47903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
47913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
47923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads2[] = {
47933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp),
47943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body),
47953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0)  // EOF
47963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
47973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
47983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // This test has a couple of variants.
47993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  enum {
48003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Induce the RST while waiting for our transaction to send.
48013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    VARIANT_RST_DURING_SEND_COMPLETION,
48023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Induce the RST while waiting for our transaction to read.
48033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // In this case, the send completed - everything copied into the SNDBUF.
48043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    VARIANT_RST_DURING_READ_COMPLETION
48053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
48063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
48073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (int variant = VARIANT_RST_DURING_SEND_COMPLETION;
48083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       variant <= VARIANT_RST_DURING_READ_COMPLETION;
48093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       ++variant) {
48103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    scoped_refptr<DelayedSocketData> data1(
48113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        new DelayedSocketData(1, reads, arraysize(reads),
48123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                              NULL, 0));
48133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
48143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    scoped_refptr<DelayedSocketData> data2(
48153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        new DelayedSocketData(1, reads2, arraysize(reads2),
48163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                               NULL, 0));
48173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
48183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    NormalSpdyTransactionHelper helper(CreateGetRequest(),
48193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                       BoundNetLog(), GetParam());
48203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    helper.AddData(data1.get());
48213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    helper.AddData(data2.get());
48223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    helper.RunPreTestSetup();
48233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
48243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    for (int i = 0; i < 2; ++i) {
48253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      scoped_ptr<HttpNetworkTransaction> trans(
48263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          new HttpNetworkTransaction(helper.session()));
48273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
48283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      TestCompletionCallback callback;
48293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
48303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      EXPECT_EQ(ERR_IO_PENDING, rv);
48313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // On the second transaction, we trigger the RST.
48323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (i == 1) {
48333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        if (variant == VARIANT_RST_DURING_READ_COMPLETION) {
48343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          // Writes to the socket complete asynchronously on SPDY by running
48353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          // through the message loop.  Complete the write here.
48363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          MessageLoop::current()->RunAllPending();
48373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        }
48383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
48393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        // Now schedule the ERR_CONNECTION_RESET.
48403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        EXPECT_EQ(3u, data1->read_index());
48413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        data1->CompleteRead();
48423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        EXPECT_EQ(4u, data1->read_index());
48433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      }
48443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      rv = callback.WaitForResult();
48453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      EXPECT_EQ(OK, rv);
48463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
48473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      const HttpResponseInfo* response = trans->GetResponseInfo();
48483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ASSERT_TRUE(response != NULL);
48493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      EXPECT_TRUE(response->headers != NULL);
48503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      EXPECT_TRUE(response->was_fetched_via_spdy);
48513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      std::string response_data;
48523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      rv = ReadTransaction(trans.get(), &response_data);
48533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      EXPECT_EQ(OK, rv);
48543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
48553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      EXPECT_EQ("hello!", response_data);
48563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
48573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
48583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    helper.VerifyDataConsumed();
48593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
48603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
4861731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
4862731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Test that turning SPDY on and off works properly.
4863731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickTEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) {
4864731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  net::HttpStreamFactory::set_spdy_enabled(true);
4865731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4866731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  MockWrite spdy_writes[] = { CreateMockWrite(*req) };
4867731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
4868731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4869731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4870731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  MockRead spdy_reads[] = {
4871731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    CreateMockRead(*resp),
4872731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    CreateMockRead(*body),
4873731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    MockRead(true, 0, 0)  // EOF
4874731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  };
4875731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
4876731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  scoped_refptr<DelayedSocketData> data(
4877513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      new DelayedSocketData(1,
4878513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                            spdy_reads, arraysize(spdy_reads),
4879731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                            spdy_writes, arraysize(spdy_writes)));
4880731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
4881731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                     BoundNetLog(), GetParam());
4882731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  helper.RunToCompletion(data.get());
4883731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  TransactionHelperResult out = helper.output();
4884731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EXPECT_EQ(OK, out.rv);
4885731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4886731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EXPECT_EQ("hello!", out.response_data);
4887731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
4888731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  net::HttpStreamFactory::set_spdy_enabled(false);
4889731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  MockRead http_reads[] = {
4890731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4891731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    MockRead("hello from http"),
4892731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    MockRead(false, OK),
4893731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  };
4894731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  scoped_refptr<DelayedSocketData> data2(
4895731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      new DelayedSocketData(1, http_reads, arraysize(http_reads),
4896731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                            NULL, 0));
4897731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  NormalSpdyTransactionHelper helper2(CreateGetRequest(),
4898731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                     BoundNetLog(), GetParam());
4899731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  helper2.SetSpdyDisabled();
4900731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  helper2.RunToCompletion(data2.get());
4901731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  TransactionHelperResult out2 = helper2.output();
4902731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EXPECT_EQ(OK, out2.rv);
4903731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", out2.status_line);
4904731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EXPECT_EQ("hello from http", out2.response_data);
4905731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
4906731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  net::HttpStreamFactory::set_spdy_enabled(true);
4907731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
4908513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
4909513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Tests that Basic authentication works over SPDY
4910513209b27ff55e2841eac0e4120199c23acce758Ben MurdochTEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) {
4911513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  net::HttpStreamFactory::set_spdy_enabled(true);
4912513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
4913513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // The first request will be a bare GET, the second request will be a
4914513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // GET with an Authorization header.
4915513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_ptr<spdy::SpdyFrame> req_get(
4916513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4917513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const char* const kExtraAuthorizationHeaders[] = {
4918513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    "authorization",
4919513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    "Basic Zm9vOmJhcg==",
4920513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  };
4921513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_ptr<spdy::SpdyFrame> req_get_authorization(
4922513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      ConstructSpdyGet(
4923201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch          kExtraAuthorizationHeaders,
4924201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch          arraysize(kExtraAuthorizationHeaders) / 2,
4925513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          false, 3, LOWEST));
4926513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  MockWrite spdy_writes[] = {
4927513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    CreateMockWrite(*req_get, 1),
4928513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    CreateMockWrite(*req_get_authorization, 4),
4929513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  };
4930513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
4931513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // The first response is a 401 authentication challenge, and the second
4932513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // response will be a 200 response since the second request includes a valid
4933513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Authorization header.
4934513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const char* const kExtraAuthenticationHeaders[] = {
4935513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    "WWW-Authenticate",
4936513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    "Basic realm=\"MyRealm\""
4937513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  };
4938513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_ptr<spdy::SpdyFrame> resp_authentication(
4939513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      ConstructSpdySynReplyError(
4940513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          "401 Authentication Required",
4941201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch          kExtraAuthenticationHeaders,
4942201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch          arraysize(kExtraAuthenticationHeaders) / 2,
4943513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          1));
4944513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_ptr<spdy::SpdyFrame> body_authentication(
4945513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      ConstructSpdyBodyFrame(1, true));
4946513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_ptr<spdy::SpdyFrame> resp_data(ConstructSpdyGetSynReply(NULL, 0, 3));
4947513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_ptr<spdy::SpdyFrame> body_data(ConstructSpdyBodyFrame(3, true));
4948513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  MockRead spdy_reads[] = {
4949513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    CreateMockRead(*resp_authentication, 2),
4950513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    CreateMockRead(*body_authentication, 3),
4951513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    CreateMockRead(*resp_data, 5),
4952513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    CreateMockRead(*body_data, 6),
4953513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    MockRead(true, 0, 7),
4954513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  };
4955513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
4956513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_refptr<OrderedSocketData> data(
4957513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      new OrderedSocketData(spdy_reads, arraysize(spdy_reads),
4958513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                            spdy_writes, arraysize(spdy_writes)));
4959513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  HttpRequestInfo request(CreateGetRequest());
4960513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  BoundNetLog net_log;
4961513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  NormalSpdyTransactionHelper helper(request, net_log, GetParam());
4962513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
4963513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  helper.RunPreTestSetup();
4964513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  helper.AddData(data.get());
4965513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  HttpNetworkTransaction* trans = helper.trans();
4966513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  TestCompletionCallback callback_start;
4967513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const int rv_start = trans->Start(&request, &callback_start, net_log);
4968513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv_start);
4969513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const int rv_start_complete = callback_start.WaitForResult();
4970513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_EQ(OK, rv_start_complete);
4971513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
4972513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Make sure the response has an auth challenge.
4973513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const HttpResponseInfo* const response_start = trans->GetResponseInfo();
4974513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  ASSERT_TRUE(response_start != NULL);
4975513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  ASSERT_TRUE(response_start->headers != NULL);
4976513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_EQ(401, response_start->headers->response_code());
4977513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_TRUE(response_start->was_fetched_via_spdy);
4978513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  ASSERT_TRUE(response_start->auth_challenge.get() != NULL);
4979513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_FALSE(response_start->auth_challenge->is_proxy);
4980513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_EQ(L"basic", response_start->auth_challenge->scheme);
4981513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_EQ(L"MyRealm", response_start->auth_challenge->realm);
4982513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
4983513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Restart with a username/password.
4984513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const string16 kFoo(ASCIIToUTF16("foo"));
4985513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const string16 kBar(ASCIIToUTF16("bar"));
4986513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  TestCompletionCallback callback_restart;
4987513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const int rv_restart = trans->RestartWithAuth(kFoo, kBar, &callback_restart);
4988513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv_restart);
4989513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const int rv_restart_complete = callback_restart.WaitForResult();
4990513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_EQ(OK, rv_restart_complete);
4991513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // TODO(cbentzel): This is actually the same response object as before, but
4992513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // data has changed.
4993513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
4994513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  ASSERT_TRUE(response_restart != NULL);
4995513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  ASSERT_TRUE(response_restart->headers != NULL);
4996513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_EQ(200, response_restart->headers->response_code());
4997513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
4998513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
4999513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
5000201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushWithHeaders) {
5001201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const unsigned char kPushBodyFrame[] = {
5002201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    0x00, 0x00, 0x00, 0x02,                                      // header, ID
5003201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    0x01, 0x00, 0x00, 0x06,                                      // FIN, length
5004201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed"
5005201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5006201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5007201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5008201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5009201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_body(ConstructSpdyBodyFrame(1, true));
5010201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MockWrite writes[] = {
5011201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockWrite(*stream1_syn, 1),
5012201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5013201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5014201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kInitialHeaders[] = {
5015201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "url",
5016201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "http://www.google.com/foo.dat",
5017201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5018201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kLateHeaders[] = {
5019201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "hello",
5020201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "bye",
5021201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "status",
5022201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "200",
5023201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "version",
5024201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "HTTP/1.1"
5025201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5026201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5027201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    stream2_syn(ConstructSpdyControlFrame(kInitialHeaders,
5028201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                          arraysize(kInitialHeaders) / 2,
5029201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                          false,
5030201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                          2,
5031201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                          LOWEST,
5032201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                          spdy::SYN_STREAM,
5033201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                          spdy::CONTROL_FLAG_NONE,
5034201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                          NULL,
5035201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                          0,
5036201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                          1));
5037201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5038201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_headers(ConstructSpdyControlFrame(kLateHeaders,
5039201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                arraysize(kLateHeaders) / 2,
5040201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                false,
5041201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                2,
5042201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                LOWEST,
5043201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                spdy::HEADERS,
5044201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                spdy::CONTROL_FLAG_NONE,
5045201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                NULL,
5046201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                0,
5047201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                0));
5048201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5049201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5050201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
5051201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MockRead reads[] = {
5052201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_reply, 2),
5053201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream2_syn, 3),
5054201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream2_headers, 4),
5055201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_body, 5, false),
5056201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame),
5057201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch             arraysize(kPushBodyFrame), 6),
5058201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    MockRead(true, ERR_IO_PENDING, 7),  // Force a pause
5059201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5060201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5061201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  HttpResponseInfo response;
5062201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  HttpResponseInfo response2;
5063201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::string expected_push_result("pushed");
5064201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_refptr<OrderedSocketData> data(new OrderedSocketData(
5065201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      reads,
5066201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(reads),
5067201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      writes,
5068201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(writes)));
5069201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  RunServerPushTest(data.get(),
5070201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    &response,
5071201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    &response2,
5072201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    expected_push_result);
5073201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5074201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verify the SYN_REPLY.
5075201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(response.headers != NULL);
5076201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5077201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5078201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verify the pushed stream.
5079201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(response2.headers != NULL);
5080201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5081201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
5082201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5083201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
5084201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // We push a stream and attempt to claim it before the headers come down.
5085201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const unsigned char kPushBodyFrame[] = {
5086201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    0x00, 0x00, 0x00, 0x02,                                      // header, ID
5087201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    0x01, 0x00, 0x00, 0x06,                                      // FIN, length
5088201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed"
5089201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5090201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5091201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5092201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5093201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_body(ConstructSpdyBodyFrame(1, true));
5094201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MockWrite writes[] = {
5095201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockWrite(*stream1_syn, 0, false),
5096201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5097201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5098201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kInitialHeaders[] = {
5099201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "url",
5100201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "http://www.google.com/foo.dat",
5101201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5102201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kLateHeaders[] = {
5103201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "hello",
5104201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "bye",
5105201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "status",
5106201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "200",
5107201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "version",
5108201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "HTTP/1.1"
5109201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5110201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5111201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_syn(ConstructSpdyControlFrame(kInitialHeaders,
5112201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            arraysize(kInitialHeaders) / 2,
5113201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            false,
5114201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            2,
5115201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            LOWEST,
5116201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            spdy::SYN_STREAM,
5117201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            spdy::CONTROL_FLAG_NONE,
5118201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            NULL,
5119201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            0,
5120201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            1));
5121201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5122201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_headers(ConstructSpdyControlFrame(kLateHeaders,
5123201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                arraysize(kLateHeaders) / 2,
5124201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                false,
5125201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                2,
5126201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                LOWEST,
5127201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                spdy::HEADERS,
5128201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                spdy::CONTROL_FLAG_NONE,
5129201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                NULL,
5130201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                0,
5131201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                0));
5132201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5133201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5134201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
5135201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MockRead reads[] = {
5136201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_reply, 1),
5137201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream2_syn, 2),
5138201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_body, 3),
5139201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream2_headers, 4),
5140201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame),
5141201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch             arraysize(kPushBodyFrame), 5),
5142201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    MockRead(true, 0, 5),  // EOF
5143201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5144201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5145201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  HttpResponseInfo response;
5146201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  HttpResponseInfo response2;
5147201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::string expected_push_result("pushed");
5148201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_refptr<DeterministicSocketData> data(new DeterministicSocketData(
5149201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      reads,
5150201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(reads),
5151201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      writes,
5152201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(writes)));
5153201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5154201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
5155201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                     BoundNetLog(), GetParam());
5156201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  helper.SetDeterministic();
5157201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  helper.AddDeterministicData(static_cast<DeterministicSocketData*>(data));
5158201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  helper.RunPreTestSetup();
5159201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5160201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  HttpNetworkTransaction* trans = helper.trans();
5161201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5162201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5163201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // and the body of the primary stream, but before we've received the HEADERS
5164201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // for the pushed stream.
5165201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  data->SetStop(3);
5166201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5167201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Start the transaction.
5168201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  TestCompletionCallback callback;
5169201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
5170201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
5171201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  data->Run();
5172201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  rv = callback.WaitForResult();
5173201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(0, rv);
5174201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5175201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Request the pushed path.  At this point, we've received the push, but the
5176201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // headers are not yet complete.
5177201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<HttpNetworkTransaction> trans2(
5178201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      new HttpNetworkTransaction(helper.session()));
5179201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  rv = trans2->Start(&CreateGetPushRequest(), &callback, BoundNetLog());
5180201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
5181201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  data->RunFor(3);
5182201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MessageLoop::current()->RunAllPending();
5183201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5184201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Read the server push body.
5185201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::string result2;
5186201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  ReadResult(trans2.get(), data.get(), &result2);
5187201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Read the response body.
5188201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::string result;
5189201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  ReadResult(trans, data, &result);
5190201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5191201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verify that we consumed all test data.
5192201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(data->at_read_eof());
5193201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(data->at_write_eof());
5194201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5195201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verify that the received push data is same as the expected push data.
5196201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(result2.compare(expected_push_result), 0)
5197201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      << "Received data: "
5198201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      << result2
5199201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      << "||||| Expected data: "
5200201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      << expected_push_result;
5201201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5202201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verify the SYN_REPLY.
5203201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Copy the response info, because trans goes away.
5204201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  response = *trans->GetResponseInfo();
5205201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  response2 = *trans2->GetResponseInfo();
5206201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5207201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  VerifyStreamsClosed(helper);
5208201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5209201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verify the SYN_REPLY.
5210201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(response.headers != NULL);
5211201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5212201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5213201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verify the pushed stream.
5214201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(response2.headers != NULL);
5215201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5216201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
5217201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5218201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) {
5219201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // We push a stream and attempt to claim it before the headers come down.
5220201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const unsigned char kPushBodyFrame[] = {
5221201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    0x00, 0x00, 0x00, 0x02,                                      // header, ID
5222201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    0x01, 0x00, 0x00, 0x06,                                      // FIN, length
5223201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed"
5224201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5225201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5226201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5227201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5228201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_body(ConstructSpdyBodyFrame(1, true));
5229201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MockWrite writes[] = {
5230201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockWrite(*stream1_syn, 0, false),
5231201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5232201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5233201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kInitialHeaders[] = {
5234201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "url",
5235201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "http://www.google.com/foo.dat",
5236201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5237201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kMiddleHeaders[] = {
5238201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "hello",
5239201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "bye",
5240201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5241201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kLateHeaders[] = {
5242201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "status",
5243201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "200",
5244201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "version",
5245201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "HTTP/1.1"
5246201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5247201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5248201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_syn(ConstructSpdyControlFrame(kInitialHeaders,
5249201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            arraysize(kInitialHeaders) / 2,
5250201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            false,
5251201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            2,
5252201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            LOWEST,
5253201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            spdy::SYN_STREAM,
5254201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            spdy::CONTROL_FLAG_NONE,
5255201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            NULL,
5256201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            0,
5257201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            1));
5258201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5259201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_headers1(ConstructSpdyControlFrame(kMiddleHeaders,
5260201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 arraysize(kMiddleHeaders) / 2,
5261201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 false,
5262201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 2,
5263201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 LOWEST,
5264201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 spdy::HEADERS,
5265201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 spdy::CONTROL_FLAG_NONE,
5266201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 NULL,
5267201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 0,
5268201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 0));
5269201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5270201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_headers2(ConstructSpdyControlFrame(kLateHeaders,
5271201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 arraysize(kLateHeaders) / 2,
5272201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 false,
5273201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 2,
5274201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 LOWEST,
5275201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 spdy::HEADERS,
5276201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 spdy::CONTROL_FLAG_NONE,
5277201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 NULL,
5278201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 0,
5279201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 0));
5280201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5281201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5282201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
5283201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MockRead reads[] = {
5284201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_reply, 1),
5285201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream2_syn, 2),
5286201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_body, 3),
5287201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream2_headers1, 4),
5288201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream2_headers2, 5),
5289201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame),
5290201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch             arraysize(kPushBodyFrame), 6),
5291201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    MockRead(true, 0, 6),  // EOF
5292201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5293201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5294201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  HttpResponseInfo response;
5295201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  HttpResponseInfo response2;
5296201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::string expected_push_result("pushed");
5297201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_refptr<DeterministicSocketData> data(new DeterministicSocketData(
5298201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      reads,
5299201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(reads),
5300201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      writes,
5301201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(writes)));
5302201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5303201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
5304201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                     BoundNetLog(), GetParam());
5305201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  helper.SetDeterministic();
5306201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  helper.AddDeterministicData(static_cast<DeterministicSocketData*>(data));
5307201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  helper.RunPreTestSetup();
5308201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5309201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  HttpNetworkTransaction* trans = helper.trans();
5310201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5311201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5312201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // the first HEADERS frame, and the body of the primary stream, but before
5313201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // we've received the final HEADERS for the pushed stream.
5314201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  data->SetStop(4);
5315201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5316201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Start the transaction.
5317201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  TestCompletionCallback callback;
5318201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
5319201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
5320201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  data->Run();
5321201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  rv = callback.WaitForResult();
5322201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(0, rv);
5323201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5324201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Request the pushed path.  At this point, we've received the push, but the
5325201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // headers are not yet complete.
5326201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<HttpNetworkTransaction> trans2(
5327201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      new HttpNetworkTransaction(helper.session()));
5328201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  rv = trans2->Start(&CreateGetPushRequest(), &callback, BoundNetLog());
5329201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
5330201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  data->RunFor(3);
5331201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MessageLoop::current()->RunAllPending();
5332201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5333201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Read the server push body.
5334201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::string result2;
5335201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  ReadResult(trans2.get(), data, &result2);
5336201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Read the response body.
5337201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::string result;
5338201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  ReadResult(trans, data, &result);
5339201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5340201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verify that we consumed all test data.
5341201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(data->at_read_eof());
5342201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(data->at_write_eof());
5343201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5344201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verify that the received push data is same as the expected push data.
5345201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(result2.compare(expected_push_result), 0)
5346201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      << "Received data: "
5347201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      << result2
5348201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      << "||||| Expected data: "
5349201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      << expected_push_result;
5350201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5351201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verify the SYN_REPLY.
5352201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Copy the response info, because trans goes away.
5353201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  response = *trans->GetResponseInfo();
5354201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  response2 = *trans2->GetResponseInfo();
5355201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5356201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  VerifyStreamsClosed(helper);
5357201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5358201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verify the SYN_REPLY.
5359201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(response.headers != NULL);
5360201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5361201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5362201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verify the pushed stream.
5363201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(response2.headers != NULL);
5364201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5365201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5366201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verify we got all the headers
5367201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(response2.headers->HasHeaderValue(
5368201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      "url",
5369201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      "http://www.google.com/foo.dat"));
5370201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye"));
5371201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200"));
5372201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(response2.headers->HasHeaderValue("version", "HTTP/1.1"));
5373201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
5374201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5375201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochTEST_P(SpdyNetworkTransactionTest, SynReplyWithHeaders) {
5376201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5377201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
5378201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5379201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kInitialHeaders[] = {
5380201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "status",
5381201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "200 OK",
5382201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "version",
5383201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "HTTP/1.1"
5384201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5385201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kLateHeaders[] = {
5386201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "hello",
5387201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "bye",
5388201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5389201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5390201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_reply(ConstructSpdyControlFrame(kInitialHeaders,
5391201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              arraysize(kInitialHeaders) / 2,
5392201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              false,
5393201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              1,
5394201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              LOWEST,
5395201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              spdy::SYN_REPLY,
5396201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              spdy::CONTROL_FLAG_NONE,
5397201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              NULL,
5398201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              0,
5399201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              0));
5400201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5401201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_headers(ConstructSpdyControlFrame(kLateHeaders,
5402201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                arraysize(kLateHeaders) / 2,
5403201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                false,
5404201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                1,
5405201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                LOWEST,
5406201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                spdy::HEADERS,
5407201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                spdy::CONTROL_FLAG_NONE,
5408201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                NULL,
5409201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                0,
5410201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                0));
5411201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame> stream1_body(ConstructSpdyBodyFrame(1, true));
5412201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MockRead reads[] = {
5413201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_reply),
5414201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_headers),
5415201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_body),
5416201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    MockRead(true, 0, 0)  // EOF
5417201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5418201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5419201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_refptr<DelayedSocketData> data(
5420201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
5421201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                            writes, arraysize(writes)));
5422201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
5423201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                     BoundNetLog(), GetParam());
5424201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  helper.RunToCompletion(data.get());
5425201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  TransactionHelperResult out = helper.output();
5426201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(OK, out.rv);
5427201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
5428201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ("hello!", out.response_data);
5429201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
5430201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5431201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochTEST_P(SpdyNetworkTransactionTest, SynReplyWithLateHeaders) {
5432201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5433201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
5434201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5435201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kInitialHeaders[] = {
5436201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "status",
5437201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "200 OK",
5438201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "version",
5439201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "HTTP/1.1"
5440201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5441201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kLateHeaders[] = {
5442201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "hello",
5443201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "bye",
5444201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5445201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5446201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_reply(ConstructSpdyControlFrame(kInitialHeaders,
5447201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              arraysize(kInitialHeaders) / 2,
5448201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              false,
5449201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              1,
5450201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              LOWEST,
5451201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              spdy::SYN_REPLY,
5452201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              spdy::CONTROL_FLAG_NONE,
5453201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              NULL,
5454201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              0,
5455201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              0));
5456201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5457201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_headers(ConstructSpdyControlFrame(kLateHeaders,
5458201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                arraysize(kLateHeaders) / 2,
5459201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                false,
5460201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                1,
5461201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                LOWEST,
5462201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                spdy::HEADERS,
5463201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                spdy::CONTROL_FLAG_NONE,
5464201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                NULL,
5465201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                0,
5466201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                0));
5467201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame> stream1_body(ConstructSpdyBodyFrame(1, false));
5468201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame> stream1_body2(ConstructSpdyBodyFrame(1, true));
5469201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MockRead reads[] = {
5470201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_reply),
5471201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_body),
5472201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_headers),
5473201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_body2),
5474201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    MockRead(true, 0, 0)  // EOF
5475201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5476201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5477201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_refptr<DelayedSocketData> data(
5478201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
5479201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                            writes, arraysize(writes)));
5480201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
5481201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                     BoundNetLog(), GetParam());
5482201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  helper.RunToCompletion(data.get());
5483201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  TransactionHelperResult out = helper.output();
5484201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(OK, out.rv);
5485201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
5486201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ("hello!hello!", out.response_data);
5487201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
5488201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5489201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochTEST_P(SpdyNetworkTransactionTest, SynReplyWithDuplicateLateHeaders) {
5490201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5491201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
5492201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5493201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kInitialHeaders[] = {
5494201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "status",
5495201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "200 OK",
5496201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "version",
5497201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "HTTP/1.1"
5498201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5499201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kLateHeaders[] = {
5500201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "status",
5501201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "500 Server Error",
5502201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5503201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5504201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_reply(ConstructSpdyControlFrame(kInitialHeaders,
5505201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              arraysize(kInitialHeaders) / 2,
5506201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              false,
5507201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              1,
5508201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              LOWEST,
5509201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              spdy::SYN_REPLY,
5510201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              spdy::CONTROL_FLAG_NONE,
5511201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              NULL,
5512201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              0,
5513201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              0));
5514201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5515201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_headers(ConstructSpdyControlFrame(kLateHeaders,
5516201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                arraysize(kLateHeaders) / 2,
5517201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                false,
5518201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                1,
5519201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                LOWEST,
5520201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                spdy::HEADERS,
5521201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                spdy::CONTROL_FLAG_NONE,
5522201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                NULL,
5523201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                0,
5524201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                0));
5525201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame> stream1_body(ConstructSpdyBodyFrame(1, false));
5526201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame> stream1_body2(ConstructSpdyBodyFrame(1, true));
5527201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MockRead reads[] = {
5528201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_reply),
5529201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_body),
5530201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_headers),
5531201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_body2),
5532201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    MockRead(true, 0, 0)  // EOF
5533201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5534201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5535201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_refptr<DelayedSocketData> data(
5536201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
5537201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                            writes, arraysize(writes)));
5538201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
5539201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                     BoundNetLog(), GetParam());
5540201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  helper.RunToCompletion(data.get());
5541201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  TransactionHelperResult out = helper.output();
5542201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
5543201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
5544201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5545201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
5546201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // In this test we want to verify that we can't accidentally push content
5547201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // which can't be pushed by this content server.
5548201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // This test assumes that:
5549201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  //   - if we're requesting http://www.foo.com/barbaz
5550201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  //   - the browser has made a connection to "www.foo.com".
5551201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5552201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // A list of the URL to fetch, followed by the URL being pushed.
5553201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kTestCases[] = {
5554201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "http://www.google.com/foo.html",
5555201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "http://www.google.com:81/foo.js",     // Bad port
5556201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5557201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "http://www.google.com/foo.html",
5558201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "https://www.google.com/foo.js",       // Bad protocol
5559201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5560201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "http://www.google.com/foo.html",
5561201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "ftp://www.google.com/foo.js",         // Invalid Protocol
5562201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5563201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "http://www.google.com/foo.html",
5564201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "http://blat.www.google.com/foo.js",   // Cross subdomain
5565201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5566201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "http://www.google.com/foo.html",
5567201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "http://www.foo.com/foo.js",           // Cross domain
5568201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5569201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5570201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5571201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const unsigned char kPushBodyFrame[] = {
5572201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    0x00, 0x00, 0x00, 0x02,                                      // header, ID
5573201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    0x01, 0x00, 0x00, 0x06,                                      // FIN, length
5574201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed"
5575201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5576201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5577201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  for (size_t index = 0; index < arraysize(kTestCases); index += 2) {
5578201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    const char* url_to_fetch = kTestCases[index];
5579201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    const char* url_to_push = kTestCases[index + 1];
5580201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5581201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    scoped_ptr<spdy::SpdyFrame>
5582201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        stream1_syn(ConstructSpdyGet(url_to_fetch, false, 1, LOWEST));
5583201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    scoped_ptr<spdy::SpdyFrame>
5584201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        stream1_body(ConstructSpdyBodyFrame(1, true));
5585201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    scoped_ptr<spdy::SpdyFrame> push_rst(
5586201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        ConstructSpdyRstStream(2, spdy::REFUSED_STREAM));
5587201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    MockWrite writes[] = {
5588201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      CreateMockWrite(*stream1_syn, 1),
5589201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      CreateMockWrite(*push_rst, 4),
5590201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    };
5591201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5592201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    scoped_ptr<spdy::SpdyFrame>
5593201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
5594201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    scoped_ptr<spdy::SpdyFrame>
5595201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        stream2_syn(ConstructSpdyPush(NULL,
5596201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                      0,
5597201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                      2,
5598201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                      1,
5599201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                      url_to_push));
5600201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    scoped_ptr<spdy::SpdyFrame> rst(
5601201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        ConstructSpdyRstStream(2, spdy::CANCEL));
5602201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5603201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    MockRead reads[] = {
5604201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      CreateMockRead(*stream1_reply, 2),
5605201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      CreateMockRead(*stream2_syn, 3),
5606201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      CreateMockRead(*stream1_body, 5, false),
5607201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame),
5608201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch               arraysize(kPushBodyFrame), 6),
5609201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      MockRead(true, ERR_IO_PENDING, 7),  // Force a pause
5610201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    };
5611201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5612201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    HttpResponseInfo response;
5613201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    scoped_refptr<OrderedSocketData> data(new OrderedSocketData(
5614201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        reads,
5615201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        arraysize(reads),
5616201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        writes,
5617201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        arraysize(writes)));
5618201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5619201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    HttpRequestInfo request;
5620201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    request.method = "GET";
5621201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    request.url = GURL(url_to_fetch);
5622201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    request.load_flags = 0;
5623201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    NormalSpdyTransactionHelper helper(request,
5624201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                       BoundNetLog(), GetParam());
5625201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    helper.RunPreTestSetup();
5626201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    helper.AddData(data);
5627201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5628201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    HttpNetworkTransaction* trans = helper.trans();
5629201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5630201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // Start the transaction with basic parameters.
5631201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    TestCompletionCallback callback;
5632201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5633201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    int rv = trans->Start(&request, &callback, BoundNetLog());
5634201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    EXPECT_EQ(ERR_IO_PENDING, rv);
5635201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    rv = callback.WaitForResult();
5636201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5637201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // Read the response body.
5638201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    std::string result;
5639201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    ReadResult(trans, data, &result);
5640201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5641201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // Verify that we consumed all test data.
5642201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    EXPECT_TRUE(data->at_read_eof());
5643201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    EXPECT_TRUE(data->at_write_eof());
5644201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5645201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // Verify the SYN_REPLY.
5646201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // Copy the response info, because trans goes away.
5647201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    response = *trans->GetResponseInfo();
5648201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5649201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    VerifyStreamsClosed(helper);
5650201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5651201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // Verify the SYN_REPLY.
5652201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    EXPECT_TRUE(response.headers != NULL);
5653201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5654201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
5655201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
5656201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace net
5658