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"
14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/socket/client_socket_pool_base.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/spdy/spdy_http_stream.h"
1672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "net/spdy/spdy_http_utils.h"
173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/spdy/spdy_session.h"
183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/spdy/spdy_session_pool.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/spdy/spdy_test_util.h"
2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "net/url_request/url_request_test_util.h"
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "testing/platform_test.h"
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//-----------------------------------------------------------------------------
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace net {
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// This is the expected list of advertised protocols from the browser's NPN
283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// list.
293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic const char kExpectedNPNString[] = "\x08http/1.1\x06spdy/2";
303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickenum SpdyNetworkTransactionTestTypes {
323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SPDYNPN,
333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SPDYNOSSL,
34731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  SPDYSSL,
353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick};
363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass SpdyNetworkTransactionTest
373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    : public ::testing::TestWithParam<SpdyNetworkTransactionTestTypes> {
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected:
39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void SetUp() {
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // By default, all tests turn off compression.
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EnableCompression(false);
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    google_get_request_initialized_ = false;
443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    google_post_request_initialized_ = false;
45dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    google_chunked_post_request_initialized_ = false;
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void TearDown() {
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Empty the current queue.
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MessageLoop::current()->RunAllPending();
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct TransactionHelperResult {
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int rv;
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string status_line;
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string response_data;
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HttpResponseInfo response_info;
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void EnableCompression(bool enabled) {
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SpdyFramer::set_enable_compression_default(enabled);
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  class StartTransactionCallback;
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  class DeleteSessionCallback;
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // A helper class that handles all the initial npn/ssl setup.
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  class NormalSpdyTransactionHelper {
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   public:
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NormalSpdyTransactionHelper(const HttpRequestInfo& request,
713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                const BoundNetLog& log,
723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                SpdyNetworkTransactionTestTypes test_type)
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        : request_(request),
743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          session_deps_(new SpdySessionDependencies()),
753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          session_(SpdySessionDependencies::SpdyCreateSession(
763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              session_deps_.get())),
773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          log_(log),
783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          test_type_(test_type),
79731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          deterministic_(false),
80731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          spdy_enabled_(true) {
813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            switch (test_type_) {
823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              case SPDYNOSSL:
833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              case SPDYSSL:
843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                port_ = 80;
853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                break;
863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              case SPDYNPN:
873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                port_ = 443;
883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                break;
893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              default:
903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                NOTREACHED();
913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            }
923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          }
933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ~NormalSpdyTransactionHelper() {
953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // Any test which doesn't close the socket by sending it an EOF will
963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // have a valid session left open, which leaks the entire session pool.
973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // This is just fine - in fact, some of our tests intentionally do this
983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // so that we can check consistency of the SpdySessionPool as the test
993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // finishes.  If we had put an EOF on the socket, the SpdySession would
1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // have closed and we wouldn't be able to check the consistency.
1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // Forcefully close existing sessions here.
1033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      session()->spdy_session_pool()->CloseAllSessions();
1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    void SetDeterministic() {
1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          session_deps_.get());
1093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      deterministic_ = true;
1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
112731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    void SetSpdyDisabled() {
113731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      spdy_enabled_ = false;
114731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
115731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    void RunPreTestSetup() {
1173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (!session_deps_.get())
1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        session_deps_.reset(new SpdySessionDependencies());
1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (!session_.get())
1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        session_ = SpdySessionDependencies::SpdyCreateSession(
1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            session_deps_.get());
1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      HttpStreamFactory::set_use_alternate_protocols(false);
1233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      HttpStreamFactory::set_force_spdy_over_ssl(false);
1243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      HttpStreamFactory::set_force_spdy_always(false);
1253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      switch (test_type_) {
1263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        case SPDYNPN:
1273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          session_->mutable_alternate_protocols()->SetAlternateProtocolFor(
1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              HostPortPair("www.google.com", 80), 443,
1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              HttpAlternateProtocols::NPN_SPDY_2);
1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          HttpStreamFactory::set_use_alternate_protocols(true);
1313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          HttpStreamFactory::set_next_protos(kExpectedNPNString);
1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          break;
1333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        case SPDYNOSSL:
1343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          HttpStreamFactory::set_force_spdy_over_ssl(false);
1353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          HttpStreamFactory::set_force_spdy_always(true);
1363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          break;
1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        case SPDYSSL:
1383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          HttpStreamFactory::set_force_spdy_over_ssl(true);
1393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          HttpStreamFactory::set_force_spdy_always(true);
1403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          break;
1413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        default:
1423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          NOTREACHED();
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // We're now ready to use SSL-npn SPDY.
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      trans_.reset(new HttpNetworkTransaction(session_));
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Start the transaction, read some data, finish.
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void RunDefaultTest() {
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      output_.rv = trans_->Start(&request_, &callback, log_);
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // We expect an IO Pending or some sort of error.
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_LT(output_.rv, 0);
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (output_.rv != ERR_IO_PENDING)
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return;
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      output_.rv = callback.WaitForResult();
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (output_.rv != OK) {
1603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        session_->spdy_session_pool()->CloseCurrentSessions();
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return;
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Verify responses.
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const HttpResponseInfo* response = trans_->GetResponseInfo();
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ASSERT_TRUE(response != NULL);
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ASSERT_TRUE(response->headers != NULL);
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
169731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      EXPECT_EQ(spdy_enabled_, response->was_fetched_via_spdy);
170731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      if (test_type_ == SPDYNPN && spdy_enabled_) {
1713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        EXPECT_TRUE(response->was_npn_negotiated);
1723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      } else {
1733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        EXPECT_TRUE(!response->was_npn_negotiated);
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_);
240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (test_type_ == SPDYNPN || test_type_ == SPDYSSL)
2413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        session_deps_->socket_factory->AddSSLSocketDataProvider(ssl_.get());
2423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      session_deps_->socket_factory->AddSocketDataProvider(data);
243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (test_type_ == SPDYNPN) {
244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        MockConnect never_finishing_connect(false, ERR_IO_PENDING);
245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        linked_ptr<StaticSocketDataProvider>
246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            hanging_non_alternate_protocol_socket(
247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                new StaticSocketDataProvider(NULL, 0, NULL, 0));
248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        hanging_non_alternate_protocol_socket->set_connect_data(
249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            never_finishing_connect);
250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        session_deps_->socket_factory->AddSocketDataProvider(
251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            hanging_non_alternate_protocol_socket.get());
252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        alternate_vector_.push_back(hanging_non_alternate_protocol_socket);
253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      }
2543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
2553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    void AddDeterministicData(DeterministicSocketData* data) {
2573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      DCHECK(deterministic_);
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      data_vector_.push_back(data);
2593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      linked_ptr<SSLSocketDataProvider> ssl_(
2603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          new SSLSocketDataProvider(true, OK));
2613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (test_type_ == SPDYNPN) {
2623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        ssl_->next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        ssl_->next_proto = "spdy/2";
2643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        ssl_->was_npn_negotiated = true;
2653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      }
2663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ssl_vector_.push_back(ssl_);
267ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (test_type_ == SPDYNPN || test_type_ == SPDYSSL) {
2683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        session_deps_->deterministic_socket_factory->
2693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            AddSSLSocketDataProvider(ssl_.get());
270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      }
2713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      session_deps_->deterministic_socket_factory->AddSocketDataProvider(data);
272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (test_type_ == SPDYNPN) {
273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        MockConnect never_finishing_connect(false, ERR_IO_PENDING);
274ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        scoped_refptr<DeterministicSocketData>
275ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            hanging_non_alternate_protocol_socket(
276ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            new DeterministicSocketData(NULL, 0, NULL, 0));
277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        hanging_non_alternate_protocol_socket->set_connect_data(
278ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            never_finishing_connect);
279ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        session_deps_->deterministic_socket_factory->AddSocketDataProvider(
280ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            hanging_non_alternate_protocol_socket);
281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        alternate_deterministic_vector_.push_back(
282ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            hanging_non_alternate_protocol_socket);
283ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      }
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // This can only be called after RunPreTestSetup. It adds a Data Provider,
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // but not a corresponding SSL data provider
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void AddDataNoSSL(StaticSocketDataProvider* data) {
2893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      DCHECK(!deterministic_);
2903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      session_deps_->socket_factory->AddSocketDataProvider(data);
2913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
2923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    void AddDataNoSSL(DeterministicSocketData* data) {
2933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      DCHECK(deterministic_);
2943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      session_deps_->deterministic_socket_factory->AddSocketDataProvider(data);
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    void SetSession(const scoped_refptr<HttpNetworkSession>& session) {
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      session_ = session;
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HttpNetworkTransaction* trans() { return trans_.get(); }
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void ResetTrans() { trans_.reset(); }
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TransactionHelperResult& output() { return output_; }
3033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const HttpRequestInfo& request() const { return request_; }
3043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const scoped_refptr<HttpNetworkSession>& session() const {
3053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return session_;
3063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
3073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    scoped_ptr<SpdySessionDependencies>& session_deps() {
3083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return session_deps_;
3093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
3103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    int port() const { return port_; }
3113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    SpdyNetworkTransactionTestTypes test_type() const { return test_type_; }
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   private:
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    typedef std::vector<StaticSocketDataProvider*> DataVector;
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    typedef std::vector<linked_ptr<SSLSocketDataProvider> > SSLVector;
316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    typedef std::vector<linked_ptr<StaticSocketDataProvider> > AlternateVector;
317ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    typedef std::vector<scoped_refptr<DeterministicSocketData> >
318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        AlternateDeterministicVector;
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HttpRequestInfo request_;
3203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    scoped_ptr<SpdySessionDependencies> session_deps_;
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_refptr<HttpNetworkSession> session_;
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TransactionHelperResult output_;
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<StaticSocketDataProvider> first_transaction_;
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SSLVector ssl_vector_;
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TestCompletionCallback callback;
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<HttpNetworkTransaction> trans_;
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<HttpNetworkTransaction> trans_http_;
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DataVector data_vector_;
329ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    AlternateVector alternate_vector_;
330ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    AlternateDeterministicVector alternate_deterministic_vector_;
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BoundNetLog& log_;
3323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    SpdyNetworkTransactionTestTypes test_type_;
3333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    int port_;
3343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    bool deterministic_;
335731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    bool spdy_enabled_;
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                             int expected_status);
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void ConnectStatusHelper(const MockRead& status);
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HttpRequestInfo& CreateGetPushRequest() {
3443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    google_get_push_request_.method = "GET";
3453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    google_get_push_request_.url = GURL("http://www.google.com/foo.dat");
3463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    google_get_push_request_.load_flags = 0;
3473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return google_get_push_request_;
3483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
3493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const HttpRequestInfo& CreateGetRequest() {
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!google_get_request_initialized_) {
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      google_get_request_.method = "GET";
3533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      google_get_request_.url = GURL(kDefaultURL);
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      google_get_request_.load_flags = 0;
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      google_get_request_initialized_ = true;
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return google_get_request_;
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3604a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  const HttpRequestInfo& CreateGetRequestWithUserAgent() {
3614a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    if (!google_get_request_initialized_) {
3624a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      google_get_request_.method = "GET";
3634a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      google_get_request_.url = GURL(kDefaultURL);
3644a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      google_get_request_.load_flags = 0;
3654a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      google_get_request_.extra_headers.SetHeader("User-Agent", "Chrome");
3664a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      google_get_request_initialized_ = true;
3674a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    }
3684a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    return google_get_request_;
3694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
3704a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
3713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HttpRequestInfo& CreatePostRequest() {
3723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (!google_post_request_initialized_) {
3733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      google_post_request_.method = "POST";
3743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      google_post_request_.url = GURL(kDefaultURL);
3753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      google_post_request_.upload_data = new UploadData();
3763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      google_post_request_.upload_data->AppendBytes(kUploadData,
3773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                    kUploadDataSize);
3783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      google_post_request_initialized_ = true;
3793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
3803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return google_post_request_;
3813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
3823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
383dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const HttpRequestInfo& CreateChunkedPostRequest() {
384dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (!google_chunked_post_request_initialized_) {
385dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      google_chunked_post_request_.method = "POST";
386dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      google_chunked_post_request_.url = GURL(kDefaultURL);
387dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      google_chunked_post_request_.upload_data = new UploadData();
388dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      google_chunked_post_request_.upload_data->set_is_chunked(true);
389dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      google_chunked_post_request_.upload_data->AppendChunk(
390dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          kUploadData, kUploadDataSize, false);
391dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      google_chunked_post_request_.upload_data->AppendChunk(
392dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          kUploadData, kUploadDataSize, true);
393dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      google_chunked_post_request_initialized_ = true;
394dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
395dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return google_chunked_post_request_;
396dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
397dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
3983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Read the result of a particular transaction, knowing that we've got
3993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // multiple transactions in the read pipeline; so as we read, we may have
4003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // to skip over data destined for other transactions while we consume
4013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // the data for |trans|.
4023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int ReadResult(HttpNetworkTransaction* trans,
403201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                 StaticSocketDataProvider* data,
4043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                 std::string* result) {
4053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const int kSize = 3000;
4063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    int bytes_read = 0;
408513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(kSize));
4093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    TestCompletionCallback callback;
4103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    while (true) {
4113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      int rv = trans->Read(buf, kSize, &callback);
4123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (rv == ERR_IO_PENDING) {
4133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        // Multiple transactions may be in the data set.  Keep pulling off
4143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        // reads until we complete our callback.
4153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        while (!callback.have_result()) {
4163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          data->CompleteRead();
4173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          MessageLoop::current()->RunAllPending();
4183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        }
4193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        rv = callback.WaitForResult();
4203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      } else if (rv <= 0) {
4213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        break;
4223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      }
4233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      result->append(buf->data(), rv);
4243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      bytes_read += rv;
4253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
4263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return bytes_read;
4273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
4283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void VerifyStreamsClosed(const NormalSpdyTransactionHelper& helper) {
4303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // This lengthy block is reaching into the pool to dig out the active
4313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // session.  Once we have the session, we verify that the streams are
4323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // all closed and not leaked at this point.
4333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const GURL& url = helper.request().url;
4343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    int port = helper.test_type() == SPDYNPN ? 443 : 80;
4353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    HostPortPair host_port_pair(url.host(), port);
4363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
4373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    BoundNetLog log;
4383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const scoped_refptr<HttpNetworkSession>& session = helper.session();
439731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    SpdySessionPool* pool(session->spdy_session_pool());
4403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_TRUE(pool->HasSession(pair));
441dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    scoped_refptr<SpdySession> spdy_session(pool->Get(pair, log));
4423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ASSERT_TRUE(spdy_session.get() != NULL);
4433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(0u, spdy_session->num_active_streams());
4443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams());
4453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
4463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
447201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  void RunServerPushTest(OrderedSocketData* data,
4483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                         HttpResponseInfo* response,
449201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                         HttpResponseInfo* push_response,
4503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                         std::string& expected) {
4513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    NormalSpdyTransactionHelper helper(CreateGetRequest(),
4523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                       BoundNetLog(), GetParam());
4533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    helper.RunPreTestSetup();
454201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    helper.AddData(data);
4553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    HttpNetworkTransaction* trans = helper.trans();
4573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Start the transaction with basic parameters.
4593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    TestCompletionCallback callback;
4603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
4613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(ERR_IO_PENDING, rv);
4623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    rv = callback.WaitForResult();
4633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Request the pushed path.
4653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    scoped_ptr<HttpNetworkTransaction> trans2(
4663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        new HttpNetworkTransaction(helper.session()));
4673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    rv = trans2->Start(&CreateGetPushRequest(), &callback, BoundNetLog());
4683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(ERR_IO_PENDING, rv);
4693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MessageLoop::current()->RunAllPending();
4703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // The data for the pushed path may be coming in more than 1 packet. Compile
4723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // the results into a single string.
4733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Read the server push body.
4753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    std::string result2;
4763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ReadResult(trans2.get(), data, &result2);
4773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Read the response body.
4783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    std::string result;
4793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ReadResult(trans, data, &result);
4803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Verify that we consumed all test data.
4823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_TRUE(data->at_read_eof());
4833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_TRUE(data->at_write_eof());
4843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Verify that the received push data is same as the expected push data.
4863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(result2.compare(expected), 0) << "Received data: "
4873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                            << result2
4883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                            << "||||| Expected data: "
4893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                            << expected;
4903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Verify the SYN_REPLY.
4923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Copy the response info, because trans goes away.
4933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    *response = *trans->GetResponseInfo();
494201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    *push_response = *trans2->GetResponseInfo();
4953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    VerifyStreamsClosed(helper);
4973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
4983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool google_get_request_initialized_;
5013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool google_post_request_initialized_;
502dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  bool google_chunked_post_request_initialized_;
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpRequestInfo google_get_request_;
5043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo google_post_request_;
505dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  HttpRequestInfo google_chunked_post_request_;
5063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo google_get_push_request_;
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//-----------------------------------------------------------------------------
5103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// All tests are run with three different connection types: SPDY after NPN
5113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// negotiation, SPDY without SSL, and SPDY with SSL.
5123345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickINSTANTIATE_TEST_CASE_P(Spdy,
5133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        SpdyNetworkTransactionTest,
5143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        ::testing::Values(SPDYNOSSL, SPDYSSL, SPDYNPN));
5153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Verify HttpNetworkTransaction constructor.
5183345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, Constructor) {
519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SpdySessionDependencies session_deps;
520513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_refptr<HttpNetworkSession> session(
521513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      SpdySessionDependencies::SpdyCreateSession(&session_deps));
522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5253345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, Get) {
526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Construct the request.
527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
5423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunToCompletion(data.get());
544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("hello!", out.response_data);
548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5503345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) {
5513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (RequestPriority p = HIGHEST; p < NUM_PRIORITIES;
5523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       p = RequestPriority(p+1)) {
5533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Construct the request.
5543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, p));
5553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockWrite writes[] = { CreateMockWrite(*req) };
5563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
5573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const int spdy_prio = reinterpret_cast<spdy::SpdySynStreamControlFrame*>(
5583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        req.get())->priority();
5593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // this repeats the RequestPriority-->SpdyPriority mapping from
5603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
5613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // sure it's being done right.
5623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    switch(p) {
5633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      case HIGHEST:
5643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        EXPECT_EQ(0, spdy_prio);
5653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        break;
5663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      case MEDIUM:
5673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        EXPECT_EQ(1, spdy_prio);
5683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        break;
5693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      case LOW:
5703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      case LOWEST:
5713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        EXPECT_EQ(2, spdy_prio);
5723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        break;
5733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      case IDLE:
5743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        EXPECT_EQ(3, spdy_prio);
5753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        break;
5763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      default:
5773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        FAIL();
5783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
5793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
5803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
5813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
5823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead reads[] = {
5833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      CreateMockRead(*resp),
5843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      CreateMockRead(*body),
5853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      MockRead(true, 0, 0)  // EOF
5863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    };
5873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
5883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    scoped_refptr<DelayedSocketData> data(
5893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        new DelayedSocketData(1, reads, arraysize(reads),
5903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                              writes, arraysize(writes)));
5913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    HttpRequestInfo http_req = CreateGetRequest();
5923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    http_req.priority = p;
5933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
5943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    NormalSpdyTransactionHelper helper(http_req, BoundNetLog(), GetParam());
5953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    helper.RunToCompletion(data.get());
5963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    TransactionHelperResult out = helper.output();
5973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(OK, out.rv);
5983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
5993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ("hello!", out.response_data);
6003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
6013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
6023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Start three gets simultaniously; making sure that multiplexed
604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// streams work properly.
605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This can't use the TransactionHelper method, since it only
607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// handles a single transaction, and finishes them as soon
608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// as it launches them.
609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(gavinp): create a working generalized TransactionHelper that
611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// can allow multiple streams in flight.
612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
6133345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ThreeGets) {
614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req3(ConstructSpdyGet(NULL, 0, false, 5, LOWEST));
625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 5));
626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body3(ConstructSpdyBodyFrame(5, false));
627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> fbody3(ConstructSpdyBodyFrame(5, true));
628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
629dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MockWrite writes[] = {
630dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockWrite(*req),
631dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockWrite(*req2),
632dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockWrite(*req3),
633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp, 1),
636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp2, 4),
638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body2),
639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp3, 7),
640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body3),
641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*fbody),
643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*fbody2),
644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*fbody3),
645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0),  // EOF
647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<OrderedSocketData> data(
649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new OrderedSocketData(reads, arraysize(reads),
650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
6513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data_placeholder(
6523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(NULL, 0, NULL, 0));
653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BoundNetLog log;
655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out;
6563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
6573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
6583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
6593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
6603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // We require placeholder data because three get requests are sent out, so
6613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // there needs to be three sets of SSL connection data.
6623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data_placeholder.get());
6633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data_placeholder.get());
6643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<HttpNetworkTransaction> trans1(
6653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new HttpNetworkTransaction(helper.session()));
6663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<HttpNetworkTransaction> trans2(
6673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new HttpNetworkTransaction(helper.session()));
6683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<HttpNetworkTransaction> trans3(
6693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new HttpNetworkTransaction(helper.session()));
6703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback1;
6723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback2;
6733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback3;
6743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo httpreq1 = CreateGetRequest();
6763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo httpreq2 = CreateGetRequest();
6773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo httpreq3 = CreateGetRequest();
6783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans1->Start(&httpreq1, &callback1, log);
6803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(ERR_IO_PENDING, out.rv);
6813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans2->Start(&httpreq2, &callback2, log);
6823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(ERR_IO_PENDING, out.rv);
6833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans3->Start(&httpreq3, &callback3, log);
6843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(ERR_IO_PENDING, out.rv);
6853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = callback1.WaitForResult();
6873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(OK, out.rv);
6883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = callback3.WaitForResult();
6893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(OK, out.rv);
6903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
6923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response1->headers != NULL);
6933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response1->was_fetched_via_spdy);
6943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.status_line = response1->headers->GetStatusLine();
6953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.response_info = *response1;
6963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  trans2->GetResponseInfo();
6983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = ReadTransaction(trans1.get(), &out.response_data);
7003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("hello!hello!", out.response_data);
706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
708dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST_P(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
709dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
710dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
711dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
712dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
713dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
714dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
715dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
716dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
717dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
718dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
719dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MockWrite writes[] = {
720dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockWrite(*req),
721dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockWrite(*req2),
722dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  };
723dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MockRead reads[] = {
724dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*resp, 1),
725dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*body),
726dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*resp2, 4),
727dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*body2),
728dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*fbody),
729dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*fbody2),
730dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    MockRead(true, 0, 0),  // EOF
731dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  };
732dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_refptr<OrderedSocketData> data(
733dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      new OrderedSocketData(reads, arraysize(reads),
734dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                            writes, arraysize(writes)));
735dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
736ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  MockConnect never_finishing_connect(false, ERR_IO_PENDING);
737dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
738dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_refptr<OrderedSocketData> data_placeholder(
739dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      new OrderedSocketData(NULL, 0, NULL, 0));
740dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  data_placeholder->set_connect_data(never_finishing_connect);
741dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
742dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  BoundNetLog log;
743dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  TransactionHelperResult out;
744dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  NormalSpdyTransactionHelper helper(CreateGetRequest(),
745dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                     BoundNetLog(), GetParam());
746dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  helper.RunPreTestSetup();
747dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  helper.AddData(data.get());
748dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // We require placeholder data because two get requests are sent out, so
749dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // there needs to be two sets of SSL connection data.
750dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  helper.AddData(data_placeholder.get());
751dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<HttpNetworkTransaction> trans1(
752dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      new HttpNetworkTransaction(helper.session()));
753dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<HttpNetworkTransaction> trans2(
754dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      new HttpNetworkTransaction(helper.session()));
755dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
756dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  TestCompletionCallback callback1;
757dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  TestCompletionCallback callback2;
758dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
759dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  HttpRequestInfo httpreq1 = CreateGetRequest();
760dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  HttpRequestInfo httpreq2 = CreateGetRequest();
761dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
762dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.rv = trans1->Start(&httpreq1, &callback1, log);
763dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ASSERT_EQ(ERR_IO_PENDING, out.rv);
764dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.rv = trans2->Start(&httpreq2, &callback2, log);
765dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ASSERT_EQ(ERR_IO_PENDING, out.rv);
766dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
767dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.rv = callback1.WaitForResult();
768dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ASSERT_EQ(OK, out.rv);
769dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.rv = callback2.WaitForResult();
770dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ASSERT_EQ(OK, out.rv);
771dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
772dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
773dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(response1->headers != NULL);
774dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(response1->was_fetched_via_spdy);
775dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.status_line = response1->headers->GetStatusLine();
776dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.response_info = *response1;
777dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.rv = ReadTransaction(trans1.get(), &out.response_data);
778dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(OK, out.rv);
779dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
780dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ("hello!hello!", out.response_data);
781dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
782dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
783dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(response2->headers != NULL);
784dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(response2->was_fetched_via_spdy);
785dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.status_line = response2->headers->GetStatusLine();
786dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.response_info = *response2;
787dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.rv = ReadTransaction(trans2.get(), &out.response_data);
788dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(OK, out.rv);
789dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
790dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ("hello!hello!", out.response_data);
791dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
792dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  helper.VerifyDataConsumed();
793dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
794dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
795dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST_P(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
796dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
797dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
798dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
799dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
800dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
801dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
802dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
803dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
804dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
805dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
806dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MockWrite writes[] = {
807dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockWrite(*req),
808dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockWrite(*req2),
809dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  };
810dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MockRead reads[] = {
811dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*resp, 1),
812dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*body),
813dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*resp2, 4),
814dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*body2),
815dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*fbody),
816dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*fbody2),
817dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    MockRead(true, 0, 0),  // EOF
818dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  };
819dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_refptr<OrderedSocketData> preconnect_data(
820dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      new OrderedSocketData(reads, arraysize(reads),
821dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                            writes, arraysize(writes)));
822dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
823dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MockConnect never_finishing_connect(true, ERR_IO_PENDING);
824dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
825dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_refptr<OrderedSocketData> data_placeholder(
826dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      new OrderedSocketData(NULL, 0, NULL, 0));
827dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  data_placeholder->set_connect_data(never_finishing_connect);
828dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
829dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  BoundNetLog log;
830dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  TransactionHelperResult out;
831dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  NormalSpdyTransactionHelper helper(CreateGetRequest(),
832dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                     BoundNetLog(), GetParam());
833dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  helper.RunPreTestSetup();
834dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  helper.AddData(preconnect_data.get());
835dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // We require placeholder data because 3 connections are attempted (first is
836dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // the preconnect, 2nd and 3rd are the never finished connections.
837dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  helper.AddData(data_placeholder.get());
838dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  helper.AddData(data_placeholder.get());
839dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
840dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<HttpNetworkTransaction> trans1(
841dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      new HttpNetworkTransaction(helper.session()));
842dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<HttpNetworkTransaction> trans2(
843dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      new HttpNetworkTransaction(helper.session()));
844dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
845dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  TestCompletionCallback callback1;
846dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  TestCompletionCallback callback2;
847dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
848dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  HttpRequestInfo httpreq = CreateGetRequest();
849dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
850dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Preconnect the first.
851dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SSLConfig preconnect_ssl_config;
852dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  helper.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config);
853dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  HttpStreamFactory* http_stream_factory =
854dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      helper.session()->http_stream_factory();
855dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (http_stream_factory->next_protos()) {
856dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    preconnect_ssl_config.next_protos = *http_stream_factory->next_protos();
857dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
858dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
859dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  http_stream_factory->PreconnectStreams(
860dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      1, httpreq, preconnect_ssl_config, log);
861dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
862dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.rv = trans1->Start(&httpreq, &callback1, log);
863dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ASSERT_EQ(ERR_IO_PENDING, out.rv);
864dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.rv = trans2->Start(&httpreq, &callback2, log);
865dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ASSERT_EQ(ERR_IO_PENDING, out.rv);
866dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
867dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.rv = callback1.WaitForResult();
868dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ASSERT_EQ(OK, out.rv);
869dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.rv = callback2.WaitForResult();
870dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ASSERT_EQ(OK, out.rv);
871dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
872dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
873dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(response1->headers != NULL);
874dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(response1->was_fetched_via_spdy);
875dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.status_line = response1->headers->GetStatusLine();
876dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.response_info = *response1;
877dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.rv = ReadTransaction(trans1.get(), &out.response_data);
878dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(OK, out.rv);
879dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
880dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ("hello!hello!", out.response_data);
881dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
882dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
883dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(response2->headers != NULL);
884dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(response2->was_fetched_via_spdy);
885dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.status_line = response2->headers->GetStatusLine();
886dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.response_info = *response2;
887dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.rv = ReadTransaction(trans2.get(), &out.response_data);
888dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(OK, out.rv);
889dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
890dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ("hello!hello!", out.response_data);
891dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
892dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  helper.VerifyDataConsumed();
893dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
894dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Similar to ThreeGets above, however this test adds a SETTINGS
896c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// frame.  The SETTINGS frame is read during the IO loop waiting on
897c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the first transaction completion, and sets a maximum concurrent
898c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// stream limit of 1.  This means that our IO loop exists after the
899c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// second transaction completes, so we can assert on read_index().
9003345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Construct the request.
902c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
903c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
907c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
908c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req3(ConstructSpdyGet(NULL, 0, false, 5, LOWEST));
913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 5));
914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body3(ConstructSpdyBodyFrame(5, false));
915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> fbody3(ConstructSpdyBodyFrame(5, true));
916c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
917c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdySettings settings;
918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SettingsFlagsAndId id(0);
919c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  id.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS);
920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const size_t max_concurrent_streams = 1;
921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  settings.push_back(spdy::SpdySetting(id, max_concurrent_streams));
923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
925ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  MockWrite writes[] = {
926ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    CreateMockWrite(*req),
927ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    CreateMockWrite(*req2),
928ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    CreateMockWrite(*req3),
929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
930ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
9323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*settings_frame, 1),
933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*fbody),
9363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp2, 7),
937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body2),
938c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*fbody2),
9393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp3, 12),
940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body3),
941c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*fbody3),
942c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
943c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0),  // EOF
944c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<OrderedSocketData> data(
947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new OrderedSocketData(reads, arraysize(reads),
948c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
9493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data_placeholder(
9503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(NULL, 0, NULL, 0));
951c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
952c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BoundNetLog log;
953c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out;
954c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
955ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    NormalSpdyTransactionHelper helper(CreateGetRequest(),
956ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                       BoundNetLog(), GetParam());
957ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    helper.RunPreTestSetup();
958ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    helper.AddData(data.get());
959ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // We require placeholder data because three get requests are sent out, so
960ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // there needs to be three sets of SSL connection data.
961ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    helper.AddData(data_placeholder.get());
962ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    helper.AddData(data_placeholder.get());
9633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    scoped_ptr<HttpNetworkTransaction> trans1(
9643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        new HttpNetworkTransaction(helper.session()));
9653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    scoped_ptr<HttpNetworkTransaction> trans2(
9663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        new HttpNetworkTransaction(helper.session()));
9673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    scoped_ptr<HttpNetworkTransaction> trans3(
9683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        new HttpNetworkTransaction(helper.session()));
969c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TestCompletionCallback callback1;
971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TestCompletionCallback callback2;
972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TestCompletionCallback callback3;
973c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HttpRequestInfo httpreq1 = CreateGetRequest();
975c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HttpRequestInfo httpreq2 = CreateGetRequest();
976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HttpRequestInfo httpreq3 = CreateGetRequest();
977c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
978c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.rv = trans1->Start(&httpreq1, &callback1, log);
979c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ASSERT_EQ(out.rv, ERR_IO_PENDING);
980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // run transaction 1 through quickly to force a read of our SETTINGS
981c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // frame
982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.rv = callback1.WaitForResult();
9833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ASSERT_EQ(OK, out.rv);
984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.rv = trans2->Start(&httpreq2, &callback2, log);
986c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ASSERT_EQ(out.rv, ERR_IO_PENDING);
987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.rv = trans3->Start(&httpreq3, &callback3, log);
988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ASSERT_EQ(out.rv, ERR_IO_PENDING);
989c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.rv = callback2.WaitForResult();
990c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ASSERT_EQ(OK, out.rv);
991c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(7U, data->read_index());  // i.e. the third trans was queued
992c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
993c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.rv = callback3.WaitForResult();
994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ASSERT_EQ(OK, out.rv);
995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
996c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const HttpResponseInfo* response1 = trans1->GetResponseInfo();
9973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ASSERT_TRUE(response1 != NULL);
998c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(response1->headers != NULL);
999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(response1->was_fetched_via_spdy);
1000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.status_line = response1->headers->GetStatusLine();
1001c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.response_info = *response1;
1002c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.rv = ReadTransaction(trans1.get(), &out.response_data);
1003c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(OK, out.rv);
1004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ("hello!hello!", out.response_data);
1006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1008c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.status_line = response2->headers->GetStatusLine();
1009c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.response_info = *response2;
1010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.rv = ReadTransaction(trans2.get(), &out.response_data);
1011c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(OK, out.rv);
1012c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1013c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ("hello!hello!", out.response_data);
1014c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1015c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1016c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.status_line = response3->headers->GetStatusLine();
1017c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.response_info = *response3;
1018c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    out.rv = ReadTransaction(trans3.get(), &out.response_data);
1019c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(OK, out.rv);
1020c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1021c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ("hello!hello!", out.response_data);
10223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
10233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    helper.VerifyDataConsumed();
1024c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1025c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
1026c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1027c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1028c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1029c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// a fourth transaction.  The third and fourth transactions have
1030c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// different data ("hello!" vs "hello!hello!") and because of the
1031c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// user specified priority, we expect to see them inverted in
1032c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the response from the server.
10333345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
1034c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Construct the request.
1035c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1036c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1037c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
1038c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
1039c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1040c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
1041c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
1042c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
1043c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
1044c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1045c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req4(
1046c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ConstructSpdyGet(NULL, 0, false, 5, HIGHEST));
1047c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp4(ConstructSpdyGetSynReply(NULL, 0, 5));
1048c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> fbody4(ConstructSpdyBodyFrame(5, true));
1049c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1050c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req3(ConstructSpdyGet(NULL, 0, false, 7, LOWEST));
1051c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 7));
1052c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body3(ConstructSpdyBodyFrame(7, false));
1053c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> fbody3(ConstructSpdyBodyFrame(7, true));
1054c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1055c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1056c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdySettings settings;
1057c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SettingsFlagsAndId id(0);
1058c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  id.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS);
1059c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const size_t max_concurrent_streams = 1;
1060c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1061c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  settings.push_back(spdy::SpdySetting(id, max_concurrent_streams));
1062c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
1063c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1064c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req),
10653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req2),
10663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req4),
10673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req3),
1068c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
1069c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
10703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*settings_frame, 1),
1071c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
1072c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
1073c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*fbody),
10743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp2, 7),
1075c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body2),
1076c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*fbody2),
10773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp4, 13),
1078c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*fbody4),
10793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp3, 16),
1080c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body3),
1081c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*fbody3),
1082c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1083c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0),  // EOF
1084c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
1085c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1086c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<OrderedSocketData> data(
1087c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new OrderedSocketData(reads, arraysize(reads),
10883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        writes, arraysize(writes)));
10893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data_placeholder(
10903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(NULL, 0, NULL, 0));
1091c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1092c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BoundNetLog log;
1093c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out;
10943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
10953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      BoundNetLog(), GetParam());
10963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
10973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
10983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // We require placeholder data because four get requests are sent out, so
10993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // there needs to be four sets of SSL connection data.
11003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data_placeholder.get());
11013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data_placeholder.get());
11023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data_placeholder.get());
11033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<HttpNetworkTransaction> trans1(
11043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new HttpNetworkTransaction(helper.session()));
11053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<HttpNetworkTransaction> trans2(
11063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new HttpNetworkTransaction(helper.session()));
11073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<HttpNetworkTransaction> trans3(
11083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new HttpNetworkTransaction(helper.session()));
11093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<HttpNetworkTransaction> trans4(
11103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new HttpNetworkTransaction(helper.session()));
11113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
11123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback1;
11133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback2;
11143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback3;
11153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback4;
11163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
11173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo httpreq1 = CreateGetRequest();
11183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo httpreq2 = CreateGetRequest();
11193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo httpreq3 = CreateGetRequest();
11203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo httpreq4 = CreateGetRequest();
11213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  httpreq4.priority = HIGHEST;
11223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
11233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans1->Start(&httpreq1, &callback1, log);
11243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(ERR_IO_PENDING, out.rv);
11253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // run transaction 1 through quickly to force a read of our SETTINGS
11263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // frame
11273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = callback1.WaitForResult();
11283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(OK, out.rv);
11293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
11303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans2->Start(&httpreq2, &callback2, log);
11313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(ERR_IO_PENDING, out.rv);
11323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans3->Start(&httpreq3, &callback3, log);
11333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(ERR_IO_PENDING, out.rv);
11343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans4->Start(&httpreq4, &callback4, log);
11353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(ERR_IO_PENDING, out.rv);
11363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
11373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = callback2.WaitForResult();
11383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(OK, out.rv);
11393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(data->read_index(), 7U);  // i.e. the third & fourth trans queued
11403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
11413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = callback3.WaitForResult();
11423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(OK, out.rv);
11433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
11443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
11453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response1->headers != NULL);
11463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response1->was_fetched_via_spdy);
11473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.status_line = response1->headers->GetStatusLine();
11483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.response_info = *response1;
11493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = ReadTransaction(trans1.get(), &out.response_data);
11503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, out.rv);
11513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
11523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("hello!hello!", out.response_data);
1153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
11543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
11553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.status_line = response2->headers->GetStatusLine();
11563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.response_info = *response2;
11573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = ReadTransaction(trans2.get(), &out.response_data);
11583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, out.rv);
11593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
11603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("hello!hello!", out.response_data);
1161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
11623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // notice: response3 gets two hellos, response4 gets one
11633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // hello, so we know dequeuing priority was respected.
11643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HttpResponseInfo* response3 = trans3->GetResponseInfo();
11653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.status_line = response3->headers->GetStatusLine();
11663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.response_info = *response3;
11673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = ReadTransaction(trans3.get(), &out.response_data);
1168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
11693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
11703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("hello!hello!", out.response_data);
1171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
11723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = callback4.WaitForResult();
11733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, out.rv);
11743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HttpResponseInfo* response4 = trans4->GetResponseInfo();
11753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.status_line = response4->headers->GetStatusLine();
11763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.response_info = *response4;
11773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = ReadTransaction(trans4.get(), &out.response_data);
11783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, out.rv);
11793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
11803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("hello!", out.response_data);
11813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
11823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, out.rv);
1183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Similar to ThreeGetsMaxConcurrrent above, however, this test
1186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// deletes a session in the middle of the transaction to insure
1187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// that we properly remove pendingcreatestream objects from
1188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the spdy_session
11893345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
1190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Construct the request.
1191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
1194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
1195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
1197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
1198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
1199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
1200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdySettings settings;
1202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SettingsFlagsAndId id(0);
1203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  id.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS);
1204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const size_t max_concurrent_streams = 1;
1205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  settings.push_back(spdy::SpdySetting(id, max_concurrent_streams));
1207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
1208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req),
12103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req2),
1211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
1212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
12133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*settings_frame, 1),
1214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
1215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
1216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*fbody),
12173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp2, 7),
1218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body2),
1219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*fbody2),
1220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0),  // EOF
1221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
1222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<OrderedSocketData> data(
1224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new OrderedSocketData(reads, arraysize(reads),
12253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        writes, arraysize(writes)));
12263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data_placeholder(
12273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(NULL, 0, NULL, 0));
1228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BoundNetLog log;
1230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out;
12313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
12323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      BoundNetLog(), GetParam());
12333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
12343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
12353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // We require placeholder data because three get requests are sent out, so
12363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // there needs to be three sets of SSL connection data.
12373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data_placeholder.get());
12383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data_placeholder.get());
12393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<HttpNetworkTransaction> trans1(
12403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new HttpNetworkTransaction(helper.session()));
12413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<HttpNetworkTransaction> trans2(
12423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new HttpNetworkTransaction(helper.session()));
12433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<HttpNetworkTransaction> trans3(
12443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new HttpNetworkTransaction(helper.session()));
12453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
12463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback1;
12473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback2;
12483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback3;
12493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
12503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo httpreq1 = CreateGetRequest();
12513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo httpreq2 = CreateGetRequest();
12523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo httpreq3 = CreateGetRequest();
12533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
12543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans1->Start(&httpreq1, &callback1, log);
12553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(out.rv, ERR_IO_PENDING);
12563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // run transaction 1 through quickly to force a read of our SETTINGS
12573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // frame
12583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = callback1.WaitForResult();
12593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(OK, out.rv);
12603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
12613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans2->Start(&httpreq2, &callback2, log);
12623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(out.rv, ERR_IO_PENDING);
12633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans3->Start(&httpreq3, &callback3, log);
12643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  delete trans3.release();
12653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(out.rv, ERR_IO_PENDING);
12663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = callback2.WaitForResult();
12673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(OK, out.rv);
12683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
12693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(8U, data->read_index());
12703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
12713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
12723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(response1 != NULL);
12733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response1->headers != NULL);
12743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response1->was_fetched_via_spdy);
12753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.status_line = response1->headers->GetStatusLine();
12763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.response_info = *response1;
12773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = ReadTransaction(trans1.get(), &out.response_data);
12783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, out.rv);
12793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
12803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("hello!hello!", out.response_data);
1281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
12823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
12833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(response2 != NULL);
12843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.status_line = response2->headers->GetStatusLine();
12853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.response_info = *response2;
12863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = ReadTransaction(trans2.get(), &out.response_data);
12873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, out.rv);
12883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
12893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("hello!hello!", out.response_data);
12903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
12913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, out.rv);
12923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
12943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// The KillerCallback will delete the transaction on error as part of the
12953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// callback.
12963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass KillerCallback : public TestCompletionCallback {
12973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick public:
12983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  explicit KillerCallback(HttpNetworkTransaction* transaction)
12993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      : transaction_(transaction) {}
1300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
13013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual void RunWithParams(const Tuple1<int>& params) {
13023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (params.a < 0)
13033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      delete transaction_;
13043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    TestCompletionCallback::RunWithParams(params);
13053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
13073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick private:
13083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* transaction_;
13093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick};
1310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
13113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
13123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// closes the socket while we have a pending transaction waiting for
13133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// a pending stream creation.  http://crbug.com/52901
13143345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
13153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Construct the request.
13163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
13173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
13183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
13193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> fin_body(ConstructSpdyBodyFrame(1, true));
1320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
13213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
13223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
13233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
13243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  spdy::SpdySettings settings;
13253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  spdy::SettingsFlagsAndId id(0);
13263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  id.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS);
13273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const size_t max_concurrent_streams = 1;
13283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
13293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  settings.push_back(spdy::SpdySetting(id, max_concurrent_streams));
13303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
13313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
13323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = { CreateMockWrite(*req),
13333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req2),
13343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
13353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
13363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*settings_frame, 1),
13373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp),
13383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body),
13393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*fin_body),
13403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp2, 7),
13413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_CONNECTION_RESET, 0),  // Abort!
13423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
13433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
13443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data(
13453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(reads, arraysize(reads),
13463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        writes, arraysize(writes)));
13473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data_placeholder(
13483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(NULL, 0, NULL, 0));
13493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
13503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  BoundNetLog log;
13513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TransactionHelperResult out;
13523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
13533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      BoundNetLog(), GetParam());
13543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
13553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
13563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // We require placeholder data because three get requests are sent out, so
13573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // there needs to be three sets of SSL connection data.
13583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data_placeholder.get());
13593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data_placeholder.get());
13603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction trans1(helper.session());
13613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction trans2(helper.session());
13623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans3(new HttpNetworkTransaction(helper.session()));
13633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
13643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback1;
13653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback2;
13663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  KillerCallback callback3(trans3);
13673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
13683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo httpreq1 = CreateGetRequest();
13693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo httpreq2 = CreateGetRequest();
13703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo httpreq3 = CreateGetRequest();
13713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
13723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans1.Start(&httpreq1, &callback1, log);
13733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(out.rv, ERR_IO_PENDING);
13743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // run transaction 1 through quickly to force a read of our SETTINGS
13753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // frame
13763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = callback1.WaitForResult();
13773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(OK, out.rv);
13783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
13793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans2.Start(&httpreq2, &callback2, log);
13803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(out.rv, ERR_IO_PENDING);
13813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans3->Start(&httpreq3, &callback3, log);
13823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(out.rv, ERR_IO_PENDING);
13833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = callback3.WaitForResult();
13843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(ERR_ABORTED, out.rv);
13853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
13863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(6U, data->read_index());
13873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
13883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HttpResponseInfo* response1 = trans1.GetResponseInfo();
13893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(response1 != NULL);
13903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response1->headers != NULL);
13913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response1->was_fetched_via_spdy);
13923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.status_line = response1->headers->GetStatusLine();
13933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.response_info = *response1;
13943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = ReadTransaction(&trans1, &out.response_data);
1395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
1396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
13973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HttpResponseInfo* response2 = trans2.GetResponseInfo();
13983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(response2 != NULL);
13993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.status_line = response2->headers->GetStatusLine();
14003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.response_info = *response2;
14013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = ReadTransaction(&trans2, &out.response_data);
14023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_CONNECTION_RESET, out.rv);
14033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
14043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
1405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
14073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Test that a simple PUT request works.
14083345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, Put) {
14093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Setup the request
14103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo request;
14113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.method = "PUT";
14123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.url = GURL("http://www.google.com/");
14133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
14143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const SpdyHeaderInfo kSynStartHeader = {
14153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::SYN_STREAM,             // Kind = Syn
14163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    1,                            // Stream ID
14173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0,                            // Associated stream ID
14183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    net::ConvertRequestPriorityToSpdyPriority(LOWEST),  // Priority
14193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::CONTROL_FLAG_FIN,       // Control Flags
14203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    false,                        // Compressed
14213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::INVALID,                // Status
14223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    NULL,                         // Data
14233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0,                            // Length
14243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::DATA_FLAG_NONE          // Data Flags
14253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
14263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char* const kPutHeaders[] = {
14273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "method", "PUT",
14283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "url", "/",
14293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "host", "www.google.com",
14303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "scheme", "http",
14313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "version", "HTTP/1.1",
14323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "content-length", "0"
14333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
14343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPacket(kSynStartHeader, NULL, 0,
1435201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    kPutHeaders, arraysize(kPutHeaders) / 2));
14363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
14373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req)
14383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
14393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
14403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
14413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const SpdyHeaderInfo kSynReplyHeader = {
14423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::SYN_REPLY,              // Kind = SynReply
14433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    1,                            // Stream ID
14443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0,                            // Associated stream ID
14453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    net::ConvertRequestPriorityToSpdyPriority(LOWEST),  // Priority
14463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::CONTROL_FLAG_NONE,      // Control Flags
14473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    false,                        // Compressed
14483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::INVALID,                // Status
14493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    NULL,                         // Data
14503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0,                            // Length
14513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::DATA_FLAG_NONE          // Data Flags
14523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
14533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const char* const kStandardGetHeaders[] = {
14543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "status", "200",
14553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "version", "HTTP/1.1"
14563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "content-length", "1234"
14573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
14583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPacket(kSynReplyHeader,
1459201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      NULL, 0, kStandardGetHeaders, arraysize(kStandardGetHeaders) / 2));
14603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
14613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp),
14623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body),
14633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0)  // EOF
14643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
14653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
14663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<DelayedSocketData> data(
14673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new DelayedSocketData(1, reads, arraysize(reads),
14683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes, arraysize(writes)));
14693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(request,
14703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
14713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunToCompletion(data.get());
14723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TransactionHelperResult out = helper.output();
14733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
14743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, out.rv);
14753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
14763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
14783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Test that a simple HEAD request works.
14793345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, Head) {
1480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Setup the request
1481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpRequestInfo request;
14823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.method = "HEAD";
1483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request.url = GURL("http://www.google.com/");
1484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
14853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const SpdyHeaderInfo kSynStartHeader = {
14863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::SYN_STREAM,             // Kind = Syn
14873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    1,                            // Stream ID
14883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0,                            // Associated stream ID
14893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    net::ConvertRequestPriorityToSpdyPriority(LOWEST),  // Priority
14903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::CONTROL_FLAG_FIN,       // Control Flags
14913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    false,                        // Compressed
14923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::INVALID,                // Status
14933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    NULL,                         // Data
14943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0,                            // Length
14953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::DATA_FLAG_NONE          // Data Flags
14963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
14973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char* const kHeadHeaders[] = {
14983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "method", "HEAD",
14993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "url", "/",
15003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "host", "www.google.com",
15013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "scheme", "http",
15023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "version", "HTTP/1.1",
15033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "content-length", "0"
15043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
15053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPacket(kSynStartHeader, NULL, 0,
1506201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    kHeadHeaders, arraysize(kHeadHeaders) / 2));
15073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
15083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req)
15093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
15103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
15113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
15123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const SpdyHeaderInfo kSynReplyHeader = {
15133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::SYN_REPLY,              // Kind = SynReply
15143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    1,                            // Stream ID
15153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0,                            // Associated stream ID
15163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    net::ConvertRequestPriorityToSpdyPriority(LOWEST),  // Priority
15173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::CONTROL_FLAG_NONE,      // Control Flags
15183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    false,                        // Compressed
15193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::INVALID,                // Status
15203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    NULL,                         // Data
15213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0,                            // Length
15223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::DATA_FLAG_NONE          // Data Flags
15233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
15243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const char* const kStandardGetHeaders[] = {
15253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "status", "200",
15263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "version", "HTTP/1.1"
15273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "content-length", "1234"
15283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
15293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPacket(kSynReplyHeader,
1530201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      NULL, 0, kStandardGetHeaders, arraysize(kStandardGetHeaders) / 2));
15313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
15323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp),
15333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body),
15343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0)  // EOF
15353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
15363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
15373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<DelayedSocketData> data(
15383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new DelayedSocketData(1, reads, arraysize(reads),
15393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes, arraysize(writes)));
15403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(request,
15413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
15423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunToCompletion(data.get());
15433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TransactionHelperResult out = helper.output();
15443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
15453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, out.rv);
15463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
15473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
15483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
15493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Test that a simple POST works.
15503345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, Post) {
15513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(kUploadDataSize, NULL, 0));
1552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = {
1554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockWrite(*req),
1555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockWrite(*body),  // POST upload frame
1556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
1557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
1559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
1560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
1561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
1562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
1563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
1564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
1566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(2, reads, arraysize(reads),
1567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
15683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreatePostRequest(),
15693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
15703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunToCompletion(data.get());
15713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TransactionHelperResult out = helper.output();
15723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, out.rv);
15733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
15743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("hello!", out.response_data);
15753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
15763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1577dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Test that a chunked POST works.
1578dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST_P(SpdyNetworkTransactionTest, ChunkedPost) {
1579dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  UploadDataStream::set_merge_chunks(false);
1580dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0));
1581dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> chunk1(ConstructSpdyBodyFrame(1, false));
1582dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> chunk2(ConstructSpdyBodyFrame(1, true));
1583dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MockWrite writes[] = {
1584dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockWrite(*req),
1585dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockWrite(*chunk1),
1586dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockWrite(*chunk2),
1587dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  };
1588dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1589dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
1590dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MockRead reads[] = {
1591dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*resp),
1592dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*chunk1),
1593dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CreateMockRead(*chunk2),
1594dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    MockRead(true, 0, 0)  // EOF
1595dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  };
1596dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1597dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_refptr<DelayedSocketData> data(
1598dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      new DelayedSocketData(2, reads, arraysize(reads),
1599dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                            writes, arraysize(writes)));
1600dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
1601dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                     BoundNetLog(), GetParam());
1602dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  helper.RunToCompletion(data.get());
1603dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  TransactionHelperResult out = helper.output();
1604dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(OK, out.rv);
1605dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1606dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ("hello!hello!", out.response_data);
1607dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
1608dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
16093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Test that a POST without any post data works.
16103345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, NullPost) {
16113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Setup the request
16123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo request;
16133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.method = "POST";
16143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.url = GURL("http://www.google.com/");
16153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Create an empty UploadData.
16163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.upload_data = NULL;
16173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
16183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // When request.upload_data is NULL for post, content-length is
16193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // expected to be 0.
16203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(0, NULL, 0));
16213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Set the FIN bit since there will be no body.
16223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  req->set_flags(spdy::CONTROL_FLAG_FIN);
16233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
16243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req),
16253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
16263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
16273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
16283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
16293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
16303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp),
16313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body),
16323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0)  // EOF
16333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
16343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
16353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<DelayedSocketData> data(
16363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new DelayedSocketData(1, reads, arraysize(reads),
16373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes, arraysize(writes)));
16383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(request,
16403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
1641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunToCompletion(data.get());
1642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
1643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
1644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("hello!", out.response_data);
1646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test that a simple POST works.
16493345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, EmptyPost) {
1650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Setup the request
1651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpRequestInfo request;
1652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request.method = "POST";
1653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request.url = GURL("http://www.google.com/");
1654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Create an empty UploadData.
1655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request.upload_data = new UploadData();
1656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
16573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Http POST Content-Length is using UploadDataStream::size().
16583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // It is the same as request.upload_data->GetContentLength().
16593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<UploadDataStream> stream(UploadDataStream::Create(
16603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      request.upload_data, NULL));
16613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(request.upload_data->GetContentLength(), stream->size());
16623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
16633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
16643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      req(ConstructSpdyPost(request.upload_data->GetContentLength(), NULL, 0));
1665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Set the FIN bit since there will be no body.
1666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  req->set_flags(spdy::CONTROL_FLAG_FIN);
1667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = {
1668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockWrite(*req),
1669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
1670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
1672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
1674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
1675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
1676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
1677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
1678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
1680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
1681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
1682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(request,
16843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
1685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunToCompletion(data.get());
1686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
1687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
1688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("hello!", out.response_data);
1690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// While we're doing a post, the server sends back a SYN_REPLY.
16933345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, PostWithEarlySynReply) {
1694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const char upload[] = { "hello!" };
1695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Setup the request
1697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpRequestInfo request;
1698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request.method = "POST";
1699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request.url = GURL("http://www.google.com/");
1700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request.upload_data = new UploadData();
1701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request.upload_data->AppendBytes(upload, sizeof(upload));
1702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
17033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Http POST Content-Length is using UploadDataStream::size().
17043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // It is the same as request.upload_data->GetContentLength().
17053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<UploadDataStream> stream(UploadDataStream::Create(
17063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      request.upload_data, NULL));
17073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(request.upload_data->GetContentLength(), stream->size());
17083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> stream_reply(ConstructSpdyPostSynReply(NULL, 0));
17093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> stream_body(ConstructSpdyBodyFrame(1, true));
1710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
17113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream_reply, 2),
17123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream_body, 3),
1713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(false, 0, 0)  // EOF
1714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
1715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
17173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new DelayedSocketData(0, reads, arraysize(reads), NULL, 0));
1718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(request,
17193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
1720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunPreTestSetup();
17213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
1722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunDefaultTest();
17233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
17243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
17263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_SYN_REPLY_NOT_RECEIVED, out.rv);
17273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
17283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
17293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// The client upon cancellation tries to send a RST_STREAM frame. The mock
17303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// socket causes the TCP write to return zero. This test checks that the client
17313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// tries to queue up the RST_STREAM frame again.
17323345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
17333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
17343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> rst(
17353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyRstStream(1, spdy::CANCEL));
17363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
17373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req.get(), 0, false),
17383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockWrite(false, 0, 0, 2),
17393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*rst.get(), 3, false),
17403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
17413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
17423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
17433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
1744731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    CreateMockRead(*resp.get(), 1, true),
1745731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    MockRead(true, 0, 0, 4)  // EOF
17463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
17473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
17483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<DeterministicSocketData> data(
17493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new DeterministicSocketData(reads, arraysize(reads),
1750ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  writes, arraysize(writes)));
17513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
17523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
17533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.SetDeterministic();
17543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
17553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddDeterministicData(data.get());
17563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans = helper.trans();
17573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
17583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
17593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
17603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_IO_PENDING, rv);
17613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
17623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->SetStop(2);
17633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->Run();
17643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.ResetTrans();
17653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->SetStop(20);
17663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->Run();
17673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
17683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
1769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test that the transaction doesn't crash when we don't have a reply.
17723345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ResponseWithoutSynReply) {
1773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
1775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
1776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
1777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
1778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
1780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads), NULL, 0));
1781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
17823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
1783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunToCompletion(data.get());
1784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
1785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_SYN_REPLY_NOT_RECEIVED, out.rv);
1786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test that the transaction doesn't crash when we get two replies on the same
1789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// stream ID. See http://crbug.com/45639.
17903345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
1791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
1793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
1797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
1798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
1799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
1800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
1801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
1802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
1804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
1805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
1806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
18083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
1809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunPreTestSetup();
18103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
1811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
1813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback callback;
1815c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
1816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
1817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = callback.WaitForResult();
1818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, rv);
1819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const HttpResponseInfo* response = trans->GetResponseInfo();
18213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(response != NULL);
1822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->headers != NULL);
1823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->was_fetched_via_spdy);
1824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string response_data;
1825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = ReadTransaction(trans, &response_data);
1826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
1827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.VerifyDataConsumed();
1829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
18313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Test that sent data frames and received WINDOW_UPDATE frames change
18323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// the send_window_size_ correctly.
18333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
18343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// WINDOW_UPDATE is different than most other frames in that it can arrive
18353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// while the client is still sending the request body.  In order to enforce
18363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// this scenario, we feed a couple of dummy frames and give a delay of 0 to
18373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// socket data provider, so that initial read that is done as soon as the
18383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// stream is created, succeeds and schedules another read.  This way reads
18393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// and writes are interleaved; after doing a full frame write, SpdyStream
18403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// will break out of DoLoop and will read and process a WINDOW_UPDATE.
18413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
18423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// since request has not been completely written, therefore we feed
18433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// enough number of WINDOW_UPDATEs to finish the first read and cause a
18443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// write, leading to a complete write of request body; after that we send
18453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// a reply with a body, to cause a graceful shutdown.
18463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
18473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// TODO(agayev): develop a socket data provider where both, reads and
18483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// writes are ordered so that writing tests like these are easy and rewrite
18493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// all these tests using it.  Right now we are working around the
18503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// limitations as described above and it's not deterministic, tests may
18513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// fail under specific circumstances.
18523345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) {
18533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SpdySession::set_flow_control(true);
18543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
18553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static int kFrameCount = 2;
18563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<std::string> content(
18573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new std::string(kMaxSpdyFrameChunkSize, 'a'));
18583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(
18593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      kMaxSpdyFrameChunkSize * kFrameCount, NULL, 0));
18603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body(
18613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyBodyFrame(1, content->c_str(), content->size(), false));
18623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body_end(
18633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyBodyFrame(1, content->c_str(), content->size(), true));
1864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = {
1866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockWrite(*req),
1867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockWrite(*body),
18683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*body_end),
1869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
1870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const int kDeltaWindowSize = 0xff;
18723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const int kDeltaCount = 4;
1873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> window_update(
1874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
18753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> window_update_dummy(
18763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
18773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
1878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
18793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*window_update_dummy),
18803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*window_update_dummy),
18813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*window_update_dummy),
18823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*window_update),     // Four updates, therefore window
18833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*window_update),     // size should increase by
18843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*window_update),     // kDeltaWindowSize * 4
1885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*window_update),
18863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp),
18873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body_end),
1888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
1889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
1890c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1891c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
18923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new DelayedSocketData(0, reads, arraysize(reads),
1893c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
1894c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
18953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Setup the request
18963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo request;
18973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.method = "POST";
18983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.url = GURL(kDefaultURL);
18993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.upload_data = new UploadData();
19003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (int i = 0; i < kFrameCount; ++i)
19013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    request.upload_data->AppendBytes(content->c_str(), content->size());
1902c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
19033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(request, BoundNetLog(), GetParam());
19043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
19053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
1906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
19073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans = helper.trans();
19083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
19103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
1911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
1913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = callback.WaitForResult();
1914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, rv);
1915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
19163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
19173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(stream != NULL);
19183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(stream->stream() != NULL);
1919201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(static_cast<int>(spdy::kSpdyStreamInitialWindowSize) +
19203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            kDeltaWindowSize * kDeltaCount -
19213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            kMaxSpdyFrameChunkSize * kFrameCount,
19223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            stream->stream()->send_window_size());
19233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
19243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SpdySession::set_flow_control(false);
1925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
19273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Test that received data frames and sent WINDOW_UPDATE frames change
19283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// the recv_window_size_ correctly.
19293345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) {
19303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SpdySession::set_flow_control(true);
1931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
19323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
19333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> window_update(
19343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyWindowUpdate(1, kUploadDataSize));
1935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
19363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
19373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req),
19383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*window_update),
19393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
1940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
19413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(
19423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyGetSynReply(NULL, 0, 1));
19433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body_no_fin(
19443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyBodyFrame(1, false));
19453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body_fin(
19463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyBodyFrame(1, NULL, 0, true));
19473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
19483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp),
19493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body_no_fin),
19503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 0),  // Force a pause
19513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body_fin),
19523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 0),  // Force a pause
19533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0)  // EOF
19543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
19553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<DelayedSocketData> data(
19573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new DelayedSocketData(1, reads, arraysize(reads),
19583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes, arraysize(writes)));
19593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
19613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
19623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
19633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
19643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans = helper.trans();
19653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
19673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
19683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_IO_PENDING, rv);
19703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  rv = callback.WaitForResult();
19713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, rv);
19723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SpdyHttpStream* stream =
19743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      static_cast<SpdyHttpStream*>(trans->stream_.get());
19753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(stream != NULL);
19763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(stream->stream() != NULL);
19773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1978201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(
1979201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      static_cast<int>(spdy::kSpdyStreamInitialWindowSize) - kUploadDataSize,
1980201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream->stream()->recv_window_size());
19813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HttpResponseInfo* response = trans->GetResponseInfo();
19833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(response != NULL);
19843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(response->headers != NULL);
19853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
19863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response->was_fetched_via_spdy);
19873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Issue a read which will cause a WINDOW_UPDATE to be sent and window
19893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // size increased to default.
1990513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kUploadDataSize));
19913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  rv = trans->Read(buf, kUploadDataSize, NULL);
19923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(kUploadDataSize, rv);
19933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string content(buf->data(), buf->data()+kUploadDataSize);
19943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_STREQ(kUploadData, content.c_str());
19953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Schedule the reading of empty data frame with FIN
19973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->CompleteRead();
19983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Force write of WINDOW_UPDATE which was scheduled during the above
20003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // read.
20013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MessageLoop::current()->RunAllPending();
20023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
20033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Read EOF.
20043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->CompleteRead();
20053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
20063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
20073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SpdySession::set_flow_control(false);
20083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
20093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
20103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Test that WINDOW_UPDATE frame causing overflow is handled correctly.  We
20113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// use the same trick as in the above test to enforce our scenario.
20123345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
20133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SpdySession::set_flow_control(true);
20143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
20153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // number of full frames we hope to write (but will not, used to
20163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // set content-length header correctly)
20173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static int kFrameCount = 3;
20183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
20193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<std::string> content(
20203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new std::string(kMaxSpdyFrameChunkSize, 'a'));
20213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(
20223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      kMaxSpdyFrameChunkSize * kFrameCount, NULL, 0));
20233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body(
20243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyBodyFrame(1, content->c_str(), content->size(), false));
2025c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> rst(
2026c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ConstructSpdyRstStream(1, spdy::FLOW_CONTROL_ERROR));
20273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
20283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // We're not going to write a data frame with FIN, we'll receive a bad
20293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
2030c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = {
2031c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockWrite(*req),
2032c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockWrite(*body),
2033c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockWrite(*rst),
2034c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
2035c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
20363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const int kDeltaWindowSize = 0x7fffffff;  // cause an overflow
2037c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> window_update(
2038c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
20393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> window_update2(
20403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
2041c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> reply(ConstructSpdyPostSynReply(NULL, 0));
20423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2043c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
20443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*window_update2),
20453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*window_update2),
2046c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*window_update),
20473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*window_update),
20483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*window_update),
20493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 0),  // Wait for the RST to be written.
2050c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
2051c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
2052c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2053c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
20543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new DelayedSocketData(0, reads, arraysize(reads),
2055c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
2056c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
20573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Setup the request
20583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo request;
20593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.method = "POST";
20603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.url = GURL("http://www.google.com/");
20613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.upload_data = new UploadData();
20623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (int i = 0; i < kFrameCount; ++i)
20633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    request.upload_data->AppendBytes(content->c_str(), content->size());
20643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
20653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(request,
20663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
20673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
20683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
2069c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
20703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans = helper.trans();
2071c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
20723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
20733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
2074c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2075c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
2076c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = callback.WaitForResult();
2077c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
2078c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
20793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->CompleteRead();
2080c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
20813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(helper.session() != NULL);
20823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(helper.session()->spdy_session_pool() != NULL);
20833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.session()->spdy_session_pool()->CloseAllSessions();
20843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
20853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
20863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SpdySession::set_flow_control(false);
2087c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
2088c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
20893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Test that after hitting a send window size of 0, the write process
20903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// stalls and upon receiving WINDOW_UPDATE frame write resumes.
20913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
20923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// This test constructs a POST request followed by enough data frames
20933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// containing 'a' that would make the window size 0, followed by another
20943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// data frame containing default content (which is "hello!") and this frame
20953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// also contains a FIN flag.  DelayedSocketData is used to enforce all
20963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// writes go through before a read could happen.  However, the last frame
20973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// ("hello!")  is not supposed to go through since by the time its turn
20983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// arrives, window size is 0.  At this point MessageLoop::Run() called via
20993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// callback would block.  Therefore we call MessageLoop::RunAllPending()
21003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// which returns after performing all possible writes.  We use DCHECKS to
21013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// ensure that last data frame is still there and stream has stalled.
21023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// After that, next read is artifically enforced, which causes a
21033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// WINDOW_UPDATE to be read and I/O process resumes.
21043345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) {
21053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SpdySession::set_flow_control(true);
21063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Number of frames we need to send to zero out the window size: data
21083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // frames plus SYN_STREAM plus the last data frame; also we need another
21093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // data frame that we will send once the WINDOW_UPDATE is received,
21103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // therefore +3.
2111201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  size_t nwrites =
2112201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      spdy::kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
21133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Calculate last frame's size; 0 size data frame is legal.
2115201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  size_t last_frame_size =
2116201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      spdy::kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
21173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Construct content for a data frame of maximum size.
21193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<std::string> content(
21203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new std::string(kMaxSpdyFrameChunkSize, 'a'));
21213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(
2123201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      spdy::kSpdyStreamInitialWindowSize + kUploadDataSize, NULL, 0));
21243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Full frames.
21263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body1(
21273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyBodyFrame(1, content->c_str(), content->size(), false));
21283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Last frame to zero out the window size.
21303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body2(
21313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyBodyFrame(1, content->c_str(), last_frame_size, false));
21323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Data frame to be sent once WINDOW_UPDATE frame is received.
21343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body3(ConstructSpdyBodyFrame(1, true));
21353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Fill in mock writes.
21373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_array<MockWrite> writes(new MockWrite[nwrites]);
21383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  size_t i = 0;
21393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  writes[i] = CreateMockWrite(*req);
21403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (i = 1; i < nwrites-2; i++)
21413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    writes[i] = CreateMockWrite(*body1);
21423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  writes[i++] = CreateMockWrite(*body2);
21433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  writes[i] = CreateMockWrite(*body3);
21443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Construct read frame, give enough space to upload the rest of the
21463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // data.
21473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> window_update(
21483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyWindowUpdate(1, kUploadDataSize));
21493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> reply(ConstructSpdyPostSynReply(NULL, 0));
21503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
21513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*window_update),
21523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*window_update),
21533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*reply),
21543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body2),
21553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body3),
21563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0)  // EOF
21573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
21583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Force all writes to happen before any read, last write will not
21603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // actually queue a frame, due to window size being 0.
21613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<DelayedSocketData> data(
21623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new DelayedSocketData(nwrites, reads, arraysize(reads),
21633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes.get(), nwrites));
21643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo request;
21663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.method = "POST";
21673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.url = GURL("http://www.google.com/");
21683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.upload_data = new UploadData();
21693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<std::string> upload_data(
2170201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      new std::string(spdy::kSpdyStreamInitialWindowSize, 'a'));
21713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  upload_data->append(kUploadData, kUploadDataSize);
21723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request.upload_data->AppendBytes(upload_data->c_str(), upload_data->size());
21733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(request,
21743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
21753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
21763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
21773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans = helper.trans();
21793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
21813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
21823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_IO_PENDING, rv);
21833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MessageLoop::current()->RunAllPending(); // Write as much as we can.
21853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
21873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(stream != NULL);
21883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(stream->stream() != NULL);
21893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(0, stream->stream()->send_window_size());
21903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_FALSE(stream->request_body_stream_->eof());
21913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->ForceNextRead();   // Read in WINDOW_UPDATE frame.
21933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  rv = callback.WaitForResult();
21943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
21953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SpdySession::set_flow_control(false);
21973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
21983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21993345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, CancelledTransaction) {
2200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Construct the request.
2201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = {
2203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockWrite(*req),
2204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
2205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
2208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
2209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // This following read isn't used by the test, except during the
2210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // RunAllPending() call at the end since the SpdySession survives the
2211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // HttpNetworkTransaction and still tries to continue Read()'ing.  Any
2212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // MockRead will do here.
2213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
2214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
2215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  StaticSocketDataProvider data(reads, arraysize(reads),
2217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                writes, arraysize(writes));
2218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
22203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
2221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunPreTestSetup();
22223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(&data);
2223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
2224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback callback;
2226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
2227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
2228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.ResetTrans();  // Cancel the transaction.
2229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
2231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // MockClientSocketFactory) are still alive.
2232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->RunAllPending();
2233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.VerifyDataNotConsumed();
2234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
2235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
22363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Verify that the client sends a Rst Frame upon cancelling the stream.
22373345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
22383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
22393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> rst(
22403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyRstStream(1, spdy::CANCEL));
22413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
22423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req, 0, false),
22433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*rst, 2, false),
22443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
22453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
22463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
22473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
2248731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    CreateMockRead(*resp, 1, true),
2249731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    MockRead(true, 0, 0, 3)  // EOF
22503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
22513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
22523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<DeterministicSocketData> data(
22533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new DeterministicSocketData(reads, arraysize(reads),
22543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes, arraysize(writes)));
22553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
22563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
22573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(),
22583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     GetParam());
22593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.SetDeterministic();
22603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
22613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddDeterministicData(data.get());
22623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans = helper.trans();
22633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
22643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
22653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
22663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
22673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_IO_PENDING, rv);
22683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
22693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->SetStop(2);
22703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->Run();
22713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.ResetTrans();
22723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->SetStop(20);
22733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->Run();
22743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
22753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
22763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
22773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SpdyNetworkTransactionTest::StartTransactionCallback
2279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : public CallbackRunner< Tuple1<int> > {
2280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
2281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  explicit StartTransactionCallback(
22823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      const scoped_refptr<HttpNetworkSession>& session,
2283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NormalSpdyTransactionHelper& helper)
2284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : session_(session), helper_(helper) {}
2285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We try to start another transaction, which should succeed.
2287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void RunWithParams(const Tuple1<int>& params) {
2288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<HttpNetworkTransaction> trans(
2289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        new HttpNetworkTransaction(session_));
2290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TestCompletionCallback callback;
2291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HttpRequestInfo request;
2292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    request.method = "GET";
2293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    request.url = GURL("http://www.google.com/");
2294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    request.load_flags = 0;
2295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int rv = trans->Start(&request, &callback, BoundNetLog());
2296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(ERR_IO_PENDING, rv);
2297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    rv = callback.WaitForResult();
2298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
2299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
23013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const scoped_refptr<HttpNetworkSession>& session_;
2302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper& helper_;
2303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
2304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Verify that the client can correctly deal with the user callback attempting
2306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// to start another transaction on a session that is closing down. See
2307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// http://crbug.com/47455
23083345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
2309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
2311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes2[] = { CreateMockWrite(*req) };
2312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The indicated length of this packet is longer than its actual length. When
2314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the session receives an empty packet after this one, it shuts down the
2315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // session, and calls the read callback with the incomplete data.
2316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const uint8 kGetBodyFrame2[] = {
2317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0x00, 0x00, 0x00, 0x01,
2318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0x01, 0x00, 0x00, 0x07,
2319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    'h', 'e', 'l', 'l', 'o', '!',
2320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
2321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
23223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
23233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
23243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp, 2),
23253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 3),  // Force a pause
23263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame2),
23273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick             arraysize(kGetBodyFrame2), 4),
23283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 5),  // Force a pause
23293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0, 6),  // EOF
23303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
23313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads2[] = {
23323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp, 2),
23333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0, 3),  // EOF
23343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
23353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
23363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data(
23373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(reads, arraysize(reads),
23383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes, arraysize(writes)));
23393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<DelayedSocketData> data2(
23403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new DelayedSocketData(1, reads2, arraysize(reads2),
23413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes2, arraysize(writes2)));
23423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
23433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
23443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
23453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
23463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
23473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data2.get());
23483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans = helper.trans();
23493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
23503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Start the transaction with basic parameters.
23513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
23523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
23533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_IO_PENDING, rv);
23543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  rv = callback.WaitForResult();
23553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
23563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  StartTransactionCallback callback2(helper.session(), helper);
23573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const int kSize = 3000;
2358513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
23593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  rv = trans->Read(buf, kSize, &callback2);
23603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // This forces an err_IO_pending, which sets the callback.
23613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->CompleteRead();
23623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // This finishes the read.
23633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->CompleteRead();
23643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
23653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
23663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
23673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass SpdyNetworkTransactionTest::DeleteSessionCallback
23683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    : public CallbackRunner< Tuple1<int> > {
23693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick public:
23703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  explicit DeleteSessionCallback(NormalSpdyTransactionHelper& helper) :
23713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      helper_(helper) {}
23723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
23733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // We kill the transaction, which deletes the session and stream.
23743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual void RunWithParams(const Tuple1<int>& params) {
23753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    helper_.ResetTrans();
23763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
23773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
23783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick private:
23793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper& helper_;
23803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick};
23813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
23823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Verify that the client can correctly deal with the user callback deleting the
23833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// transaction. Failures will usually be valgrind errors. See
23843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// http://crbug.com/46925
23853345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
23863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
23873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = { CreateMockWrite(*req) };
23883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
23893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
23903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
23913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
23923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp.get(), 2),
23933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 3),  // Force a pause
23943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body.get(), 4),
23953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0, 5),  // EOF
23963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
23973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
23983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data(
23993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(reads, arraysize(reads),
24003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes, arraysize(writes)));
24013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
24023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
24033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
24043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
24053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
24063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans = helper.trans();
24073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
24083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Start the transaction with basic parameters.
24093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
24103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
24113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_IO_PENDING, rv);
24123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  rv = callback.WaitForResult();
24133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
24143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Setup a user callback which will delete the session, and clear out the
24153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // memory holding the stream object. Note that the callback deletes trans.
24163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DeleteSessionCallback callback2(helper);
24173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const int kSize = 3000;
2418513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
24193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  rv = trans->Read(buf, kSize, &callback2);
24203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(ERR_IO_PENDING, rv);
24213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->CompleteRead();
24223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
24233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Finish running rest of tasks.
24243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MessageLoop::current()->RunAllPending();
24253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
24263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
24273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
24283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Send a spdy request to www.google.com that gets redirected to www.foo.com.
24293345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, RedirectGetRequest) {
243021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // These are headers which the net::URLRequest tacks on.
24313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char* const kExtraHeaders[] = {
24323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "accept-encoding",
24333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "gzip,deflate",
24343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
24353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const SpdyHeaderInfo kSynStartHeader = make_spdy_header(spdy::SYN_STREAM);
24363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char* const kStandardGetHeaders[] = {
24373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "host",
24383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "www.google.com",
24393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "method",
24403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "GET",
24413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "scheme",
24423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "http",
24433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "url",
24443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "/",
24453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "user-agent",
24463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "",
24473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "version",
24483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "HTTP/1.1"
24493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
24503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char* const kStandardGetHeaders2[] = {
24513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "host",
24523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "www.foo.com",
24533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "method",
24543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "GET",
24553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "scheme",
24563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "http",
24573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "url",
24583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "/index.php",
24593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "user-agent",
24603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "",
24613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "version",
24623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "HTTP/1.1"
24633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
24643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
24653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Setup writes/reads to www.google.com
24663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPacket(
2467201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      kSynStartHeader, kExtraHeaders, arraysize(kExtraHeaders) / 2,
2468201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      kStandardGetHeaders, arraysize(kStandardGetHeaders) / 2));
24693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyPacket(
2470201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      kSynStartHeader, kExtraHeaders, arraysize(kExtraHeaders) / 2,
2471201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      kStandardGetHeaders2, arraysize(kStandardGetHeaders2) / 2));
24723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReplyRedirect(1));
24733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
24743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req, 1),
24753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
24763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
24773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp, 2),
24783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0, 3)  // EOF
24793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
24803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
24813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Setup writes/reads to www.foo.com
24823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 1));
24833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(1, true));
24843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes2[] = {
24853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req2, 1),
24863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
24873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads2[] = {
24883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp2, 2),
24893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body2, 3),
24903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0, 4)  // EOF
24913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
24923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data(
24933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(reads, arraysize(reads),
24943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes, arraysize(writes)));
24953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data2(
24963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(reads2, arraysize(reads2),
24973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes2, arraysize(writes2)));
24983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
24993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
25003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpStreamFactory::set_force_spdy_over_ssl(false);
25013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpStreamFactory::set_force_spdy_always(true);
25023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestDelegate d;
25033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  {
250421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    net::URLRequest r(GURL("http://www.google.com/"), &d);
25053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    SpdyURLRequestContext* spdy_url_request_context =
25063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        new SpdyURLRequestContext();
25073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    r.set_context(spdy_url_request_context);
25083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy_url_request_context->socket_factory().
25093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        AddSocketDataProvider(data.get());
25103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy_url_request_context->socket_factory().
25113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        AddSocketDataProvider(data2.get());
25123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
25133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    d.set_quit_on_redirect(true);
25143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    r.Start();
25153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MessageLoop::current()->Run();
25163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
25173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(1, d.received_redirect_count());
25183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
25193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    r.FollowDeferredRedirect();
25203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MessageLoop::current()->Run();
25213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(1, d.response_started_count());
25223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_FALSE(d.received_data_before_response());
252372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    EXPECT_EQ(net::URLRequestStatus::SUCCESS, r.status().status());
25243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    std::string contents("hello!");
25253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(contents, d.data_received());
25263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
25273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data->at_read_eof());
25283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data->at_write_eof());
25293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data2->at_read_eof());
25303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data2->at_write_eof());
25313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
25323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
25333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Send a spdy request to www.google.com. Get a pushed stream that redirects to
25343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// www.foo.com.
25353345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, RedirectServerPush) {
253621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // These are headers which the net::URLRequest tacks on.
25373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char* const kExtraHeaders[] = {
25383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "accept-encoding",
25393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "gzip,deflate",
25403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
25413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const SpdyHeaderInfo kSynStartHeader = make_spdy_header(spdy::SYN_STREAM);
25423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char* const kStandardGetHeaders[] = {
25433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "host",
25443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "www.google.com",
25453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "method",
25463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "GET",
25473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "scheme",
25483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "http",
25493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "url",
25503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "/",
25513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "user-agent",
25523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "",
25533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "version",
25543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "HTTP/1.1"
25553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
25563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
25573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Setup writes/reads to www.google.com
2558201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame> req(
2559201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      ConstructSpdyPacket(kSynStartHeader,
2560201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                          kExtraHeaders,
2561201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                          arraysize(kExtraHeaders) / 2,
2562201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                          kStandardGetHeaders,
2563201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                          arraysize(kStandardGetHeaders) / 2));
25643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2565201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame> rep(
2566201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      ConstructSpdyPush(NULL,
2567201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                        0,
2568201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                        2,
2569201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                        1,
2570201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                        "http://www.google.com/foo.dat",
2571201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                        "301 Moved Permanently",
2572201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                        "http://www.foo.com/index.php"));
25733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
2574ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_ptr<spdy::SpdyFrame> rst(ConstructSpdyRstStream(2, spdy::CANCEL));
25753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
25763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req, 1),
2577ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    CreateMockWrite(*rst, 6),
25783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
25793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
25803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp, 2),
25813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*rep, 3),
25823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body, 4),
25833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 5),  // Force a pause
2584ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    MockRead(true, 0, 0, 7)  // EOF
25853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
25863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
25873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Setup writes/reads to www.foo.com
2588ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const char* const kStandardGetHeaders2[] = {
2589ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    "host",
2590ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    "www.foo.com",
2591ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    "method",
2592ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    "GET",
2593ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    "scheme",
2594ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    "http",
2595ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    "url",
2596ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    "/index.php",
2597ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    "user-agent",
2598ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    "",
2599ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    "version",
2600ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    "HTTP/1.1"
2601ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  };
2602ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_ptr<spdy::SpdyFrame> req2(
2603ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ConstructSpdyPacket(kSynStartHeader,
2604ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                          kExtraHeaders,
2605ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                          arraysize(kExtraHeaders) / 2,
2606ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                          kStandardGetHeaders2,
2607ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                          arraysize(kStandardGetHeaders2) / 2));
26083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 1));
26093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(1, true));
26103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes2[] = {
26113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req2, 1),
26123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
26133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads2[] = {
26143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp2, 2),
26153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body2, 3),
26163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0, 5)  // EOF
26173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
26183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data(
26193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(reads, arraysize(reads),
26203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes, arraysize(writes)));
26213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data2(
26223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(reads2, arraysize(reads2),
26233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes2, arraysize(writes2)));
26243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
26253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
26263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpStreamFactory::set_force_spdy_over_ssl(false);
26273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpStreamFactory::set_force_spdy_always(true);
26283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestDelegate d;
26293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestDelegate d2;
26303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<SpdyURLRequestContext> spdy_url_request_context(
26313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new SpdyURLRequestContext());
26323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  {
263321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    net::URLRequest r(GURL("http://www.google.com/"), &d);
26343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    r.set_context(spdy_url_request_context);
26353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy_url_request_context->socket_factory().
26363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        AddSocketDataProvider(data.get());
26373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
26383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    r.Start();
26393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MessageLoop::current()->Run();
26403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
26413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(0, d.received_redirect_count());
26423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    std::string contents("hello!");
26433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(contents, d.data_received());
26443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
264521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    net::URLRequest r2(GURL("http://www.google.com/foo.dat"), &d2);
26463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    r2.set_context(spdy_url_request_context);
26473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy_url_request_context->socket_factory().
26483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        AddSocketDataProvider(data2.get());
26493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
26503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    d2.set_quit_on_redirect(true);
26513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    r2.Start();
26523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MessageLoop::current()->Run();
26533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(1, d2.received_redirect_count());
26543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
26553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    r2.FollowDeferredRedirect();
26563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MessageLoop::current()->Run();
26573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(1, d2.response_started_count());
26583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_FALSE(d2.received_data_before_response());
265972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    EXPECT_EQ(net::URLRequestStatus::SUCCESS, r2.status().status());
26603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    std::string contents2("hello!");
26613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    EXPECT_EQ(contents2, d2.data_received());
26623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
26633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->CompleteRead();
26643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data2->CompleteRead();
26653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data->at_read_eof());
26663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data->at_write_eof());
26673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data2->at_read_eof());
26683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data2->at_write_eof());
26693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
26703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
26713345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
26723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const unsigned char kPushBodyFrame[] = {
26733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0x00, 0x00, 0x00, 0x02,                                      // header, ID
26743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0x01, 0x00, 0x00, 0x06,                                      // FIN, length
26753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed"
26763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
26773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
26783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
26793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
26803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_body(ConstructSpdyBodyFrame(1, true));
26813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
26823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*stream1_syn, 1),
26833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
26843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
26853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
26863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
26873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
2688201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_syn(ConstructSpdyPush(NULL,
2689201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    0,
2690201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    2,
2691201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    1,
2692201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    "http://www.google.com/foo.dat"));
26933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
26943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_reply, 2),
26953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream2_syn, 3),
26963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_body, 4, false),
26973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame),
26983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick             arraysize(kPushBodyFrame), 5),
26993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 6),  // Force a pause
27003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
27013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
27023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response;
27033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response2;
27043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string expected_push_result("pushed");
2705201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_refptr<OrderedSocketData> data(new OrderedSocketData(
2706201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      reads,
2707201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(reads),
2708201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      writes,
2709201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(writes)));
2710201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  RunServerPushTest(data.get(),
2711201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    &response,
2712201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    &response2,
2713201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    expected_push_result);
27143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
27153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the SYN_REPLY.
27163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response.headers != NULL);
27173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
27183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
27193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the pushed stream.
27203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response2.headers != NULL);
27213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
27223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
27233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
27243345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
27253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const unsigned char kPushBodyFrame[] = {
27263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0x00, 0x00, 0x00, 0x02,                                      // header, ID
27273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0x01, 0x00, 0x00, 0x06,                                      // FIN, length
27283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed"
27293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
27303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
27313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
27323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
27333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*stream1_syn, 1),
27343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
27353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
27363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
27373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
27383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
2739201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_syn(ConstructSpdyPush(NULL,
2740201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    0,
2741201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    2,
2742201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    1,
2743201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    "http://www.google.com/foo.dat"));
27443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
27453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_body(ConstructSpdyBodyFrame(1, true));
27463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
27473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_reply, 2),
27483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream2_syn, 3),
27493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame),
27503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick             arraysize(kPushBodyFrame), 5),
27513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_body, 4, false),
27523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 6),  // Force a pause
27533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
27543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
27553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response;
27563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response2;
27573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string expected_push_result("pushed");
2758201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_refptr<OrderedSocketData> data(new OrderedSocketData(
2759201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      reads,
2760201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(reads),
2761201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      writes,
2762201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(writes)));
2763201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  RunServerPushTest(data.get(),
2764201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    &response,
2765201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    &response2,
2766201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    expected_push_result);
27673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
27683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the SYN_REPLY.
27693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response.headers != NULL);
27703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
27713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
27723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the pushed stream.
27733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response2.headers != NULL);
27743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
27753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
27763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
27773345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ServerPushServerAborted) {
27783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
27793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
27803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
27813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_body(ConstructSpdyBodyFrame(1, true));
27823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
27833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*stream1_syn, 1),
27843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
27853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
27863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
27873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
27883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
2789201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_syn(ConstructSpdyPush(NULL,
2790201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    0,
2791201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    2,
2792201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    1,
2793201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    "http://www.google.com/foo.dat"));
27943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
27953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    stream2_rst(ConstructSpdyRstStream(2, spdy::PROTOCOL_ERROR));
27963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
27973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_reply, 2),
27983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream2_syn, 3),
27993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream2_rst, 4),
28003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_body, 5, false),
28013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 6),  // Force a pause
28023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
28033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
28043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data(
28053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(reads, arraysize(reads),
28063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes, arraysize(writes)));
28073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
28083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
28093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
28103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
28113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
28123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
28133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans = helper.trans();
28143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
28153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Start the transaction with basic parameters.
28163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
28173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
28183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_IO_PENDING, rv);
28193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  rv = callback.WaitForResult();
28203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, rv);
28213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
28223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify that we consumed all test data.
28233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data->at_read_eof()) << "Read count: "
28243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   << data->read_count()
28253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   << " Read index: "
28263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   << data->read_index();
28273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data->at_write_eof()) << "Write count: "
28283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                    << data->write_count()
28293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                    << " Write index: "
28303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                    << data->write_index();
28313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
28323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the SYN_REPLY.
28333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response = *trans->GetResponseInfo();
28343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response.headers != NULL);
28353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
28363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
28373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
28383345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ServerPushDuplicate) {
28393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify that we don't leak streams and that we properly send a reset
28403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // if the server pushes the same stream twice.
28413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const unsigned char kPushBodyFrame[] = {
28423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0x00, 0x00, 0x00, 0x02,                                      // header, ID
28433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0x01, 0x00, 0x00, 0x06,                                      // FIN, length
28443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed"
28453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
28463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
28473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
28483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
28493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
28503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_body(ConstructSpdyBodyFrame(1, true));
28513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
28523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream3_rst(ConstructSpdyRstStream(4, spdy::PROTOCOL_ERROR));
28533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
28543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*stream1_syn, 1),
28553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*stream3_rst, 5),
28563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
28573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
28583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
28593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
28603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
2861201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_syn(ConstructSpdyPush(NULL,
2862201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    0,
2863201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    2,
2864201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    1,
2865201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    "http://www.google.com/foo.dat"));
28663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
2867201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream3_syn(ConstructSpdyPush(NULL,
2868201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    0,
2869201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    4,
2870201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    1,
2871201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    "http://www.google.com/foo.dat"));
28723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
28733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_reply, 2),
28743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream2_syn, 3),
28753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream3_syn, 4),
28763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_body, 6, false),
28773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame),
28783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick             arraysize(kPushBodyFrame), 7),
28793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 8),  // Force a pause
28803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
28813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
28823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response;
28833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response2;
28843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string expected_push_result("pushed");
2885201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_refptr<OrderedSocketData> data(new OrderedSocketData(
2886201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      reads,
2887201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(reads),
2888201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      writes,
2889201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(writes)));
2890201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  RunServerPushTest(data.get(),
2891201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    &response,
2892201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    &response2,
2893201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    expected_push_result);
28943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
28953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the SYN_REPLY.
28963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response.headers != NULL);
28973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
28983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
28993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the pushed stream.
29003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response2.headers != NULL);
29013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
29023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
29033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
29043345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
29053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const unsigned char kPushBodyFrame1[] = {
29063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0x00, 0x00, 0x00, 0x02,                                      // header, ID
29073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0x01, 0x00, 0x00, 0x1F,                                      // FIN, length
29083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed"
29093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
29103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const char kPushBodyFrame2[] = " my darling";
29113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const char kPushBodyFrame3[] = " hello";
29123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const char kPushBodyFrame4[] = " my baby";
29133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
29143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
29153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
29163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
29173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_body(ConstructSpdyBodyFrame(1, true));
29183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
29193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*stream1_syn, 1),
29203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
29213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
29223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
29233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
29243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
2925201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_syn(ConstructSpdyPush(NULL,
2926201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    0,
2927201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    2,
2928201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    1,
2929201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    "http://www.google.com/foo.dat"));
29303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
29313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_reply, 2),
29323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream2_syn, 3),
29333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame1),
29343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick             arraysize(kPushBodyFrame1), 4),
29353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame2),
29363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick             arraysize(kPushBodyFrame2) - 1, 5),
29373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame3),
29383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick             arraysize(kPushBodyFrame3) - 1, 6),
29393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame4),
29403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick             arraysize(kPushBodyFrame4) - 1, 7),
29413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_body, 8, false),
29423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 9),  // Force a pause
29433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
29443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
29453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response;
29463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response2;
29473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string expected_push_result("pushed my darling hello my baby");
2948201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_refptr<OrderedSocketData> data(new OrderedSocketData(
2949201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      reads,
2950201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(reads),
2951201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      writes,
2952201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(writes)));
2953201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  RunServerPushTest(data.get(),
2954201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    &response,
2955201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    &response2,
2956201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    expected_push_result);
29573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
29583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the SYN_REPLY.
29593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response.headers != NULL);
29603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
29613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
29623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the pushed stream.
29633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response2.headers != NULL);
29643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
29653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
29663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
29673345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
29683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const unsigned char kPushBodyFrame1[] = {
29693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0x00, 0x00, 0x00, 0x02,                                      // header, ID
29703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0x01, 0x00, 0x00, 0x1F,                                      // FIN, length
29713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed"
29723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
29733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const char kPushBodyFrame2[] = " my darling";
29743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const char kPushBodyFrame3[] = " hello";
29753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const char kPushBodyFrame4[] = " my baby";
29763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
29773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
29783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
29793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
29803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_body(ConstructSpdyBodyFrame(1, true));
29813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
29823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*stream1_syn, 1),
29833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
29843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
29853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
29863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
29873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
2988201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_syn(ConstructSpdyPush(NULL,
2989201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    0,
2990201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    2,
2991201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    1,
2992201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    "http://www.google.com/foo.dat"));
29933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
29943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_reply, 2),
29953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream2_syn, 3),
29963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame1),
29973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick             arraysize(kPushBodyFrame1), 4),
29983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame2),
29993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick             arraysize(kPushBodyFrame2) - 1, 5),
30003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 6),  // Force a pause
30013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame3),
30023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick             arraysize(kPushBodyFrame3) - 1, 7),
30033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame4),
30043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick             arraysize(kPushBodyFrame4) - 1, 8),
30053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_body.get(), 9, false),
30063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 10)  // Force a pause.
30073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
30083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
30093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response;
30103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response2;
30113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string expected_push_result("pushed my darling hello my baby");
3012201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_refptr<OrderedSocketData> data(new OrderedSocketData(
3013201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      reads,
3014201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(reads),
3015201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      writes,
3016201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(writes)));
3017201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  RunServerPushTest(data.get(),
3018201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    &response,
3019201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    &response2,
3020201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    expected_push_result);
30213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
30223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the SYN_REPLY.
30233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response.headers != NULL);
30243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
30253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
30263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the pushed stream.
30273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response2.headers != NULL);
30283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
30293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
30303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
30313345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
30323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
30333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
30343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
30353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_body(ConstructSpdyBodyFrame(1, true));
30363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
30373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream2_rst(ConstructSpdyRstStream(2, spdy::INVALID_STREAM));
30383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
30393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*stream1_syn, 1),
30403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*stream2_rst, 4),
30413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
30423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
30433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
30443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
30453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
3046201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_syn(ConstructSpdyPush(NULL,
3047201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    0,
3048201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    2,
3049201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    0,
3050201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    "http://www.google.com/foo.dat"));
30513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
30523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_reply, 2),
30533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream2_syn, 3),
30543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_body, 4),
30553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 5)  // Force a pause
30563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
30573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
30583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data(
30593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(reads, arraysize(reads),
30603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes, arraysize(writes)));
30613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
30623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
30633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
30643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
30653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
30663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
30673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans = helper.trans();
30683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
30693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Start the transaction with basic parameters.
30703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
30713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
30723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_IO_PENDING, rv);
30733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  rv = callback.WaitForResult();
30743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, rv);
30753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
30763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify that we consumed all test data.
30773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data->at_read_eof()) << "Read count: "
30783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   << data->read_count()
30793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   << " Read index: "
30803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   << data->read_index();
30813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data->at_write_eof()) << "Write count: "
30823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                    << data->write_count()
30833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                    << " Write index: "
30843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                    << data->write_index();
30853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
30863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the SYN_REPLY.
30873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response = *trans->GetResponseInfo();
30883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response.headers != NULL);
30893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
30903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
30913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
30923345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
30933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
30943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
30953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
30963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_body(ConstructSpdyBodyFrame(1, true));
30973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
30983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream2_rst(ConstructSpdyRstStream(2, spdy::INVALID_ASSOCIATED_STREAM));
30993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
31003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*stream1_syn, 1),
31013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*stream2_rst, 4),
31023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
31033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
31043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
31053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
31063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
3107201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_syn(ConstructSpdyPush(NULL,
3108201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    0,
3109201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    2,
3110201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    9,
3111201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    "http://www.google.com/foo.dat"));
3112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
31133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_reply, 2),
31143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream2_syn, 3),
31153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_body, 4),
3116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, ERR_IO_PENDING, 5),  // Force a pause
3117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<OrderedSocketData> data(
3120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new OrderedSocketData(reads, arraysize(reads),
3121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
3122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
31233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
31243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunPreTestSetup();
31263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
31273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
3129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Start the transaction with basic parameters.
3131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback callback;
31323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
3133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
3134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = callback.WaitForResult();
31353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, rv);
3136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
31373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify that we consumed all test data.
31383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data->at_read_eof()) << "Read count: "
31393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   << data->read_count()
31403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   << " Read index: "
31413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   << data->read_index();
31423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data->at_write_eof()) << "Write count: "
31433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                    << data->write_count()
31443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                    << " Write index: "
31453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                    << data->write_index();
31463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
31473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the SYN_REPLY.
31483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response = *trans->GetResponseInfo();
31493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response.headers != NULL);
31503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
3152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
31533345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ServerPushNoURL) {
31543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
31553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
31563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
31573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_body(ConstructSpdyBodyFrame(1, true));
31583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
31593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream2_rst(ConstructSpdyRstStream(2, spdy::PROTOCOL_ERROR));
31603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
31613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*stream1_syn, 1),
31623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*stream2_rst, 4),
31633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
3164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
31653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
31663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
31673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame>
31683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream2_syn(ConstructSpdyPush(NULL, 0, 2, 1));
3169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
31703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_reply, 2),
31713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream2_syn, 3),
31723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*stream1_body, 4),
31733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 5)  // Force a pause
3174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<OrderedSocketData> data(
3177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new OrderedSocketData(reads, arraysize(reads),
3178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
3179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
31803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
31813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunPreTestSetup();
31833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
31843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
3186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Start the transaction with basic parameters.
3188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback callback;
31893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
3190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
3191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = callback.WaitForResult();
31923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, rv);
31933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify that we consumed all test data.
31943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data->at_read_eof()) << "Read count: "
31953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   << data->read_count()
31963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   << " Read index: "
31973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   << data->read_index();
31983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(data->at_write_eof()) << "Write count: "
31993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                    << data->write_count()
32003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                    << " Write index: "
32013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                    << data->write_index();
32023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
32033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the SYN_REPLY.
32043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response = *trans->GetResponseInfo();
32053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response.headers != NULL);
32063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
3208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Verify that various SynReply headers parse correctly through the
3210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// HTTP layer.
32113345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) {
3212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct SynReplyHeadersTests {
3213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int num_headers;
3214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const char* extra_headers[5];
3215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const char* expected_headers;
3216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } test_cases[] = {
3217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // This uses a multi-valued cookie header.
3218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { 2,
3219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { "cookie", "val1",
3220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "cookie", "val2",  // will get appended separated by NULL
3221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NULL
3222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      },
3223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "cookie: val1\n"
3224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "cookie: val2\n"
3225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "hello: bye\n"
3226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "status: 200\n"
3227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "version: HTTP/1.1\n"
3228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
3229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // This is the minimalist set of headers.
3230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { 0,
3231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { NULL },
3232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "hello: bye\n"
3233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "status: 200\n"
3234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "version: HTTP/1.1\n"
3235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
3236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Headers with a comma separated list.
3237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { 1,
3238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { "cookie", "val1,val2",
3239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NULL
3240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      },
3241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "cookie: val1,val2\n"
3242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "hello: bye\n"
3243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "status: 200\n"
3244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "version: HTTP/1.1\n"
3245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
3246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<spdy::SpdyFrame> req(
3250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockWrite writes[] = { CreateMockWrite(*req) };
3252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<spdy::SpdyFrame> resp(
3254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ConstructSpdyGetSynReply(test_cases[i].extra_headers,
3255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 test_cases[i].num_headers,
3256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 1));
3257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead reads[] = {
3259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CreateMockRead(*resp),
3260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CreateMockRead(*body),
3261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      MockRead(true, 0, 0)  // EOF
3262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    };
3263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_refptr<DelayedSocketData> data(
3265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        new DelayedSocketData(1, reads, arraysize(reads),
3266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              writes, arraysize(writes)));
3267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NormalSpdyTransactionHelper helper(CreateGetRequest(),
32683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                       BoundNetLog(), GetParam());
3269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    helper.RunToCompletion(data.get());
3270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TransactionHelperResult out = helper.output();
3271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(OK, out.rv);
3273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ("hello!", out.response_data);
3275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(headers.get() != NULL);
3278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void* iter = NULL;
3279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string name, value, lines;
3280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      lines.append(name);
3282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      lines.append(": ");
3283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      lines.append(value);
3284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      lines.append("\n");
3285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
3286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(std::string(test_cases[i].expected_headers), lines);
3287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
3288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
3289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Verify that various SynReply headers parse vary fields correctly
3291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// through the HTTP layer, and the response matches the request.
32923345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) {
3293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const SpdyHeaderInfo syn_reply_info = {
3294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SYN_REPLY,                              // Syn Reply
3295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    1,                                            // Stream ID
3296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0,                                            // Associated Stream ID
32973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    net::ConvertRequestPriorityToSpdyPriority(LOWEST),
32983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                  // Priority
3299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::CONTROL_FLAG_NONE,                      // Control Flags
3300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    false,                                        // Compressed
3301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::INVALID,                                // Status
3302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NULL,                                         // Data
3303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0,                                            // Data Length
3304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::DATA_FLAG_NONE                          // Data Flags
3305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Modify the following data to change/add test cases:
3307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct SynReplyTests {
3308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const SpdyHeaderInfo* syn_reply;
3309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool vary_matches;
3310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int num_headers[2];
3311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const char* extra_headers[2][16];
3312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } test_cases[] = {
3313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Test the case of a multi-valued cookie.  When the value is delimited
3314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // with NUL characters, it needs to be unfolded into multiple headers.
3315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    {
3316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &syn_reply_info,
3317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      true,
3318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { 1, 4 },
3319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { { "cookie",   "val1,val2",
3320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NULL
3321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        },
3322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        { "vary",     "cookie",
3323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "status",   "200",
3324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "url",      "/index.php",
3325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "version",  "HTTP/1.1",
3326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NULL
3327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
3328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
3329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }, {    // Multiple vary fields.
3330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &syn_reply_info,
3331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      true,
3332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { 2, 5 },
3333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { { "friend",   "barney",
3334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "enemy",    "snaggletooth",
3335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NULL
3336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        },
3337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        { "vary",     "friend",
3338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "vary",     "enemy",
3339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "status",   "200",
3340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "url",      "/index.php",
3341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "version",  "HTTP/1.1",
3342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NULL
3343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
3344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
3345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }, {    // Test a '*' vary field.
3346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &syn_reply_info,
3347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      false,
3348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { 1, 4 },
3349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { { "cookie",   "val1,val2",
3350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NULL
3351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        },
3352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        { "vary",     "*",
3353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "status",   "200",
3354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "url",      "/index.php",
3355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "version",  "HTTP/1.1",
3356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NULL
3357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
3358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
3359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }, {    // Multiple comma-separated vary fields.
3360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &syn_reply_info,
3361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      true,
3362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { 2, 4 },
3363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { { "friend",   "barney",
3364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "enemy",    "snaggletooth",
3365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NULL
3366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        },
3367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        { "vary",     "friend,enemy",
3368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "status",   "200",
3369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "url",      "/index.php",
3370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "version",  "HTTP/1.1",
3371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NULL
3372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
3373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
3374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
3375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Construct the request.
3379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<spdy::SpdyFrame> frame_req(
3380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ConstructSpdyGet(test_cases[i].extra_headers[0],
3381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       test_cases[i].num_headers[0],
3382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       false, 1, LOWEST));
3383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockWrite writes[] = {
3385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CreateMockWrite(*frame_req),
3386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    };
3387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Construct the reply.
3389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<spdy::SpdyFrame> frame_reply(
3390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ConstructSpdyPacket(*test_cases[i].syn_reply,
3391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          test_cases[i].extra_headers[1],
3392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          test_cases[i].num_headers[1],
3393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          NULL,
3394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          0));
3395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead reads[] = {
3398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CreateMockRead(*frame_reply),
3399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CreateMockRead(*body),
3400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      MockRead(true, 0, 0)  // EOF
3401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    };
3402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Attach the headers to the request.
3404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int header_count = test_cases[i].num_headers[0];
3405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HttpRequestInfo request = CreateGetRequest();
3407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (int ct = 0; ct < header_count; ct++) {
3408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const char* header_key = test_cases[i].extra_headers[0][ct * 2];
3409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1];
3410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      request.extra_headers.SetHeader(header_key, header_value);
3411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
3412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_refptr<DelayedSocketData> data(
3414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        new DelayedSocketData(1, reads, arraysize(reads),
3415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              writes, arraysize(writes)));
3416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NormalSpdyTransactionHelper helper(request,
34173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                       BoundNetLog(), GetParam());
3418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    helper.RunToCompletion(data.get());
3419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TransactionHelperResult out = helper.output();
3420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(OK, out.rv) << i;
3422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line) << i;
3423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ("hello!", out.response_data) << i;
3424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Test the response information.
3426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(out.response_info.response_time >
3427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                out.response_info.request_time) << i;
3428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    base::TimeDelta test_delay = out.response_info.response_time -
3429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 out.response_info.request_time;
3430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    base::TimeDelta min_expected_delay;
3431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    min_expected_delay.FromMilliseconds(10);
3432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_GT(test_delay.InMillisecondsF(),
3433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              min_expected_delay.InMillisecondsF()) << i;
3434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(out.response_info.vary_data.is_valid(),
3435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              test_cases[i].vary_matches) << i;
3436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Check the headers.
3438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ASSERT_TRUE(headers.get() != NULL) << i;
3440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void* iter = NULL;
3441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string name, value, lines;
3442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      lines.append(name);
3444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      lines.append(": ");
3445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      lines.append(value);
3446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      lines.append("\n");
3447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
3448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Construct the expected header reply string.
3450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    char reply_buffer[256] = "";
3451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ConstructSpdyReplyString(test_cases[i].extra_headers[1],
3452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             test_cases[i].num_headers[1],
3453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             reply_buffer,
3454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             256);
3455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(std::string(reply_buffer), lines) << i;
3457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
3458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
3459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Verify that we don't crash on invalid SynReply responses.
34613345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, InvalidSynReply) {
3462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const SpdyHeaderInfo kSynStartHeader = {
3463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SYN_REPLY,              // Kind = SynReply
3464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    1,                            // Stream ID
3465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0,                            // Associated stream ID
34663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    net::ConvertRequestPriorityToSpdyPriority(LOWEST),
34673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                  // Priority
3468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::CONTROL_FLAG_NONE,      // Control Flags
3469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    false,                        // Compressed
3470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::INVALID,                // Status
3471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NULL,                         // Data
3472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0,                            // Length
3473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::DATA_FLAG_NONE          // Data Flags
3474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct InvalidSynReplyTests {
3477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int num_headers;
3478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const char* headers[10];
3479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } test_cases[] = {
3480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // SYN_REPLY missing status header
3481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { 4,
3482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { "cookie", "val1",
3483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "cookie", "val2",
3484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "url", "/index.php",
3485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "version", "HTTP/1.1",
3486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NULL
3487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      },
3488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
3489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // SYN_REPLY missing version header
3490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { 2,
3491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      { "status", "200",
3492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "url", "/index.php",
3493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NULL
3494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      },
3495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
3496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // SYN_REPLY with no headers
3497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    { 0, { NULL }, },
3498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<spdy::SpdyFrame> req(
3502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockWrite writes[] = {
3504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CreateMockWrite(*req),
3505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    };
3506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<spdy::SpdyFrame> resp(
3508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ConstructSpdyPacket(kSynStartHeader,
3509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            NULL, 0,
3510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            test_cases[i].headers,
3511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            test_cases[i].num_headers));
3512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead reads[] = {
3514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CreateMockRead(*resp),
3515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CreateMockRead(*body),
3516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      MockRead(true, 0, 0)  // EOF
3517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    };
3518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_refptr<DelayedSocketData> data(
3520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        new DelayedSocketData(1, reads, arraysize(reads),
3521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              writes, arraysize(writes)));
3522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NormalSpdyTransactionHelper helper(CreateGetRequest(),
35233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                       BoundNetLog(), GetParam());
3524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    helper.RunToCompletion(data.get());
3525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TransactionHelperResult out = helper.output();
3526201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    EXPECT_EQ(ERR_INCOMPLETE_SPDY_HEADERS, out.rv);
3527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
3528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
3529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Verify that we don't crash on some corrupt frames.
353172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenTEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
353272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // This is the length field that's too short.
353372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  scoped_ptr<spdy::SpdyFrame> syn_reply_wrong_length(
3534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ConstructSpdyGetSynReply(NULL, 0, 1));
353572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  syn_reply_wrong_length->set_length(syn_reply_wrong_length->length() - 4);
3536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct SynReplyTests {
3538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const spdy::SpdyFrame* syn_reply;
3539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } test_cases[] = {
354072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    { syn_reply_wrong_length.get(), },
3541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<spdy::SpdyFrame> req(
3545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockWrite writes[] = {
3547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CreateMockWrite(*req),
3548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      MockWrite(true, 0, 0)  // EOF
3549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    };
3550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead reads[] = {
3553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CreateMockRead(*test_cases[i].syn_reply),
3554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CreateMockRead(*body),
3555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      MockRead(true, 0, 0)  // EOF
3556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    };
3557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_refptr<DelayedSocketData> data(
3559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        new DelayedSocketData(1, reads, arraysize(reads),
3560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              writes, arraysize(writes)));
3561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NormalSpdyTransactionHelper helper(CreateGetRequest(),
35623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                       BoundNetLog(), GetParam());
3563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    helper.RunToCompletion(data.get());
3564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TransactionHelperResult out = helper.output();
3565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
3567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
3568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test that we shutdown correctly on write errors.
35703345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, WriteError) {
3571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = {
3573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We'll write 10 bytes successfully
3574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockWrite(true, req->data(), 10),
3575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Followed by ERROR!
3576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockWrite(true, ERR_FAILED),
3577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
3580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(2, NULL, 0,
3581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
3582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
35833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
3584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunToCompletion(data.get());
3585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
3586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_FAILED, out.rv);
3587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  data->Reset();
3588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
3589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test that partial writes work.
35913345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, PartialWrite) {
3592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Chop the SYN_STREAM frame into 5 chunks.
3593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const int kChunks = 5;
3595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_array<MockWrite> writes(ChopWriteFrame(*req.get(), kChunks));
3596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
3598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
3600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
3601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
3602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
3603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
3606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(kChunks, reads, arraysize(reads),
3607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes.get(), kChunks));
3608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
36093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
3610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunToCompletion(data.get());
3611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
3612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
3613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("hello!", out.response_data);
3615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
3616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// In this test, we enable compression, but get a uncompressed SynReply from
3618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the server.  Verify that teardown is all clean.
36193345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) {
3620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // For this test, we turn on the normal compression.
3621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EnableCompression(true);
3622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> compressed(
3624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ConstructSpdyGet(NULL, 0, true, 1, LOWEST));
36253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> rst(
36263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ConstructSpdyRstStream(1, spdy::PROTOCOL_ERROR));
3627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = {
3628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockWrite(*compressed),
36293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*rst),
3630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
3633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
3635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
3636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
36373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0)
3638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
3641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
3642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
3643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
36443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
3645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunToCompletion(data.get());
3646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
36473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  data->Reset();
3649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EnableCompression(false);
3651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
3652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test that the NetLog contains good data for a simple GET request.
36543345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, NetLog) {
36554a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  static const char* const kExtraHeaders[] = {
36564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    "user-agent",   "Chrome",
36574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  };
36584a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(kExtraHeaders, 1, false, 1,
36594a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                                                   LOWEST));
3660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
3661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
3663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
3665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
3666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
3667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
3668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net::CapturingBoundNetLog log(net::CapturingNetLog::kUnbounded);
3671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
3673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
3674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
36754a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(),
36763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     log.bound(), GetParam());
3677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunToCompletion(data.get());
3678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
3679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
3680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("hello!", out.response_data);
3682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Check that the NetLog was filled reasonably.
3684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This test is intentionally non-specific about the exact ordering of the
3685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // log; instead we just check to make sure that certain events exist, and that
3686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // they are in the right order.
368721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  net::CapturingNetLog::EntryList entries;
368821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  log.GetEntries(&entries);
368921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
369021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  EXPECT_LT(0u, entries.size());
3691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int pos = 0;
369221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  pos = net::ExpectLogContainsSomewhere(entries, 0,
36933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      net::NetLog::PHASE_BEGIN);
369521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
36963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      net::NetLog::PHASE_END);
369821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
36993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      net::NetLog::PHASE_BEGIN);
370121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
37023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      net::NetLog::PHASE_END);
370421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
37053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      net::NetLog::PHASE_BEGIN);
370721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
37083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      net::NetLog::PHASE_END);
37104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
37114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // Check that we logged all the headers correctly
37124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  pos = net::ExpectLogContainsSomewhere(
371321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      entries, 0,
37144a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM,
37154a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      net::NetLog::PHASE_NONE);
371621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  CapturingNetLog::Entry entry = entries[pos];
37174a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  NetLogSpdySynParameter* request_params =
37184a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      static_cast<NetLogSpdySynParameter*>(entry.extra_parameters.get());
37194a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  spdy::SpdyHeaderBlock* headers =
37204a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      request_params->GetHeaders().get();
37214a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
37224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  spdy::SpdyHeaderBlock expected;
37234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  expected["host"] = "www.google.com";
37244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  expected["url"] = "/";
37254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  expected["scheme"] = "http";
37264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  expected["version"] = "HTTP/1.1";
37274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  expected["method"] = "GET";
37284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  expected["user-agent"] = "Chrome";
37294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ(expected.size(), headers->size());
37304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  spdy::SpdyHeaderBlock::const_iterator end = expected.end();
37314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  for (spdy::SpdyHeaderBlock::const_iterator it = expected.begin();
37324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      it != end;
37334a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      ++it) {
37344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    EXPECT_EQ(it->second, (*headers)[it->first]);
37354a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
3736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
3737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Since we buffer the IO from the stream to the renderer, this test verifies
3739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// that when we read out the maximum amount of data (e.g. we received 50 bytes
3740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// on the network, but issued a Read for only 5 of those bytes) that the data
3741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// flow still works correctly.
37423345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, BufferFull) {
3743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdyFramer framer;
3744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
3747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // 2 data frames in a single read.
3749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> data_frame_1(
3750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      framer.CreateDataFrame(1, "goodby", 6, spdy::DATA_FLAG_NONE));
3751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> data_frame_2(
3752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      framer.CreateDataFrame(1, "e worl", 6, spdy::DATA_FLAG_NONE));
3753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const spdy::SpdyFrame* data_frames[2] = {
3754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame_1.get(),
3755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame_2.get(),
3756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  char combined_data_frames[100];
3758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int combined_data_frames_len =
3759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CombineFrames(data_frames, arraysize(data_frames),
3760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    combined_data_frames, arraysize(combined_data_frames));
3761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> last_frame(
3762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      framer.CreateDataFrame(1, "d", 1, spdy::DATA_FLAG_FIN));
3763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
3765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
3766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
3767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, ERR_IO_PENDING),  // Force a pause
3768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, combined_data_frames, combined_data_frames_len),
3769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, ERR_IO_PENDING),  // Force a pause
3770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*last_frame),
3771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
3772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
3775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
3776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
3777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback callback;
3780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
37823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
3783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunPreTestSetup();
37843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
3785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
3786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
3787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
3788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
3790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.rv = callback.WaitForResult();
3791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(out.rv, OK);
3792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const HttpResponseInfo* response = trans->GetResponseInfo();
3794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->headers != NULL);
3795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->was_fetched_via_spdy);
3796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.status_line = response->headers->GetStatusLine();
3797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.response_info = *response;  // Make a copy so we can verify.
3798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Read Data
3800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback read_callback;
3801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string content;
3803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  do {
3804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Read small chunks at a time.
3805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const int kSmallReadSize = 3;
3806513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    rv = trans->Read(buf, kSmallReadSize, &read_callback);
3808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (rv == net::ERR_IO_PENDING) {
3809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      data->CompleteRead();
3810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      rv = read_callback.WaitForResult();
3811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
3812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (rv > 0) {
3813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      content.append(buf->data(), rv);
3814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else if (rv < 0) {
3815c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED();
3816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
3817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } while (rv > 0);
3818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.response_data.swap(content);
3820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // MockClientSocketFactory) are still alive.
3823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->RunAllPending();
3824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Verify that we consumed all test data.
3826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.VerifyDataConsumed();
3827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
3829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("goodbye world", out.response_data);
3831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
3832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Verify that basic buffering works; when multiple data frames arrive
3834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// at the same time, ensure that we don't notify a read completion for
3835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// each data frame individually.
38363345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, Buffering) {
3837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdyFramer framer;
3838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
3841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // 4 data frames in a single read.
3843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> data_frame(
3844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE));
3845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> data_frame_fin(
3846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_FIN));
3847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const spdy::SpdyFrame* data_frames[4] = {
3848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame.get(),
3849c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame.get(),
3850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame.get(),
3851c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame_fin.get()
3852c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3853c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  char combined_data_frames[100];
3854c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int combined_data_frames_len =
3855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CombineFrames(data_frames, arraysize(data_frames),
3856c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    combined_data_frames, arraysize(combined_data_frames));
3857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
3859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
3860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
3861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, ERR_IO_PENDING),  // Force a pause
3862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, combined_data_frames, combined_data_frames_len),
3863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
3864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
3867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
3868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
3869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
38713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
3872c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunPreTestSetup();
38733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
3874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
3875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback callback;
3877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
3878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
3879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
3881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.rv = callback.WaitForResult();
3882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(out.rv, OK);
3883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const HttpResponseInfo* response = trans->GetResponseInfo();
3885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->headers != NULL);
3886c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->was_fetched_via_spdy);
3887c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.status_line = response->headers->GetStatusLine();
3888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.response_info = *response;  // Make a copy so we can verify.
3889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3890c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Read Data
3891c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback read_callback;
3892c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3893c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string content;
3894c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int reads_completed = 0;
3895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  do {
3896c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Read small chunks at a time.
3897c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const int kSmallReadSize = 14;
3898513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3899c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    rv = trans->Read(buf, kSmallReadSize, &read_callback);
3900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (rv == net::ERR_IO_PENDING) {
3901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      data->CompleteRead();
3902c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      rv = read_callback.WaitForResult();
3903c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
3904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (rv > 0) {
3905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_EQ(kSmallReadSize, rv);
3906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      content.append(buf->data(), rv);
3907c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else if (rv < 0) {
3908c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      FAIL() << "Unexpected read error: " << rv;
3909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
3910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    reads_completed++;
3911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } while (rv > 0);
3912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(3, reads_completed);  // Reads are: 14 bytes, 14 bytes, 0 bytes.
3914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.response_data.swap(content);
3916c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3917c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // MockClientSocketFactory) are still alive.
3919c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->RunAllPending();
3920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Verify that we consumed all test data.
3922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.VerifyDataConsumed();
3923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
3925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3927c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
3928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Verify the case where we buffer data but read it after it has been buffered.
39303345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, BufferedAll) {
3931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdyFramer framer;
3932c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
3935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // 5 data frames in a single read.
3937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> syn_reply(
3938c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ConstructSpdyGetSynReply(NULL, 0, 1));
3939c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  syn_reply->set_flags(spdy::CONTROL_FLAG_NONE);  // turn off FIN bit
3940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> data_frame(
3941c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE));
3942c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> data_frame_fin(
3943c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_FIN));
3944c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const spdy::SpdyFrame* frames[5] = {
3945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    syn_reply.get(),
3946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame.get(),
3947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame.get(),
3948c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame.get(),
3949c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame_fin.get()
3950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3951c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  char combined_frames[200];
3952c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int combined_frames_len =
3953c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CombineFrames(frames, arraysize(frames),
3954c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    combined_frames, arraysize(combined_frames));
3955c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
3957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, combined_frames, combined_frames_len),
3958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
3959c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3960c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3961c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
3962c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
3963c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
3964c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3965c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
39663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
3967c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunPreTestSetup();
39683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
3969c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
3970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback callback;
3972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
3973c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
3974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3975c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
3976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.rv = callback.WaitForResult();
3977c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(out.rv, OK);
3978c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3979c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const HttpResponseInfo* response = trans->GetResponseInfo();
3980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->headers != NULL);
3981c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->was_fetched_via_spdy);
3982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.status_line = response->headers->GetStatusLine();
3983c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.response_info = *response;  // Make a copy so we can verify.
3984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Read Data
3986c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback read_callback;
3987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string content;
3989c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int reads_completed = 0;
3990c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  do {
3991c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Read small chunks at a time.
3992c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const int kSmallReadSize = 14;
3993513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    rv = trans->Read(buf, kSmallReadSize, &read_callback);
3995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (rv > 0) {
3996c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_EQ(kSmallReadSize, rv);
3997c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      content.append(buf->data(), rv);
3998c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else if (rv < 0) {
3999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      FAIL() << "Unexpected read error: " << rv;
4000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
4001c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    reads_completed++;
4002c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } while (rv > 0);
4003c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(3, reads_completed);
4005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.response_data.swap(content);
4007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4008c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4009c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // MockClientSocketFactory) are still alive.
4010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->RunAllPending();
4011c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4012c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Verify that we consumed all test data.
4013c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.VerifyDataConsumed();
4014c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4015c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
4016c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4017c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("messagemessagemessagemessage", out.response_data);
4018c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
4019c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4020c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Verify the case where we buffer data and close the connection.
40213345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
4022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdyFramer framer;
4023c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4024c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4025c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
4026c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4027c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // All data frames in a single read.
4028c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // NOTE: We don't FIN the stream.
4029c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> data_frame(
4030c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE));
4031c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const spdy::SpdyFrame* data_frames[4] = {
4032c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame.get(),
4033c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame.get(),
4034c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame.get(),
4035c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_frame.get()
4036c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
4037c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  char combined_data_frames[100];
4038c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int combined_data_frames_len =
4039c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CombineFrames(data_frames, arraysize(data_frames),
4040c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    combined_data_frames, arraysize(combined_data_frames));
4041c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4042c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
4043c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
4044c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, ERR_IO_PENDING),  // Force a wait
4045c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, combined_data_frames, combined_data_frames_len),
4046c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
4047c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
4048c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4049c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
4050c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
4051c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
4052c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4053c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
40543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
4055c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunPreTestSetup();
40563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
4057c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
4058c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4059c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback callback;
4060c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4061c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
4062c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
4063c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4064c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
4065c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.rv = callback.WaitForResult();
4066c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(out.rv, OK);
4067c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4068c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const HttpResponseInfo* response = trans->GetResponseInfo();
4069c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->headers != NULL);
4070c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->was_fetched_via_spdy);
4071c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.status_line = response->headers->GetStatusLine();
4072c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.response_info = *response;  // Make a copy so we can verify.
4073c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4074c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Read Data
4075c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback read_callback;
4076c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4077c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string content;
4078c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int reads_completed = 0;
4079c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  do {
4080c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Read small chunks at a time.
4081c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const int kSmallReadSize = 14;
4082513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4083c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    rv = trans->Read(buf, kSmallReadSize, &read_callback);
4084c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (rv == net::ERR_IO_PENDING) {
4085c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      data->CompleteRead();
4086c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      rv = read_callback.WaitForResult();
4087c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
4088c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (rv > 0) {
4089c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      content.append(buf->data(), rv);
4090c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else if (rv < 0) {
4091c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // This test intentionally closes the connection, and will get an error.
4092c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
4093c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
4094c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
4095c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    reads_completed++;
4096c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } while (rv > 0);
4097c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4098c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(0, reads_completed);
4099c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.response_data.swap(content);
4101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // MockClientSocketFactory) are still alive.
4104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->RunAllPending();
4105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Verify that we consumed all test data.
4107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.VerifyDataConsumed();
4108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
4109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Verify the case where we buffer data and cancel the transaction.
41113345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, BufferedCancelled) {
4112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdyFramer framer;
4113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
4116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // NOTE: We don't FIN the stream.
4118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> data_frame(
4119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE));
4120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
4123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
4124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, ERR_IO_PENDING),  // Force a wait
4125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*data_frame),
4126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
4127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
4128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
4130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
4131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
4132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
41343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
4135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunPreTestSetup();
41363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
4137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
4138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback callback;
4139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
4141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
4142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
4144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.rv = callback.WaitForResult();
4145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(out.rv, OK);
4146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const HttpResponseInfo* response = trans->GetResponseInfo();
4148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->headers != NULL);
4149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->was_fetched_via_spdy);
4150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.status_line = response->headers->GetStatusLine();
4151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.response_info = *response;  // Make a copy so we can verify.
4152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Read Data
4154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback read_callback;
4155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  do {
4157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const int kReadSize = 256;
4158513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kReadSize));
4159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    rv = trans->Read(buf, kReadSize, &read_callback);
4160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (rv == net::ERR_IO_PENDING) {
4161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Complete the read now, which causes buffering to start.
4162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      data->CompleteRead();
4163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Destroy the transaction, causing the stream to get cancelled
4164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // and orphaning the buffered IO task.
4165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      helper.ResetTrans();
4166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
4167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
4168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We shouldn't get here in this test.
4169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    FAIL() << "Unexpected read: " << rv;
4170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } while (rv > 0);
4171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Flush the MessageLoop; this will cause the buffered IO task
4173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // to run for the final time.
4174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->RunAllPending();
4175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Verify that we consumed all test data.
4177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.VerifyDataConsumed();
4178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
4179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test that if the server requests persistence of settings, that we save
4181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the settings in the SpdySettingsStorage.
41823345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
4183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const SpdyHeaderInfo kSynReplyInfo = {
4184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SYN_REPLY,                              // Syn Reply
4185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    1,                                            // Stream ID
4186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0,                                            // Associated Stream ID
41873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    net::ConvertRequestPriorityToSpdyPriority(LOWEST),
41883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                  // Priority
4189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::CONTROL_FLAG_NONE,                      // Control Flags
4190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    false,                                        // Compressed
4191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::INVALID,                                // Status
4192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NULL,                                         // Data
4193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0,                                            // Data Length
4194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::DATA_FLAG_NONE                          // Data Flags
4195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
4196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const char* const kExtraHeaders[] = {
4197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "status",   "200",
4198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "version",  "HTTP/1.1"
4199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
4200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
42023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
42033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
4204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Verify that no settings exist initially.
42063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HostPortPair host_port_pair("www.google.com", helper.port());
4207dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4208dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(spdy_session_pool->spdy_settings().Get(host_port_pair).empty());
4209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Construct the request.
4211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
4213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Construct the reply.
4215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> reply(
4216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ConstructSpdyPacket(kSynReplyInfo,
4217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        kExtraHeaders,
4218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        arraysize(kExtraHeaders) / 2,
4219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        NULL,
4220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        0));
4221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  unsigned int kSampleId1 = 0x1;
4223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  unsigned int kSampleValue1 = 0x0a0a0a0a;
4224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  unsigned int kSampleId2 = 0x2;
4225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  unsigned int kSampleValue2 = 0x0b0b0b0b;
4226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  unsigned int kSampleId3 = 0xababab;
4227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  unsigned int kSampleValue3 = 0x0c0c0c0c;
4228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> settings_frame;
4229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
4230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Construct the SETTINGS frame.
4231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SpdySettings settings;
4232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SettingsFlagsAndId setting(0);
4233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // First add a persisted setting
4234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST);
4235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    setting.set_id(kSampleId1);
4236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    settings.push_back(std::make_pair(setting, kSampleValue1));
4237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Next add a non-persisted setting
4238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    setting.set_flags(0);
4239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    setting.set_id(kSampleId2);
4240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    settings.push_back(std::make_pair(setting, kSampleValue2));
4241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Next add another persisted setting
4242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST);
4243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    setting.set_id(kSampleId3);
4244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    settings.push_back(std::make_pair(setting, kSampleValue3));
4245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    settings_frame.reset(ConstructSpdySettings(settings));
4246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
4247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
4250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*reply),
4251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
4252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*settings_frame),
4253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
4254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
4255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
4257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
4258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
42593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
42603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunDefaultTest();
42613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
4262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
4263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
4264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("hello!", out.response_data);
4266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
4268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Verify we had two persisted settings.
4269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SpdySettings saved_settings =
4270dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        spdy_session_pool->spdy_settings().Get(host_port_pair);
4271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ASSERT_EQ(2u, saved_settings.size());
4272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Verify the first persisted setting.
4274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SpdySetting setting = saved_settings.front();
4275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    saved_settings.pop_front();
4276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags());
4277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(kSampleId1, setting.first.id());
4278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(kSampleValue1, setting.second);
4279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Verify the second persisted setting.
4281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    setting = saved_settings.front();
4282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    saved_settings.pop_front();
4283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags());
4284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(kSampleId3, setting.first.id());
4285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(kSampleValue3, setting.second);
4286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
4287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
4288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test that when there are settings saved that they are sent back to the
4290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// server upon session establishment.
42913345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, SettingsPlayback) {
4292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const SpdyHeaderInfo kSynReplyInfo = {
4293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SYN_REPLY,                              // Syn Reply
4294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    1,                                            // Stream ID
4295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0,                                            // Associated Stream ID
42963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    net::ConvertRequestPriorityToSpdyPriority(LOWEST),
42973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                  // Priority
4298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::CONTROL_FLAG_NONE,                      // Control Flags
4299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    false,                                        // Compressed
4300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::INVALID,                                // Status
4301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NULL,                                         // Data
4302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0,                                            // Data Length
4303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::DATA_FLAG_NONE                          // Data Flags
4304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
4305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const char* kExtraHeaders[] = {
4306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "status",   "200",
4307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "version",  "HTTP/1.1"
4308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
4309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
43113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
43123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
4313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Verify that no settings exist initially.
43153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HostPortPair host_port_pair("www.google.com", helper.port());
4316dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4317dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(spdy_session_pool->spdy_settings().Get(host_port_pair).empty());
4318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  unsigned int kSampleId1 = 0x1;
4320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  unsigned int kSampleValue1 = 0x0a0a0a0a;
4321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  unsigned int kSampleId2 = 0xababab;
4322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  unsigned int kSampleValue2 = 0x0c0c0c0c;
4323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Manually insert settings into the SpdySettingsStorage here.
4324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
4325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SpdySettings settings;
4326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SettingsFlagsAndId setting(0);
4327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // First add a persisted setting
4328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST);
4329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    setting.set_id(kSampleId1);
4330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    settings.push_back(std::make_pair(setting, kSampleValue1));
4331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Next add another persisted setting
4332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST);
4333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    setting.set_id(kSampleId2);
4334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    settings.push_back(std::make_pair(setting, kSampleValue2));
4335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4336dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    spdy_session_pool->mutable_spdy_settings()->Set(host_port_pair, settings);
4337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
4338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4339dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(2u, spdy_session_pool->spdy_settings().Get(host_port_pair).size());
4340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Construct the SETTINGS frame.
4342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const spdy::SpdySettings& settings =
4343dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      spdy_session_pool->spdy_settings().Get(host_port_pair);
4344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
4345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Construct the request.
4347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = {
4350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockWrite(*settings_frame),
4351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockWrite(*req),
4352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
4353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Construct the reply.
4355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> reply(
4356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ConstructSpdyPacket(kSynReplyInfo,
4357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        kExtraHeaders,
4358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        arraysize(kExtraHeaders) / 2,
4359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        NULL,
4360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        0));
4361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
4364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*reply),
4365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*body),
4366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0)  // EOF
4367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
4368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
4370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(2, reads, arraysize(reads),
4371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
43723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
43733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunDefaultTest();
43743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
4375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
4376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, out.rv);
4377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("hello!", out.response_data);
4379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
4381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Verify we had two persisted settings.
4382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SpdySettings saved_settings =
4383dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        spdy_session_pool->spdy_settings().Get(host_port_pair);
4384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ASSERT_EQ(2u, saved_settings.size());
4385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Verify the first persisted setting.
4387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SpdySetting setting = saved_settings.front();
4388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    saved_settings.pop_front();
4389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags());
4390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(kSampleId1, setting.first.id());
4391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(kSampleValue1, setting.second);
4392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Verify the second persisted setting.
4394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    setting = saved_settings.front();
4395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    saved_settings.pop_front();
4396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags());
4397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(kSampleId2, setting.first.id());
4398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(kSampleValue2, setting.second);
4399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
4400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
4401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
44023345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
4403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
4405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> go_away(ConstructSpdyGoAway());
4407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
4408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*go_away),
44093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0),  // EOF
4410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
4411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
4413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
4414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
4415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
44163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
44173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data);
4418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunToCompletion(data.get());
4419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out = helper.output();
44203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_ABORTED, out.rv);
4421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
4422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
44233345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) {
4424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
4426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
4429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
4430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(false, 0, 0)  // EOF
4431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
4432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<DelayedSocketData> data(
4434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
4435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
4436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BoundNetLog log;
4437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
44383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     log, GetParam());
4439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.RunPreTestSetup();
44403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
4441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
4442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback callback;
4444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TransactionHelperResult out;
4445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.rv = trans->Start(&CreateGetRequest(), &callback, log);
4446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(out.rv, ERR_IO_PENDING);
4448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.rv = callback.WaitForResult();
4449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(out.rv, OK);
4450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const HttpResponseInfo* response = trans->GetResponseInfo();
4452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->headers != NULL);
4453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(response->was_fetched_via_spdy);
4454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  out.rv = ReadTransaction(trans, &out.response_data);
4455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv);
4456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Verify that we consumed all test data.
4458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  helper.VerifyDataConsumed();
4459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
4460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
44613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Test to make sure we can correctly connect through a proxy.
44623345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, ProxyConnect) {
44633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
44643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
44653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.session_deps().reset(new SpdySessionDependencies(
44663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
4467513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  helper.SetSession(make_scoped_refptr(
4468513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
44693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
44703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans = helper.trans();
44713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
44723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
44733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                           "Host: www.google.com\r\n"
44743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                           "Proxy-Connection: keep-alive\r\n\r\n"};
44753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
44763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                           "Host: www.google.com\r\n"
44773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                           "Proxy-Connection: keep-alive\r\n\r\n"};
44783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
44793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
44803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
44813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
44823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
44833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes_SPDYNPN[] = {
44843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockWrite(false, kConnect443, arraysize(kConnect443) - 1, 0),
44853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req, 2),
44863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
44873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads_SPDYNPN[] = {
44883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(false, kHTTP200, arraysize(kHTTP200) - 1, 1),
44893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp, 3),
44903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body.get(), 4),
44913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0, 5),
44923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
44933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
44943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes_SPDYSSL[] = {
44953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockWrite(false, kConnect80, arraysize(kConnect80) - 1, 0),
44963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req, 2),
44973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
44983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads_SPDYSSL[] = {
44993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(false, kHTTP200, arraysize(kHTTP200) - 1, 1),
45003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp, 3),
45013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body.get(), 4),
45023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0, 5),
45033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
45043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
45053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes_SPDYNOSSL[] = {
45063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req, 0),
45073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
45083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
45093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads_SPDYNOSSL[] = {
45103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp, 1),
45113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body.get(), 2),
45123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0, 3),
45133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
45143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
45153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data;
45163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  switch(GetParam()) {
45173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case SPDYNOSSL:
45183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      data = new OrderedSocketData(reads_SPDYNOSSL,
45193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   arraysize(reads_SPDYNOSSL),
45203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   writes_SPDYNOSSL,
45213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   arraysize(writes_SPDYNOSSL));
45223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      break;
45233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case SPDYSSL:
45243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      data = new OrderedSocketData(reads_SPDYSSL, arraysize(reads_SPDYSSL),
45253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   writes_SPDYSSL, arraysize(writes_SPDYSSL));
45263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      break;
45273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case SPDYNPN:
45283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      data = new OrderedSocketData(reads_SPDYNPN, arraysize(reads_SPDYNPN),
45293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   writes_SPDYNPN, arraysize(writes_SPDYNPN));
45303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      break;
45313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    default:
45323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NOTREACHED();
45333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
45343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
45353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
45363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
45373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
45383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
45393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_IO_PENDING, rv);
45403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
45413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  rv = callback.WaitForResult();
45423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(0, rv);
45433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
45443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Verify the SYN_REPLY.
45453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response = *trans->GetResponseInfo();
45463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response.headers != NULL);
45473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
45483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
45493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string response_data;
45503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(OK, ReadTransaction(trans, &response_data));
45513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("hello!", response_data);
45523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.VerifyDataConsumed();
45533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
45543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
45553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Test to make sure we can correctly connect through a proxy to www.google.com,
45563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// if there already exists a direct spdy connection to www.google.com. See
45573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// http://crbug.com/49874
45583345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
45593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // When setting up the first transaction, we store the SpdySessionPool so that
45603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // we can use the same pool in the second transaction.
45613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
45623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     BoundNetLog(), GetParam());
45633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
45643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Use a proxy service which returns a proxy fallback list from DIRECT to
45653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // myproxy:70. For this test there will be no fallback, so it is equivalent
45663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // to simply DIRECT. The reason for appending the second proxy is to verify
45673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // that the session pool key used does is just "DIRECT".
45683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.session_deps().reset(new SpdySessionDependencies(
45693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
4570513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  helper.SetSession(make_scoped_refptr(
4571513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
45723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4573731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
45743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.RunPreTestSetup();
45753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
45763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Construct and send a simple GET request.
45773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
45783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes[] = {
45793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req, 1),
45803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
45813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
45823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
45833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
45843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
45853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp, 2),
45863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body, 3),
45873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING, 4),  // Force a pause
45883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 5)  // EOF
45893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
45903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data(
45913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new OrderedSocketData(reads, arraysize(reads),
45923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            writes, arraysize(writes)));
45933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper.AddData(data.get());
45943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans = helper.trans();
45953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
45963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
45973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TransactionHelperResult out;
45983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
45993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
46003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(out.rv, ERR_IO_PENDING);
46013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = callback.WaitForResult();
46023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(out.rv, OK);
46033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
46043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const HttpResponseInfo* response = trans->GetResponseInfo();
46053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response->headers != NULL);
46063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response->was_fetched_via_spdy);
46073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.rv = ReadTransaction(trans, &out.response_data);
46083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK, out.rv);
46093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  out.status_line = response->headers->GetStatusLine();
46103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
46113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("hello!", out.response_data);
46123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
46133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Check that the SpdySession is still in the SpdySessionPool.
46143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HostPortPair host_port_pair("www.google.com", helper.port());
46153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HostPortProxyPair session_pool_key_direct(
46163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      host_port_pair, ProxyServer::Direct());
46173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(spdy_session_pool->HasSession(session_pool_key_direct));
46183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HostPortProxyPair session_pool_key_proxy(
46193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      host_port_pair,
46203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP));
46213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_FALSE(spdy_session_pool->HasSession(session_pool_key_proxy));
46223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
46233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Set up data for the proxy connection.
46243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
46253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                           "Host: www.google.com\r\n"
46263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                           "Proxy-Connection: keep-alive\r\n\r\n"};
46273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
46283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                           "Host: www.google.com\r\n"
46293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                           "Proxy-Connection: keep-alive\r\n\r\n"};
46303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
46313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(
46323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      "http://www.google.com/foo.dat", false, 1, LOWEST));
46333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 1));
46343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(1, true));
46353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
46363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes_SPDYNPN[] = {
46373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockWrite(false, kConnect443, arraysize(kConnect443) - 1, 0),
46383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req2, 2),
46393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
46403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads_SPDYNPN[] = {
46413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(false, kHTTP200, arraysize(kHTTP200) - 1, 1),
46423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp2, 3),
46433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body2, 4),
46443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 5)  // EOF
46453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
46463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
46473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes_SPDYNOSSL[] = {
46483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req2, 0),
46493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
46503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads_SPDYNOSSL[] = {
46513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp2, 1),
46523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body2, 2),
46533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 3)  // EOF
46543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
46553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
46563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockWrite writes_SPDYSSL[] = {
46573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockWrite(false, kConnect80, arraysize(kConnect80) - 1, 0),
46583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockWrite(*req2, 2),
46593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
46603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads_SPDYSSL[] = {
46613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(false, kHTTP200, arraysize(kHTTP200) - 1, 1),
46623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp2, 3),
46633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body2, 4),
46643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0, 5),
46653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
46663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
46673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<OrderedSocketData> data_proxy;
46683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  switch(GetParam()) {
46693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case SPDYNPN:
46703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      data_proxy = new OrderedSocketData(reads_SPDYNPN,
46713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                         arraysize(reads_SPDYNPN),
46723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                         writes_SPDYNPN,
46733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                         arraysize(writes_SPDYNPN));
46743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      break;
46753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case SPDYNOSSL:
46763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      data_proxy = new OrderedSocketData(reads_SPDYNOSSL,
46773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                         arraysize(reads_SPDYNOSSL),
46783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                         writes_SPDYNOSSL,
46793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                         arraysize(writes_SPDYNOSSL));
46803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      break;
46813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case SPDYSSL:
46823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      data_proxy = new OrderedSocketData(reads_SPDYSSL,
46833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                         arraysize(reads_SPDYSSL),
46843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                         writes_SPDYSSL,
46853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                         arraysize(writes_SPDYSSL));
46863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      break;
46873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    default:
46883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NOTREACHED();
46893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
46903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
46913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Create another request to www.google.com, but this time through a proxy.
46923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpRequestInfo request_proxy;
46933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request_proxy.method = "GET";
46943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request_proxy.url = GURL("http://www.google.com/foo.dat");
46953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request_proxy.load_flags = 0;
4696731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  scoped_ptr<SpdySessionDependencies> ssd_proxy(new SpdySessionDependencies());
46973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Ensure that this transaction uses the same SpdySessionPool.
4698513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_refptr<HttpNetworkSession> session_proxy(
4699513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      SpdySessionDependencies::SpdyCreateSession(ssd_proxy.get()));
47003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NormalSpdyTransactionHelper helper_proxy(request_proxy,
47013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                           BoundNetLog(), GetParam());
4702731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  HttpNetworkSessionPeer session_peer(session_proxy);
4703731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  session_peer.SetProxyService(
4704731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
47053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper_proxy.session_deps().swap(ssd_proxy);
47063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper_proxy.SetSession(session_proxy);
47073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper_proxy.RunPreTestSetup();
47083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper_proxy.AddData(data_proxy.get());
47093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
47103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpNetworkTransaction* trans_proxy = helper_proxy.trans();
47113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback_proxy;
47123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = trans_proxy->Start(&request_proxy, &callback_proxy, BoundNetLog());
47133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_IO_PENDING, rv);
47143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  rv = callback_proxy.WaitForResult();
47153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(0, rv);
47163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
47173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo();
47183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(response_proxy.headers != NULL);
47193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", response_proxy.headers->GetStatusLine());
47203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
47213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string response_data;
47223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_EQ(OK, ReadTransaction(trans_proxy, &response_data));
47233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ("hello!", response_data);
47243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
47253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data->CompleteRead();
47263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  helper_proxy.VerifyDataConsumed();
47273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
47283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
47293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
47303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// on a new connection, if the connection was previously known to be good.
47313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// This can happen when a server reboots without saying goodbye, or when
47323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// we're behind a NAT that masked the RST.
47333345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
47343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
47353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
47363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads[] = {
47373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp),
47383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body),
47393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_IO_PENDING),
47403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, ERR_CONNECTION_RESET),
47413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
47423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
47433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  MockRead reads2[] = {
47443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*resp),
47453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CreateMockRead(*body),
47463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MockRead(true, 0, 0)  // EOF
47473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
47483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
47493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // This test has a couple of variants.
47503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  enum {
47513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Induce the RST while waiting for our transaction to send.
47523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    VARIANT_RST_DURING_SEND_COMPLETION,
47533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Induce the RST while waiting for our transaction to read.
47543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // In this case, the send completed - everything copied into the SNDBUF.
47553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    VARIANT_RST_DURING_READ_COMPLETION
47563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
47573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
47583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (int variant = VARIANT_RST_DURING_SEND_COMPLETION;
47593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       variant <= VARIANT_RST_DURING_READ_COMPLETION;
47603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       ++variant) {
47613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    scoped_refptr<DelayedSocketData> data1(
47623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        new DelayedSocketData(1, reads, arraysize(reads),
47633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                              NULL, 0));
47643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
47653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    scoped_refptr<DelayedSocketData> data2(
47663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        new DelayedSocketData(1, reads2, arraysize(reads2),
47673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                               NULL, 0));
47683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
47693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    NormalSpdyTransactionHelper helper(CreateGetRequest(),
47703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                       BoundNetLog(), GetParam());
47713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    helper.AddData(data1.get());
47723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    helper.AddData(data2.get());
47733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    helper.RunPreTestSetup();
47743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
47753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    for (int i = 0; i < 2; ++i) {
47763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      scoped_ptr<HttpNetworkTransaction> trans(
47773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          new HttpNetworkTransaction(helper.session()));
47783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
47793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      TestCompletionCallback callback;
47803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
47813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      EXPECT_EQ(ERR_IO_PENDING, rv);
47823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // On the second transaction, we trigger the RST.
47833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (i == 1) {
47843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        if (variant == VARIANT_RST_DURING_READ_COMPLETION) {
47853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          // Writes to the socket complete asynchronously on SPDY by running
47863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          // through the message loop.  Complete the write here.
47873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          MessageLoop::current()->RunAllPending();
47883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        }
47893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
47903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        // Now schedule the ERR_CONNECTION_RESET.
47913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        EXPECT_EQ(3u, data1->read_index());
47923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        data1->CompleteRead();
47933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        EXPECT_EQ(4u, data1->read_index());
47943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      }
47953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      rv = callback.WaitForResult();
47963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      EXPECT_EQ(OK, rv);
47973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
47983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      const HttpResponseInfo* response = trans->GetResponseInfo();
47993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ASSERT_TRUE(response != NULL);
48003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      EXPECT_TRUE(response->headers != NULL);
48013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      EXPECT_TRUE(response->was_fetched_via_spdy);
48023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      std::string response_data;
48033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      rv = ReadTransaction(trans.get(), &response_data);
48043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      EXPECT_EQ(OK, rv);
48053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
48063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      EXPECT_EQ("hello!", response_data);
48073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
48083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
48093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    helper.VerifyDataConsumed();
48103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
48113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
4812731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
4813731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Test that turning SPDY on and off works properly.
4814731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickTEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) {
4815731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  net::HttpStreamFactory::set_spdy_enabled(true);
4816731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4817731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  MockWrite spdy_writes[] = { CreateMockWrite(*req) };
4818731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
4819731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4820731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4821731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  MockRead spdy_reads[] = {
4822731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    CreateMockRead(*resp),
4823731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    CreateMockRead(*body),
4824731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    MockRead(true, 0, 0)  // EOF
4825731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  };
4826731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
4827731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  scoped_refptr<DelayedSocketData> data(
4828513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      new DelayedSocketData(1,
4829513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                            spdy_reads, arraysize(spdy_reads),
4830731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                            spdy_writes, arraysize(spdy_writes)));
4831731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  NormalSpdyTransactionHelper helper(CreateGetRequest(),
4832731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                     BoundNetLog(), GetParam());
4833731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  helper.RunToCompletion(data.get());
4834731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  TransactionHelperResult out = helper.output();
4835731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EXPECT_EQ(OK, out.rv);
4836731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4837731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EXPECT_EQ("hello!", out.response_data);
4838731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
4839731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  net::HttpStreamFactory::set_spdy_enabled(false);
4840731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  MockRead http_reads[] = {
4841731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4842731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    MockRead("hello from http"),
4843731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    MockRead(false, OK),
4844731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  };
4845731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  scoped_refptr<DelayedSocketData> data2(
4846731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      new DelayedSocketData(1, http_reads, arraysize(http_reads),
4847731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                            NULL, 0));
4848731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  NormalSpdyTransactionHelper helper2(CreateGetRequest(),
4849731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                     BoundNetLog(), GetParam());
4850731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  helper2.SetSpdyDisabled();
4851731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  helper2.RunToCompletion(data2.get());
4852731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  TransactionHelperResult out2 = helper2.output();
4853731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EXPECT_EQ(OK, out2.rv);
4854731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EXPECT_EQ("HTTP/1.1 200 OK", out2.status_line);
4855731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EXPECT_EQ("hello from http", out2.response_data);
4856731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
4857731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  net::HttpStreamFactory::set_spdy_enabled(true);
4858731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
4859513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
4860513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Tests that Basic authentication works over SPDY
4861513209b27ff55e2841eac0e4120199c23acce758Ben MurdochTEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) {
4862513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  net::HttpStreamFactory::set_spdy_enabled(true);
4863513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
4864513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // The first request will be a bare GET, the second request will be a
4865513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // GET with an Authorization header.
4866513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_ptr<spdy::SpdyFrame> req_get(
4867513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4868513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const char* const kExtraAuthorizationHeaders[] = {
4869513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    "authorization",
4870513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    "Basic Zm9vOmJhcg==",
4871513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  };
4872513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_ptr<spdy::SpdyFrame> req_get_authorization(
4873513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      ConstructSpdyGet(
4874201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch          kExtraAuthorizationHeaders,
4875201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch          arraysize(kExtraAuthorizationHeaders) / 2,
4876513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          false, 3, LOWEST));
4877513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  MockWrite spdy_writes[] = {
4878513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    CreateMockWrite(*req_get, 1),
4879513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    CreateMockWrite(*req_get_authorization, 4),
4880513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  };
4881513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
4882513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // The first response is a 401 authentication challenge, and the second
4883513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // response will be a 200 response since the second request includes a valid
4884513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Authorization header.
4885513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const char* const kExtraAuthenticationHeaders[] = {
4886513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    "WWW-Authenticate",
4887513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    "Basic realm=\"MyRealm\""
4888513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  };
4889513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_ptr<spdy::SpdyFrame> resp_authentication(
4890513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      ConstructSpdySynReplyError(
4891513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          "401 Authentication Required",
4892201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch          kExtraAuthenticationHeaders,
4893201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch          arraysize(kExtraAuthenticationHeaders) / 2,
4894513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          1));
4895513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_ptr<spdy::SpdyFrame> body_authentication(
4896513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      ConstructSpdyBodyFrame(1, true));
4897513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_ptr<spdy::SpdyFrame> resp_data(ConstructSpdyGetSynReply(NULL, 0, 3));
4898513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_ptr<spdy::SpdyFrame> body_data(ConstructSpdyBodyFrame(3, true));
4899513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  MockRead spdy_reads[] = {
4900513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    CreateMockRead(*resp_authentication, 2),
4901513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    CreateMockRead(*body_authentication, 3),
4902513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    CreateMockRead(*resp_data, 5),
4903513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    CreateMockRead(*body_data, 6),
4904513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    MockRead(true, 0, 7),
4905513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  };
4906513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
4907513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_refptr<OrderedSocketData> data(
4908513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      new OrderedSocketData(spdy_reads, arraysize(spdy_reads),
4909513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                            spdy_writes, arraysize(spdy_writes)));
4910513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  HttpRequestInfo request(CreateGetRequest());
4911513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  BoundNetLog net_log;
4912513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  NormalSpdyTransactionHelper helper(request, net_log, GetParam());
4913513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
4914513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  helper.RunPreTestSetup();
4915513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  helper.AddData(data.get());
4916513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  HttpNetworkTransaction* trans = helper.trans();
4917513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  TestCompletionCallback callback_start;
4918513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const int rv_start = trans->Start(&request, &callback_start, net_log);
4919513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv_start);
4920513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const int rv_start_complete = callback_start.WaitForResult();
4921513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_EQ(OK, rv_start_complete);
4922513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
4923513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Make sure the response has an auth challenge.
4924513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const HttpResponseInfo* const response_start = trans->GetResponseInfo();
4925513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  ASSERT_TRUE(response_start != NULL);
4926513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  ASSERT_TRUE(response_start->headers != NULL);
4927513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_EQ(401, response_start->headers->response_code());
4928513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_TRUE(response_start->was_fetched_via_spdy);
4929513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  ASSERT_TRUE(response_start->auth_challenge.get() != NULL);
4930513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_FALSE(response_start->auth_challenge->is_proxy);
4931513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_EQ(L"basic", response_start->auth_challenge->scheme);
4932513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_EQ(L"MyRealm", response_start->auth_challenge->realm);
4933513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
4934513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Restart with a username/password.
4935513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const string16 kFoo(ASCIIToUTF16("foo"));
4936513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const string16 kBar(ASCIIToUTF16("bar"));
4937513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  TestCompletionCallback callback_restart;
4938513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const int rv_restart = trans->RestartWithAuth(kFoo, kBar, &callback_restart);
4939513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv_restart);
4940513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const int rv_restart_complete = callback_restart.WaitForResult();
4941513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_EQ(OK, rv_restart_complete);
4942513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // TODO(cbentzel): This is actually the same response object as before, but
4943513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // data has changed.
4944513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
4945513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  ASSERT_TRUE(response_restart != NULL);
4946513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  ASSERT_TRUE(response_restart->headers != NULL);
4947513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_EQ(200, response_restart->headers->response_code());
4948513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
4949513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
4950513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
4951201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushWithHeaders) {
4952201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const unsigned char kPushBodyFrame[] = {
4953201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    0x00, 0x00, 0x00, 0x02,                                      // header, ID
4954201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    0x01, 0x00, 0x00, 0x06,                                      // FIN, length
4955201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed"
4956201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
4957201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
4958201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4959201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
4960201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_body(ConstructSpdyBodyFrame(1, true));
4961201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MockWrite writes[] = {
4962201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockWrite(*stream1_syn, 1),
4963201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
4964201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
4965201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kInitialHeaders[] = {
4966201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "url",
4967201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "http://www.google.com/foo.dat",
4968201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
4969201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kLateHeaders[] = {
4970201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "hello",
4971201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "bye",
4972201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "status",
4973201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "200",
4974201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "version",
4975201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "HTTP/1.1"
4976201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
4977201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
4978201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    stream2_syn(ConstructSpdyControlFrame(kInitialHeaders,
4979201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                          arraysize(kInitialHeaders) / 2,
4980201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                          false,
4981201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                          2,
4982201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                          LOWEST,
4983201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                          spdy::SYN_STREAM,
4984201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                          spdy::CONTROL_FLAG_NONE,
4985201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                          NULL,
4986201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                          0,
4987201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                          1));
4988201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
4989201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_headers(ConstructSpdyControlFrame(kLateHeaders,
4990201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                arraysize(kLateHeaders) / 2,
4991201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                false,
4992201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                2,
4993201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                LOWEST,
4994201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                spdy::HEADERS,
4995201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                spdy::CONTROL_FLAG_NONE,
4996201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                NULL,
4997201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                0,
4998201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                0));
4999201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5000201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5001201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
5002201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MockRead reads[] = {
5003201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_reply, 2),
5004201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream2_syn, 3),
5005201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream2_headers, 4),
5006201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_body, 5, false),
5007201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame),
5008201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch             arraysize(kPushBodyFrame), 6),
5009201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    MockRead(true, ERR_IO_PENDING, 7),  // Force a pause
5010201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5011201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5012201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  HttpResponseInfo response;
5013201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  HttpResponseInfo response2;
5014201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::string expected_push_result("pushed");
5015201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_refptr<OrderedSocketData> data(new OrderedSocketData(
5016201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      reads,
5017201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(reads),
5018201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      writes,
5019201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(writes)));
5020201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  RunServerPushTest(data.get(),
5021201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    &response,
5022201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    &response2,
5023201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    expected_push_result);
5024201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5025201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verify the SYN_REPLY.
5026201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(response.headers != NULL);
5027201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5028201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5029201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verify the pushed stream.
5030201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(response2.headers != NULL);
5031201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5032201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
5033201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5034201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
5035201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // We push a stream and attempt to claim it before the headers come down.
5036201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const unsigned char kPushBodyFrame[] = {
5037201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    0x00, 0x00, 0x00, 0x02,                                      // header, ID
5038201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    0x01, 0x00, 0x00, 0x06,                                      // FIN, length
5039201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed"
5040201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5041201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5042201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5043201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5044201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_body(ConstructSpdyBodyFrame(1, true));
5045201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MockWrite writes[] = {
5046201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockWrite(*stream1_syn, 0, false),
5047201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5048201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5049201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kInitialHeaders[] = {
5050201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "url",
5051201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "http://www.google.com/foo.dat",
5052201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5053201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kLateHeaders[] = {
5054201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "hello",
5055201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "bye",
5056201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "status",
5057201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "200",
5058201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "version",
5059201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "HTTP/1.1"
5060201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5061201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5062201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_syn(ConstructSpdyControlFrame(kInitialHeaders,
5063201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            arraysize(kInitialHeaders) / 2,
5064201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            false,
5065201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            2,
5066201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            LOWEST,
5067201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            spdy::SYN_STREAM,
5068201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            spdy::CONTROL_FLAG_NONE,
5069201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            NULL,
5070201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            0,
5071201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            1));
5072201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5073201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_headers(ConstructSpdyControlFrame(kLateHeaders,
5074201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                arraysize(kLateHeaders) / 2,
5075201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                false,
5076201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                2,
5077201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                LOWEST,
5078201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                spdy::HEADERS,
5079201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                spdy::CONTROL_FLAG_NONE,
5080201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                NULL,
5081201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                0,
5082201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                0));
5083201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5084201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5085201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
5086201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MockRead reads[] = {
5087201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_reply, 1),
5088201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream2_syn, 2),
5089201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_body, 3),
5090201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream2_headers, 4),
5091201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame),
5092201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch             arraysize(kPushBodyFrame), 5),
5093201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    MockRead(true, 0, 5),  // EOF
5094201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5095201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5096201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  HttpResponseInfo response;
5097201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  HttpResponseInfo response2;
5098201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::string expected_push_result("pushed");
5099201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_refptr<DeterministicSocketData> data(new DeterministicSocketData(
5100201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      reads,
5101201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(reads),
5102201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      writes,
5103201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(writes)));
5104201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5105201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
5106201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                     BoundNetLog(), GetParam());
5107201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  helper.SetDeterministic();
5108201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  helper.AddDeterministicData(static_cast<DeterministicSocketData*>(data));
5109201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  helper.RunPreTestSetup();
5110201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5111201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  HttpNetworkTransaction* trans = helper.trans();
5112201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5113201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5114201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // and the body of the primary stream, but before we've received the HEADERS
5115201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // for the pushed stream.
5116201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  data->SetStop(3);
5117201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5118201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Start the transaction.
5119201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  TestCompletionCallback callback;
5120201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
5121201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
5122201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  data->Run();
5123201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  rv = callback.WaitForResult();
5124201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(0, rv);
5125201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5126201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Request the pushed path.  At this point, we've received the push, but the
5127201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // headers are not yet complete.
5128201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<HttpNetworkTransaction> trans2(
5129201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      new HttpNetworkTransaction(helper.session()));
5130201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  rv = trans2->Start(&CreateGetPushRequest(), &callback, BoundNetLog());
5131201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
5132201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  data->RunFor(3);
5133201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MessageLoop::current()->RunAllPending();
5134201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5135201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Read the server push body.
5136201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::string result2;
5137201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  ReadResult(trans2.get(), data.get(), &result2);
5138201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Read the response body.
5139201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::string result;
5140201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  ReadResult(trans, data, &result);
5141201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5142201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verify that we consumed all test data.
5143201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(data->at_read_eof());
5144201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(data->at_write_eof());
5145201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5146201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verify that the received push data is same as the expected push data.
5147201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(result2.compare(expected_push_result), 0)
5148201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      << "Received data: "
5149201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      << result2
5150201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      << "||||| Expected data: "
5151201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      << expected_push_result;
5152201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5153201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verify the SYN_REPLY.
5154201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Copy the response info, because trans goes away.
5155201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  response = *trans->GetResponseInfo();
5156201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  response2 = *trans2->GetResponseInfo();
5157201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5158201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  VerifyStreamsClosed(helper);
5159201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5160201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verify the SYN_REPLY.
5161201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(response.headers != NULL);
5162201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5163201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5164201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verify the pushed stream.
5165201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(response2.headers != NULL);
5166201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5167201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
5168201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5169201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) {
5170201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // We push a stream and attempt to claim it before the headers come down.
5171201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const unsigned char kPushBodyFrame[] = {
5172201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    0x00, 0x00, 0x00, 0x02,                                      // header, ID
5173201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    0x01, 0x00, 0x00, 0x06,                                      // FIN, length
5174201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed"
5175201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5176201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5177201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5178201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5179201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_body(ConstructSpdyBodyFrame(1, true));
5180201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MockWrite writes[] = {
5181201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockWrite(*stream1_syn, 0, false),
5182201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5183201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5184201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kInitialHeaders[] = {
5185201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "url",
5186201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "http://www.google.com/foo.dat",
5187201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5188201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kMiddleHeaders[] = {
5189201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "hello",
5190201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "bye",
5191201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5192201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kLateHeaders[] = {
5193201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "status",
5194201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "200",
5195201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "version",
5196201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "HTTP/1.1"
5197201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5198201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5199201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_syn(ConstructSpdyControlFrame(kInitialHeaders,
5200201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            arraysize(kInitialHeaders) / 2,
5201201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            false,
5202201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            2,
5203201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            LOWEST,
5204201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            spdy::SYN_STREAM,
5205201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            spdy::CONTROL_FLAG_NONE,
5206201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            NULL,
5207201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            0,
5208201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                            1));
5209201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5210201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_headers1(ConstructSpdyControlFrame(kMiddleHeaders,
5211201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 arraysize(kMiddleHeaders) / 2,
5212201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 false,
5213201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 2,
5214201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 LOWEST,
5215201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 spdy::HEADERS,
5216201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 spdy::CONTROL_FLAG_NONE,
5217201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 NULL,
5218201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 0,
5219201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 0));
5220201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5221201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream2_headers2(ConstructSpdyControlFrame(kLateHeaders,
5222201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 arraysize(kLateHeaders) / 2,
5223201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 false,
5224201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 2,
5225201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 LOWEST,
5226201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 spdy::HEADERS,
5227201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 spdy::CONTROL_FLAG_NONE,
5228201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 NULL,
5229201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 0,
5230201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                 0));
5231201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5232201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5233201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
5234201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MockRead reads[] = {
5235201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_reply, 1),
5236201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream2_syn, 2),
5237201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_body, 3),
5238201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream2_headers1, 4),
5239201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream2_headers2, 5),
5240201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame),
5241201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch             arraysize(kPushBodyFrame), 6),
5242201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    MockRead(true, 0, 6),  // EOF
5243201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5244201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5245201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  HttpResponseInfo response;
5246201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  HttpResponseInfo response2;
5247201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::string expected_push_result("pushed");
5248201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_refptr<DeterministicSocketData> data(new DeterministicSocketData(
5249201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      reads,
5250201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(reads),
5251201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      writes,
5252201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      arraysize(writes)));
5253201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5254201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
5255201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                     BoundNetLog(), GetParam());
5256201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  helper.SetDeterministic();
5257201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  helper.AddDeterministicData(static_cast<DeterministicSocketData*>(data));
5258201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  helper.RunPreTestSetup();
5259201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5260201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  HttpNetworkTransaction* trans = helper.trans();
5261201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5262201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5263201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // the first HEADERS frame, and the body of the primary stream, but before
5264201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // we've received the final HEADERS for the pushed stream.
5265201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  data->SetStop(4);
5266201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5267201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Start the transaction.
5268201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  TestCompletionCallback callback;
5269201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
5270201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
5271201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  data->Run();
5272201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  rv = callback.WaitForResult();
5273201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(0, rv);
5274201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5275201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Request the pushed path.  At this point, we've received the push, but the
5276201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // headers are not yet complete.
5277201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<HttpNetworkTransaction> trans2(
5278201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      new HttpNetworkTransaction(helper.session()));
5279201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  rv = trans2->Start(&CreateGetPushRequest(), &callback, BoundNetLog());
5280201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
5281201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  data->RunFor(3);
5282201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MessageLoop::current()->RunAllPending();
5283201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5284201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Read the server push body.
5285201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::string result2;
5286201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  ReadResult(trans2.get(), data, &result2);
5287201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Read the response body.
5288201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::string result;
5289201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  ReadResult(trans, data, &result);
5290201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5291201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verify that we consumed all test data.
5292201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(data->at_read_eof());
5293201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(data->at_write_eof());
5294201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5295201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verify that the received push data is same as the expected push data.
5296201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(result2.compare(expected_push_result), 0)
5297201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      << "Received data: "
5298201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      << result2
5299201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      << "||||| Expected data: "
5300201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      << expected_push_result;
5301201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5302201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verify the SYN_REPLY.
5303201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Copy the response info, because trans goes away.
5304201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  response = *trans->GetResponseInfo();
5305201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  response2 = *trans2->GetResponseInfo();
5306201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5307201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  VerifyStreamsClosed(helper);
5308201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5309201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verify the SYN_REPLY.
5310201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(response.headers != NULL);
5311201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5312201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5313201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verify the pushed stream.
5314201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(response2.headers != NULL);
5315201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5316201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5317201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Verify we got all the headers
5318201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(response2.headers->HasHeaderValue(
5319201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      "url",
5320201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      "http://www.google.com/foo.dat"));
5321201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye"));
5322201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200"));
5323201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(response2.headers->HasHeaderValue("version", "HTTP/1.1"));
5324201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
5325201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5326201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochTEST_P(SpdyNetworkTransactionTest, SynReplyWithHeaders) {
5327201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5328201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
5329201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5330201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kInitialHeaders[] = {
5331201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "status",
5332201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "200 OK",
5333201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "version",
5334201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "HTTP/1.1"
5335201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5336201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kLateHeaders[] = {
5337201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "hello",
5338201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "bye",
5339201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5340201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5341201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_reply(ConstructSpdyControlFrame(kInitialHeaders,
5342201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              arraysize(kInitialHeaders) / 2,
5343201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              false,
5344201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              1,
5345201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              LOWEST,
5346201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              spdy::SYN_REPLY,
5347201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              spdy::CONTROL_FLAG_NONE,
5348201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              NULL,
5349201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              0,
5350201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              0));
5351201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5352201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_headers(ConstructSpdyControlFrame(kLateHeaders,
5353201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                arraysize(kLateHeaders) / 2,
5354201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                false,
5355201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                1,
5356201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                LOWEST,
5357201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                spdy::HEADERS,
5358201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                spdy::CONTROL_FLAG_NONE,
5359201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                NULL,
5360201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                0,
5361201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                0));
5362201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame> stream1_body(ConstructSpdyBodyFrame(1, true));
5363201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MockRead reads[] = {
5364201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_reply),
5365201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_headers),
5366201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_body),
5367201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    MockRead(true, 0, 0)  // EOF
5368201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5369201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5370201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_refptr<DelayedSocketData> data(
5371201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
5372201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                            writes, arraysize(writes)));
5373201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
5374201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                     BoundNetLog(), GetParam());
5375201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  helper.RunToCompletion(data.get());
5376201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  TransactionHelperResult out = helper.output();
5377201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(OK, out.rv);
5378201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
5379201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ("hello!", out.response_data);
5380201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
5381201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5382201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochTEST_P(SpdyNetworkTransactionTest, SynReplyWithLateHeaders) {
5383201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5384201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
5385201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5386201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kInitialHeaders[] = {
5387201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "status",
5388201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "200 OK",
5389201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "version",
5390201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "HTTP/1.1"
5391201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5392201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kLateHeaders[] = {
5393201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "hello",
5394201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "bye",
5395201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5396201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5397201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_reply(ConstructSpdyControlFrame(kInitialHeaders,
5398201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              arraysize(kInitialHeaders) / 2,
5399201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              false,
5400201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              1,
5401201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              LOWEST,
5402201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              spdy::SYN_REPLY,
5403201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              spdy::CONTROL_FLAG_NONE,
5404201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              NULL,
5405201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              0,
5406201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              0));
5407201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5408201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_headers(ConstructSpdyControlFrame(kLateHeaders,
5409201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                arraysize(kLateHeaders) / 2,
5410201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                false,
5411201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                1,
5412201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                LOWEST,
5413201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                spdy::HEADERS,
5414201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                spdy::CONTROL_FLAG_NONE,
5415201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                NULL,
5416201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                0,
5417201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                0));
5418201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame> stream1_body(ConstructSpdyBodyFrame(1, false));
5419201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame> stream1_body2(ConstructSpdyBodyFrame(1, true));
5420201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MockRead reads[] = {
5421201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_reply),
5422201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_body),
5423201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_headers),
5424201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_body2),
5425201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    MockRead(true, 0, 0)  // EOF
5426201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5427201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5428201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_refptr<DelayedSocketData> data(
5429201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
5430201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                            writes, arraysize(writes)));
5431201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
5432201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                     BoundNetLog(), GetParam());
5433201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  helper.RunToCompletion(data.get());
5434201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  TransactionHelperResult out = helper.output();
5435201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(OK, out.rv);
5436201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
5437201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ("hello!hello!", out.response_data);
5438201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
5439201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5440201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochTEST_P(SpdyNetworkTransactionTest, SynReplyWithDuplicateLateHeaders) {
5441201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5442201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
5443201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5444201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kInitialHeaders[] = {
5445201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "status",
5446201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "200 OK",
5447201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "version",
5448201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "HTTP/1.1"
5449201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5450201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kLateHeaders[] = {
5451201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "status",
5452201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "500 Server Error",
5453201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5454201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5455201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_reply(ConstructSpdyControlFrame(kInitialHeaders,
5456201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              arraysize(kInitialHeaders) / 2,
5457201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              false,
5458201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              1,
5459201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              LOWEST,
5460201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              spdy::SYN_REPLY,
5461201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              spdy::CONTROL_FLAG_NONE,
5462201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              NULL,
5463201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              0,
5464201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                              0));
5465201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame>
5466201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      stream1_headers(ConstructSpdyControlFrame(kLateHeaders,
5467201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                arraysize(kLateHeaders) / 2,
5468201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                false,
5469201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                1,
5470201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                LOWEST,
5471201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                spdy::HEADERS,
5472201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                spdy::CONTROL_FLAG_NONE,
5473201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                NULL,
5474201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                0,
5475201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                0));
5476201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame> stream1_body(ConstructSpdyBodyFrame(1, false));
5477201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_ptr<spdy::SpdyFrame> stream1_body2(ConstructSpdyBodyFrame(1, true));
5478201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  MockRead reads[] = {
5479201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_reply),
5480201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_body),
5481201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_headers),
5482201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CreateMockRead(*stream1_body2),
5483201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    MockRead(true, 0, 0)  // EOF
5484201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5485201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5486201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_refptr<DelayedSocketData> data(
5487201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      new DelayedSocketData(1, reads, arraysize(reads),
5488201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                            writes, arraysize(writes)));
5489201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(),
5490201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                     BoundNetLog(), GetParam());
5491201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  helper.RunToCompletion(data.get());
5492201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  TransactionHelperResult out = helper.output();
5493201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
5494201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
5495201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5496201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
5497201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // In this test we want to verify that we can't accidentally push content
5498201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // which can't be pushed by this content server.
5499201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // This test assumes that:
5500201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  //   - if we're requesting http://www.foo.com/barbaz
5501201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  //   - the browser has made a connection to "www.foo.com".
5502201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5503201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // A list of the URL to fetch, followed by the URL being pushed.
5504201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const char* const kTestCases[] = {
5505201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "http://www.google.com/foo.html",
5506201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "http://www.google.com:81/foo.js",     // Bad port
5507201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5508201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "http://www.google.com/foo.html",
5509201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "https://www.google.com/foo.js",       // Bad protocol
5510201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5511201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "http://www.google.com/foo.html",
5512201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "ftp://www.google.com/foo.js",         // Invalid Protocol
5513201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5514201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "http://www.google.com/foo.html",
5515201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "http://blat.www.google.com/foo.js",   // Cross subdomain
5516201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5517201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "http://www.google.com/foo.html",
5518201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "http://www.foo.com/foo.js",           // Cross domain
5519201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5520201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5521201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5522201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static const unsigned char kPushBodyFrame[] = {
5523201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    0x00, 0x00, 0x00, 0x02,                                      // header, ID
5524201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    0x01, 0x00, 0x00, 0x06,                                      // FIN, length
5525201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed"
5526201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
5527201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5528201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  for (size_t index = 0; index < arraysize(kTestCases); index += 2) {
5529201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    const char* url_to_fetch = kTestCases[index];
5530201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    const char* url_to_push = kTestCases[index + 1];
5531201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5532201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    scoped_ptr<spdy::SpdyFrame>
5533201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        stream1_syn(ConstructSpdyGet(url_to_fetch, false, 1, LOWEST));
5534201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    scoped_ptr<spdy::SpdyFrame>
5535201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        stream1_body(ConstructSpdyBodyFrame(1, true));
5536201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    scoped_ptr<spdy::SpdyFrame> push_rst(
5537201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        ConstructSpdyRstStream(2, spdy::REFUSED_STREAM));
5538201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    MockWrite writes[] = {
5539201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      CreateMockWrite(*stream1_syn, 1),
5540201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      CreateMockWrite(*push_rst, 4),
5541201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    };
5542201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5543201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    scoped_ptr<spdy::SpdyFrame>
5544201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
5545201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    scoped_ptr<spdy::SpdyFrame>
5546201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        stream2_syn(ConstructSpdyPush(NULL,
5547201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                      0,
5548201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                      2,
5549201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                      1,
5550201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                      url_to_push));
5551201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    scoped_ptr<spdy::SpdyFrame> rst(
5552201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        ConstructSpdyRstStream(2, spdy::CANCEL));
5553201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5554201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    MockRead reads[] = {
5555201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      CreateMockRead(*stream1_reply, 2),
5556201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      CreateMockRead(*stream2_syn, 3),
5557201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      CreateMockRead(*stream1_body, 5, false),
5558201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame),
5559201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch               arraysize(kPushBodyFrame), 6),
5560201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      MockRead(true, ERR_IO_PENDING, 7),  // Force a pause
5561201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    };
5562201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5563201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    HttpResponseInfo response;
5564201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    scoped_refptr<OrderedSocketData> data(new OrderedSocketData(
5565201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        reads,
5566201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        arraysize(reads),
5567201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        writes,
5568201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        arraysize(writes)));
5569201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5570201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    HttpRequestInfo request;
5571201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    request.method = "GET";
5572201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    request.url = GURL(url_to_fetch);
5573201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    request.load_flags = 0;
5574201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    NormalSpdyTransactionHelper helper(request,
5575201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                       BoundNetLog(), GetParam());
5576201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    helper.RunPreTestSetup();
5577201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    helper.AddData(data);
5578201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5579201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    HttpNetworkTransaction* trans = helper.trans();
5580201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5581201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // Start the transaction with basic parameters.
5582201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    TestCompletionCallback callback;
5583201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5584201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    int rv = trans->Start(&request, &callback, BoundNetLog());
5585201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    EXPECT_EQ(ERR_IO_PENDING, rv);
5586201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    rv = callback.WaitForResult();
5587201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5588201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // Read the response body.
5589201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    std::string result;
5590201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    ReadResult(trans, data, &result);
5591201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5592201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // Verify that we consumed all test data.
5593201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    EXPECT_TRUE(data->at_read_eof());
5594201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    EXPECT_TRUE(data->at_write_eof());
5595201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5596201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // Verify the SYN_REPLY.
5597201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // Copy the response info, because trans goes away.
5598201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    response = *trans->GetResponseInfo();
5599201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5600201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    VerifyStreamsClosed(helper);
5601201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5602201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // Verify the SYN_REPLY.
5603201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    EXPECT_TRUE(response.headers != NULL);
5604201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5605201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
5606201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
5607201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace net
5609