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