blob: 7400756f5c5ad155bf89949a521a100b0f391d8f [file] [log] [blame]
[email protected]5af3c572010-07-20 14:16:271// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
[email protected]aea80602009-09-18 00:55:083// found in the LICENSE file.
4
[email protected]d8ef27b2010-08-06 17:34:395#include <string>
[email protected]a33cad2b62010-07-30 22:24:396#include <vector>
7
[email protected]018aabc2010-10-29 16:16:598#include "net/base/auth.h"
[email protected]9e743cd2010-03-16 07:03:539#include "net/base/net_log_unittest.h"
[email protected]87bfa3f2010-09-30 14:54:5610#include "net/http/http_network_session_peer.h"
[email protected]aea80602009-09-18 00:55:0811#include "net/http/http_transaction_unittest.h"
[email protected]9be804c82010-06-24 17:59:4612#include "net/spdy/spdy_http_stream.h"
[email protected]bdebd1b2010-08-09 20:18:0813#include "net/spdy/spdy_session.h"
[email protected]19ec8a72010-08-23 03:38:2314#include "net/spdy/spdy_session_pool.h"
[email protected]2ff8b312010-04-26 22:20:5415#include "net/spdy/spdy_test_util.h"
[email protected]e3ebba0f2010-08-05 17:59:5816#include "net/url_request/url_request_unittest.h"
[email protected]aea80602009-09-18 00:55:0817#include "testing/platform_test.h"
18
19//-----------------------------------------------------------------------------
20
[email protected]d1eda932009-11-04 01:03:1021namespace net {
[email protected]dae22c52010-07-30 02:16:3522
23// This is the expected list of advertised protocols from the browser's NPN
24// list.
25static const char kExpectedNPNString[] = "\x08http/1.1\x06spdy/2";
26
[email protected]9e9e842e2010-07-23 23:09:1527enum SpdyNetworkTransactionTestTypes {
28 SPDYNPN,
29 SPDYNOSSL,
[email protected]1f418ee2010-10-16 19:46:5630 SPDYSSL,
[email protected]9e9e842e2010-07-23 23:09:1531};
32class SpdyNetworkTransactionTest
33 : public ::testing::TestWithParam<SpdyNetworkTransactionTestTypes> {
[email protected]34437af82009-11-06 02:28:4934 protected:
[email protected]aea80602009-09-18 00:55:0835 virtual void SetUp() {
[email protected]94d78132010-01-22 00:53:0036 // By default, all tests turn off compression.
37 EnableCompression(false);
[email protected]d3cee19d2010-06-22 18:42:1838 google_get_request_initialized_ = false;
[email protected]310240592010-08-05 21:04:1939 google_post_request_initialized_ = false;
[email protected]aea80602009-09-18 00:55:0840 }
41
42 virtual void TearDown() {
43 // Empty the current queue.
44 MessageLoop::current()->RunAllPending();
[email protected]aea80602009-09-18 00:55:0845 }
46
[email protected]72552f02009-10-28 15:25:0147 struct TransactionHelperResult {
[email protected]aea80602009-09-18 00:55:0848 int rv;
49 std::string status_line;
50 std::string response_data;
[email protected]8b070372009-11-16 22:01:2551 HttpResponseInfo response_info;
[email protected]aea80602009-09-18 00:55:0852 };
53
[email protected]94d78132010-01-22 00:53:0054 void EnableCompression(bool enabled) {
[email protected]955fc2e72010-02-08 20:37:3055 spdy::SpdyFramer::set_enable_compression_default(enabled);
[email protected]94d78132010-01-22 00:53:0056 }
57
[email protected]3caf5542010-07-16 15:19:4758 class StartTransactionCallback;
59 class DeleteSessionCallback;
[email protected]74188f22010-04-09 20:18:5060
[email protected]3caf5542010-07-16 15:19:4761 // A helper class that handles all the initial npn/ssl setup.
62 class NormalSpdyTransactionHelper {
63 public:
64 NormalSpdyTransactionHelper(const HttpRequestInfo& request,
[email protected]9e9e842e2010-07-23 23:09:1565 const BoundNetLog& log,
66 SpdyNetworkTransactionTestTypes test_type)
[email protected]30c942b2010-07-21 16:59:5967 : request_(request),
[email protected]b261d0e2010-08-02 19:13:2468 session_deps_(new SpdySessionDependencies()),
69 session_(SpdySessionDependencies::SpdyCreateSession(
70 session_deps_.get())),
[email protected]9e9e842e2010-07-23 23:09:1571 log_(log),
[email protected]3b7828432010-08-18 18:33:2772 test_type_(test_type),
[email protected]1f418ee2010-10-16 19:46:5673 deterministic_(false),
74 spdy_enabled_(true) {
[email protected]a33cad2b62010-07-30 22:24:3975 switch (test_type_) {
[email protected]9e9e842e2010-07-23 23:09:1576 case SPDYNOSSL:
77 case SPDYSSL:
78 port_ = 80;
79 break;
80 case SPDYNPN:
81 port_ = 443;
82 break;
83 default:
84 NOTREACHED();
85 }
86 }
[email protected]74188f22010-04-09 20:18:5087
[email protected]19ec8a72010-08-23 03:38:2388 ~NormalSpdyTransactionHelper() {
89 // Any test which doesn't close the socket by sending it an EOF will
90 // have a valid session left open, which leaks the entire session pool.
91 // This is just fine - in fact, some of our tests intentionally do this
92 // so that we can check consistency of the SpdySessionPool as the test
93 // finishes. If we had put an EOF on the socket, the SpdySession would
94 // have closed and we wouldn't be able to check the consistency.
95
96 // Forcefully close existing sessions here.
97 session()->spdy_session_pool()->CloseAllSessions();
98 }
99
[email protected]3b7828432010-08-18 18:33:27100 void SetDeterministic() {
101 session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
102 session_deps_.get());
103 deterministic_ = true;
104 }
105
[email protected]1f418ee2010-10-16 19:46:56106 void SetSpdyDisabled() {
107 spdy_enabled_ = false;
108 }
109
[email protected]3caf5542010-07-16 15:19:47110 void RunPreTestSetup() {
[email protected]b261d0e2010-08-02 19:13:24111 if (!session_deps_.get())
112 session_deps_.reset(new SpdySessionDependencies());
113 if (!session_.get())
114 session_ = SpdySessionDependencies::SpdyCreateSession(
115 session_deps_.get());
[email protected]8e6441ca2010-08-19 05:56:38116 HttpStreamFactory::set_use_alternate_protocols(false);
117 HttpStreamFactory::set_force_spdy_over_ssl(false);
118 HttpStreamFactory::set_force_spdy_always(false);
[email protected]a33cad2b62010-07-30 22:24:39119 switch (test_type_) {
[email protected]9e9e842e2010-07-23 23:09:15120 case SPDYNPN:
121 session_->mutable_alternate_protocols()->SetAlternateProtocolFor(
122 HostPortPair("www.google.com", 80), 443,
[email protected]dae22c52010-07-30 02:16:35123 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]8e6441ca2010-08-19 05:56:38124 HttpStreamFactory::set_use_alternate_protocols(true);
125 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]9e9e842e2010-07-23 23:09:15126 break;
127 case SPDYNOSSL:
[email protected]8e6441ca2010-08-19 05:56:38128 HttpStreamFactory::set_force_spdy_over_ssl(false);
129 HttpStreamFactory::set_force_spdy_always(true);
[email protected]9e9e842e2010-07-23 23:09:15130 break;
131 case SPDYSSL:
[email protected]8e6441ca2010-08-19 05:56:38132 HttpStreamFactory::set_force_spdy_over_ssl(true);
133 HttpStreamFactory::set_force_spdy_always(true);
[email protected]9e9e842e2010-07-23 23:09:15134 break;
135 default:
136 NOTREACHED();
[email protected]3caf5542010-07-16 15:19:47137 }
[email protected]aea80602009-09-18 00:55:08138
[email protected]3caf5542010-07-16 15:19:47139 // We're now ready to use SSL-npn SPDY.
140 trans_.reset(new HttpNetworkTransaction(session_));
[email protected]cb54b3b22010-06-03 16:28:55141 }
[email protected]aea80602009-09-18 00:55:08142
[email protected]3caf5542010-07-16 15:19:47143 // Start the transaction, read some data, finish.
144 void RunDefaultTest() {
145 output_.rv = trans_->Start(&request_, &callback, log_);
[email protected]aea80602009-09-18 00:55:08146
[email protected]3caf5542010-07-16 15:19:47147 // We expect an IO Pending or some sort of error.
148 EXPECT_LT(output_.rv, 0);
149 if (output_.rv != ERR_IO_PENDING)
150 return;
[email protected]aea80602009-09-18 00:55:08151
[email protected]3caf5542010-07-16 15:19:47152 output_.rv = callback.WaitForResult();
153 if (output_.rv != OK) {
[email protected]a01ea222010-08-19 16:50:53154 session_->spdy_session_pool()->CloseCurrentSessions();
[email protected]3caf5542010-07-16 15:19:47155 return;
156 }
[email protected]ff57bb82009-11-12 06:52:14157
[email protected]3caf5542010-07-16 15:19:47158 // Verify responses.
159 const HttpResponseInfo* response = trans_->GetResponseInfo();
160 ASSERT_TRUE(response != NULL);
161 ASSERT_TRUE(response->headers != NULL);
162 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]1f418ee2010-10-16 19:46:56163 EXPECT_EQ(spdy_enabled_, response->was_fetched_via_spdy);
164 if (test_type_ == SPDYNPN && spdy_enabled_) {
[email protected]9e9e842e2010-07-23 23:09:15165 EXPECT_TRUE(response->was_npn_negotiated);
166 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]a33cad2b62010-07-30 22:24:39167 } else {
[email protected]9e9e842e2010-07-23 23:09:15168 EXPECT_TRUE(!response->was_npn_negotiated);
169 EXPECT_TRUE(!response->was_alternate_protocol_available);
170 }
[email protected]1f418ee2010-10-16 19:46:56171 // If SPDY is not enabled, a HTTP request should not be diverted
172 // over a SSL session.
173 if (!spdy_enabled_) {
174 EXPECT_EQ(request_.url.SchemeIs("https"),
175 response->was_npn_negotiated);
176 }
[email protected]3caf5542010-07-16 15:19:47177 output_.status_line = response->headers->GetStatusLine();
178 output_.response_info = *response; // Make a copy so we can verify.
179 output_.rv = ReadTransaction(trans_.get(), &output_.response_data);
180 EXPECT_EQ(OK, output_.rv);
181 return;
182 }
183
184 // Most tests will want to call this function. In particular, the MockReads
185 // should end with an empty read, and that read needs to be processed to
186 // ensure proper deletion of the spdy_session_pool.
187 void VerifyDataConsumed() {
[email protected]a33cad2b62010-07-30 22:24:39188 for (DataVector::iterator it = data_vector_.begin();
[email protected]3caf5542010-07-16 15:19:47189 it != data_vector_.end(); ++it) {
190 EXPECT_TRUE((*it)->at_read_eof()) << "Read count: "
191 << (*it)->read_count()
192 << " Read index: "
193 << (*it)->read_index();
194 EXPECT_TRUE((*it)->at_write_eof()) << "Write count: "
195 << (*it)->write_count()
196 << " Write index: "
197 << (*it)->write_index();
198 }
199 }
200
201 // Occasionally a test will expect to error out before certain reads are
202 // processed. In that case we want to explicitly ensure that the reads were
203 // not processed.
204 void VerifyDataNotConsumed() {
[email protected]a33cad2b62010-07-30 22:24:39205 for (DataVector::iterator it = data_vector_.begin();
[email protected]3caf5542010-07-16 15:19:47206 it != data_vector_.end(); ++it) {
207 EXPECT_TRUE(!(*it)->at_read_eof()) << "Read count: "
208 << (*it)->read_count()
209 << " Read index: "
210 << (*it)->read_index();
211 EXPECT_TRUE(!(*it)->at_write_eof()) << "Write count: "
212 << (*it)->write_count()
213 << " Write index: "
214 << (*it)->write_index();
[email protected]3caf5542010-07-16 15:19:47215 }
216 }
217
218 void RunToCompletion(StaticSocketDataProvider* data) {
[email protected]3caf5542010-07-16 15:19:47219 RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:58220 AddData(data);
[email protected]3caf5542010-07-16 15:19:47221 RunDefaultTest();
222 VerifyDataConsumed();
223 }
[email protected]e6b06862010-07-20 16:32:58224
[email protected]3caf5542010-07-16 15:19:47225 void AddData(StaticSocketDataProvider* data) {
[email protected]3b7828432010-08-18 18:33:27226 DCHECK(!deterministic_);
[email protected]3caf5542010-07-16 15:19:47227 data_vector_.push_back(data);
[email protected]9e9e842e2010-07-23 23:09:15228 linked_ptr<SSLSocketDataProvider> ssl_(
229 new SSLSocketDataProvider(true, OK));
[email protected]a33cad2b62010-07-30 22:24:39230 if (test_type_ == SPDYNPN) {
[email protected]9e9e842e2010-07-23 23:09:15231 ssl_->next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:35232 ssl_->next_proto = "spdy/2";
[email protected]9e9e842e2010-07-23 23:09:15233 ssl_->was_npn_negotiated = true;
234 }
235 ssl_vector_.push_back(ssl_);
[email protected]b261d0e2010-08-02 19:13:24236 if(test_type_ == SPDYNPN || test_type_ == SPDYSSL)
[email protected]3b7828432010-08-18 18:33:27237 session_deps_->socket_factory->AddSSLSocketDataProvider(ssl_.get());
238 session_deps_->socket_factory->AddSocketDataProvider(data);
239 }
240
241 void AddDeterministicData(DeterministicSocketData* data) {
242 DCHECK(deterministic_);
243 data_vector_.push_back(data);
244 linked_ptr<SSLSocketDataProvider> ssl_(
245 new SSLSocketDataProvider(true, OK));
246 if (test_type_ == SPDYNPN) {
247 ssl_->next_proto_status = SSLClientSocket::kNextProtoNegotiated;
248 ssl_->next_proto = "spdy/2";
249 ssl_->was_npn_negotiated = true;
250 }
251 ssl_vector_.push_back(ssl_);
252 if(test_type_ == SPDYNPN || test_type_ == SPDYSSL)
253 session_deps_->deterministic_socket_factory->
254 AddSSLSocketDataProvider(ssl_.get());
255 session_deps_->deterministic_socket_factory->AddSocketDataProvider(data);
[email protected]3caf5542010-07-16 15:19:47256 }
257
[email protected]e6b06862010-07-20 16:32:58258 // This can only be called after RunPreTestSetup. It adds a Data Provider,
259 // but not a corresponding SSL data provider
260 void AddDataNoSSL(StaticSocketDataProvider* data) {
[email protected]3b7828432010-08-18 18:33:27261 DCHECK(!deterministic_);
262 session_deps_->socket_factory->AddSocketDataProvider(data);
263 }
264 void AddDataNoSSL(DeterministicSocketData* data) {
265 DCHECK(deterministic_);
266 session_deps_->deterministic_socket_factory->AddSocketDataProvider(data);
[email protected]e6b06862010-07-20 16:32:58267 }
268
[email protected]a33cad2b62010-07-30 22:24:39269 void SetSession(const scoped_refptr<HttpNetworkSession>& session) {
[email protected]3caf5542010-07-16 15:19:47270 session_ = session;
271 }
272 HttpNetworkTransaction* trans() { return trans_.get(); }
273 void ResetTrans() { trans_.reset(); }
274 TransactionHelperResult& output() { return output_; }
[email protected]19ec8a72010-08-23 03:38:23275 const HttpRequestInfo& request() const { return request_; }
276 const scoped_refptr<HttpNetworkSession>& session() const {
277 return session_;
278 }
[email protected]b261d0e2010-08-02 19:13:24279 scoped_ptr<SpdySessionDependencies>& session_deps() {
280 return session_deps_;
281 }
[email protected]19ec8a72010-08-23 03:38:23282 int port() const { return port_; }
283 SpdyNetworkTransactionTestTypes test_type() const { return test_type_; }
[email protected]3caf5542010-07-16 15:19:47284
285 private:
286 typedef std::vector<StaticSocketDataProvider*> DataVector;
287 typedef std::vector<linked_ptr<SSLSocketDataProvider> > SSLVector;
288 HttpRequestInfo request_;
[email protected]b261d0e2010-08-02 19:13:24289 scoped_ptr<SpdySessionDependencies> session_deps_;
[email protected]3caf5542010-07-16 15:19:47290 scoped_refptr<HttpNetworkSession> session_;
291 TransactionHelperResult output_;
292 scoped_ptr<StaticSocketDataProvider> first_transaction_;
293 SSLVector ssl_vector_;
294 TestCompletionCallback callback;
295 scoped_ptr<HttpNetworkTransaction> trans_;
296 scoped_ptr<HttpNetworkTransaction> trans_http_;
297 DataVector data_vector_;
298 const BoundNetLog& log_;
[email protected]9e9e842e2010-07-23 23:09:15299 SpdyNetworkTransactionTestTypes test_type_;
300 int port_;
[email protected]3b7828432010-08-18 18:33:27301 bool deterministic_;
[email protected]1f418ee2010-10-16 19:46:56302 bool spdy_enabled_;
[email protected]3caf5542010-07-16 15:19:47303 };
[email protected]aea80602009-09-18 00:55:08304
305 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
306 int expected_status);
307
308 void ConnectStatusHelper(const MockRead& status);
[email protected]d3cee19d2010-06-22 18:42:18309
[email protected]e3ebba0f2010-08-05 17:59:58310 const HttpRequestInfo& CreateGetPushRequest() {
311 google_get_push_request_.method = "GET";
312 google_get_push_request_.url = GURL("http://www.google.com/foo.dat");
313 google_get_push_request_.load_flags = 0;
314 return google_get_push_request_;
315 }
316
[email protected]d3cee19d2010-06-22 18:42:18317 const HttpRequestInfo& CreateGetRequest() {
318 if (!google_get_request_initialized_) {
319 google_get_request_.method = "GET";
[email protected]310240592010-08-05 21:04:19320 google_get_request_.url = GURL(kDefaultURL);
[email protected]d3cee19d2010-06-22 18:42:18321 google_get_request_.load_flags = 0;
322 google_get_request_initialized_ = true;
323 }
324 return google_get_request_;
325 }
326
[email protected]3deb9a52010-11-11 00:24:40327 const HttpRequestInfo& CreateGetRequestWithUserAgent() {
328 if (!google_get_request_initialized_) {
329 google_get_request_.method = "GET";
330 google_get_request_.url = GURL(kDefaultURL);
331 google_get_request_.load_flags = 0;
332 google_get_request_.extra_headers.SetHeader("User-Agent", "Chrome");
333 google_get_request_initialized_ = true;
334 }
335 return google_get_request_;
336 }
337
[email protected]310240592010-08-05 21:04:19338 const HttpRequestInfo& CreatePostRequest() {
339 if (!google_post_request_initialized_) {
340 google_post_request_.method = "POST";
341 google_post_request_.url = GURL(kDefaultURL);
342 google_post_request_.upload_data = new UploadData();
343 google_post_request_.upload_data->AppendBytes(kUploadData,
344 kUploadDataSize);
345 google_post_request_initialized_ = true;
346 }
347 return google_post_request_;
348 }
349
[email protected]19ec8a72010-08-23 03:38:23350 // Read the result of a particular transaction, knowing that we've got
351 // multiple transactions in the read pipeline; so as we read, we may have
352 // to skip over data destined for other transactions while we consume
353 // the data for |trans|.
354 int ReadResult(HttpNetworkTransaction* trans,
355 OrderedSocketData* data,
356 std::string* result) {
357 const int kSize = 3000;
[email protected]e3ebba0f2010-08-05 17:59:58358
[email protected]19ec8a72010-08-23 03:38:23359 int bytes_read = 0;
[email protected]ad8e04a2010-11-01 04:16:27360 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(kSize));
[email protected]19ec8a72010-08-23 03:38:23361 TestCompletionCallback callback;
362 while (true) {
363 int rv = trans->Read(buf, kSize, &callback);
364 if (rv == ERR_IO_PENDING) {
365 // Multiple transactions may be in the data set. Keep pulling off
366 // reads until we complete our callback.
367 while (!callback.have_result()) {
368 data->CompleteRead();
369 MessageLoop::current()->RunAllPending();
370 }
371 rv = callback.WaitForResult();
372 } else if (rv <= 0) {
373 break;
374 }
375 result->append(buf->data(), rv);
376 bytes_read += rv;
[email protected]e3ebba0f2010-08-05 17:59:58377 }
[email protected]19ec8a72010-08-23 03:38:23378 return bytes_read;
379 }
[email protected]e3ebba0f2010-08-05 17:59:58380
[email protected]19ec8a72010-08-23 03:38:23381 void VerifyStreamsClosed(const NormalSpdyTransactionHelper& helper) {
382 // This lengthy block is reaching into the pool to dig out the active
383 // session. Once we have the session, we verify that the streams are
384 // all closed and not leaked at this point.
385 const GURL& url = helper.request().url;
386 int port = helper.test_type() == SPDYNPN ? 443 : 80;
387 HostPortPair host_port_pair(url.host(), port);
[email protected]31e68d72010-08-25 06:36:58388 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]19ec8a72010-08-23 03:38:23389 BoundNetLog log;
390 const scoped_refptr<HttpNetworkSession>& session = helper.session();
[email protected]87bfa3f2010-09-30 14:54:56391 SpdySessionPool* pool(session->spdy_session_pool());
[email protected]19ec8a72010-08-23 03:38:23392 EXPECT_TRUE(pool->HasSession(pair));
[email protected]f4580332010-09-25 21:20:27393 scoped_refptr<SpdySession> spdy_session(
394 pool->Get(pair, session->mutable_spdy_settings(), log));
[email protected]19ec8a72010-08-23 03:38:23395 ASSERT_TRUE(spdy_session.get() != NULL);
396 EXPECT_EQ(0u, spdy_session->num_active_streams());
397 EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams());
398 }
[email protected]e3ebba0f2010-08-05 17:59:58399
400 void RunServerPushTest(MockWrite writes[], int writes_length,
401 MockRead reads[], int reads_length,
402 HttpResponseInfo* response,
403 HttpResponseInfo* response2,
404 std::string& expected) {
405 scoped_refptr<OrderedSocketData> data(
406 new OrderedSocketData(reads, reads_length,
407 writes, writes_length));
408 NormalSpdyTransactionHelper helper(CreateGetRequest(),
409 BoundNetLog(), GetParam());
410
411 helper.RunPreTestSetup();
412 helper.AddData(data.get());
413
414 HttpNetworkTransaction* trans = helper.trans();
415
416 // Start the transaction with basic parameters.
417 TestCompletionCallback callback;
418 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
419 EXPECT_EQ(ERR_IO_PENDING, rv);
420 rv = callback.WaitForResult();
421
422 // Request the pushed path.
[email protected]e3ebba0f2010-08-05 17:59:58423 scoped_ptr<HttpNetworkTransaction> trans2(
424 new HttpNetworkTransaction(helper.session()));
425 rv = trans2->Start(&CreateGetPushRequest(), &callback, BoundNetLog());
426 EXPECT_EQ(ERR_IO_PENDING, rv);
427 MessageLoop::current()->RunAllPending();
428
429 // The data for the pushed path may be coming in more than 1 packet. Compile
430 // the results into a single string.
[email protected]19ec8a72010-08-23 03:38:23431
432 // Read the server push body.
433 std::string result2;
434 ReadResult(trans2.get(), data, &result2);
435 // Read the response body.
[email protected]e3ebba0f2010-08-05 17:59:58436 std::string result;
[email protected]19ec8a72010-08-23 03:38:23437 ReadResult(trans, data, &result);
[email protected]e3ebba0f2010-08-05 17:59:58438
439 // Verify that we consumed all test data.
440 EXPECT_TRUE(data->at_read_eof());
441 EXPECT_TRUE(data->at_write_eof());
442
443 // Verify that the received push data is same as the expected push data.
[email protected]19ec8a72010-08-23 03:38:23444 EXPECT_EQ(result2.compare(expected), 0) << "Received data: "
445 << result2
446 << "||||| Expected data: "
447 << expected;
[email protected]e3ebba0f2010-08-05 17:59:58448
449 // Verify the SYN_REPLY.
450 // Copy the response info, because trans goes away.
451 *response = *trans->GetResponseInfo();
452 *response2 = *trans2->GetResponseInfo();
[email protected]19ec8a72010-08-23 03:38:23453
454 VerifyStreamsClosed(helper);
[email protected]e3ebba0f2010-08-05 17:59:58455 }
456
[email protected]d3cee19d2010-06-22 18:42:18457 private:
458 bool google_get_request_initialized_;
[email protected]310240592010-08-05 21:04:19459 bool google_post_request_initialized_;
[email protected]d3cee19d2010-06-22 18:42:18460 HttpRequestInfo google_get_request_;
[email protected]310240592010-08-05 21:04:19461 HttpRequestInfo google_post_request_;
[email protected]e3ebba0f2010-08-05 17:59:58462 HttpRequestInfo google_get_push_request_;
[email protected]aea80602009-09-18 00:55:08463};
464
465//-----------------------------------------------------------------------------
[email protected]9e9e842e2010-07-23 23:09:15466// All tests are run with three different connection types: SPDY after NPN
467// negotiation, SPDY without SSL, and SPDY with SSL.
[email protected]5cd9d7f2010-09-03 22:06:24468INSTANTIATE_TEST_CASE_P(Spdy,
[email protected]9e9e842e2010-07-23 23:09:15469 SpdyNetworkTransactionTest,
[email protected]e3ebba0f2010-08-05 17:59:58470 ::testing::Values(SPDYNOSSL, SPDYSSL, SPDYNPN));
[email protected]9e9e842e2010-07-23 23:09:15471
[email protected]aea80602009-09-18 00:55:08472
[email protected]3caf5542010-07-16 15:19:47473// Verify HttpNetworkTransaction constructor.
[email protected]9e9e842e2010-07-23 23:09:15474TEST_P(SpdyNetworkTransactionTest, Constructor) {
[email protected]30c942b2010-07-21 16:59:59475 SpdySessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:27476 scoped_refptr<HttpNetworkSession> session(
477 SpdySessionDependencies::SpdyCreateSession(&session_deps));
[email protected]3caf5542010-07-16 15:19:47478 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]aea80602009-09-18 00:55:08479}
480
[email protected]9e9e842e2010-07-23 23:09:15481TEST_P(SpdyNetworkTransactionTest, Get) {
[email protected]75f30cc22010-06-28 21:41:38482 // Construct the request.
[email protected]2bd93022010-07-17 00:58:44483 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:13484 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]72552f02009-10-28 15:25:01485
[email protected]2bd93022010-07-17 00:58:44486 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
487 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]72552f02009-10-28 15:25:01488 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:13489 CreateMockRead(*resp),
490 CreateMockRead(*body),
[email protected]72552f02009-10-28 15:25:01491 MockRead(true, 0, 0) // EOF
492 };
493
[email protected]bf2491a92009-11-29 16:39:48494 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:39495 new DelayedSocketData(1, reads, arraysize(reads),
496 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:47497 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:15498 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:47499 helper.RunToCompletion(data.get());
500 TransactionHelperResult out = helper.output();
[email protected]72552f02009-10-28 15:25:01501 EXPECT_EQ(OK, out.rv);
502 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
503 EXPECT_EQ("hello!", out.response_data);
504}
505
[email protected]c9c6f5c2010-07-31 01:30:03506TEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) {
507 for (RequestPriority p = HIGHEST; p < NUM_PRIORITIES;
508 p = RequestPriority(p+1)) {
509 // Construct the request.
510 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, p));
511 MockWrite writes[] = { CreateMockWrite(*req) };
512
513 const int spdy_prio = reinterpret_cast<spdy::SpdySynStreamControlFrame*>(
514 req.get())->priority();
515 // this repeats the RequestPriority-->SpdyPriority mapping from
516 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
517 // sure it's being done right.
518 switch(p) {
519 case HIGHEST:
520 EXPECT_EQ(0, spdy_prio);
521 break;
522 case MEDIUM:
523 EXPECT_EQ(1, spdy_prio);
524 break;
525 case LOW:
526 case LOWEST:
527 EXPECT_EQ(2, spdy_prio);
528 break;
529 case IDLE:
530 EXPECT_EQ(3, spdy_prio);
531 break;
532 default:
533 FAIL();
534 }
535
536 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
537 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
538 MockRead reads[] = {
539 CreateMockRead(*resp),
540 CreateMockRead(*body),
541 MockRead(true, 0, 0) // EOF
542 };
543
544 scoped_refptr<DelayedSocketData> data(
545 new DelayedSocketData(1, reads, arraysize(reads),
546 writes, arraysize(writes)));
547 HttpRequestInfo http_req = CreateGetRequest();
548 http_req.priority = p;
549
550 NormalSpdyTransactionHelper helper(http_req, BoundNetLog(), GetParam());
551 helper.RunToCompletion(data.get());
552 TransactionHelperResult out = helper.output();
553 EXPECT_EQ(OK, out.rv);
554 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
555 EXPECT_EQ("hello!", out.response_data);
556 }
557}
558
[email protected]2bd93022010-07-17 00:58:44559// Start three gets simultaniously; making sure that multiplexed
560// streams work properly.
561
562// This can't use the TransactionHelper method, since it only
563// handles a single transaction, and finishes them as soon
564// as it launches them.
565
566// TODO(gavinp): create a working generalized TransactionHelper that
567// can allow multiple streams in flight.
568
[email protected]9e9e842e2010-07-23 23:09:15569TEST_P(SpdyNetworkTransactionTest, ThreeGets) {
[email protected]2bd93022010-07-17 00:58:44570 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
571 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
572 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
573 scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
574
575 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
576 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
577 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
578 scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
579
580 scoped_ptr<spdy::SpdyFrame> req3(ConstructSpdyGet(NULL, 0, false, 5, LOWEST));
581 scoped_ptr<spdy::SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 5));
582 scoped_ptr<spdy::SpdyFrame> body3(ConstructSpdyBodyFrame(5, false));
583 scoped_ptr<spdy::SpdyFrame> fbody3(ConstructSpdyBodyFrame(5, true));
584
585 MockWrite writes[] = { CreateMockWrite(*req),
586 CreateMockWrite(*req2),
587 CreateMockWrite(*req3),
588 };
589 MockRead reads[] = {
590 CreateMockRead(*resp, 1),
591 CreateMockRead(*body),
592 CreateMockRead(*resp2, 4),
593 CreateMockRead(*body2),
594 CreateMockRead(*resp3, 7),
595 CreateMockRead(*body3),
596
597 CreateMockRead(*fbody),
598 CreateMockRead(*fbody2),
599 CreateMockRead(*fbody3),
600
601 MockRead(true, 0, 0), // EOF
602 };
[email protected]2bd93022010-07-17 00:58:44603 scoped_refptr<OrderedSocketData> data(
604 new OrderedSocketData(reads, arraysize(reads),
605 writes, arraysize(writes)));
[email protected]bdebd1b2010-08-09 20:18:08606 scoped_refptr<OrderedSocketData> data_placeholder(
607 new OrderedSocketData(NULL, 0, NULL, 0));
[email protected]2bd93022010-07-17 00:58:44608
609 BoundNetLog log;
610 TransactionHelperResult out;
[email protected]bdebd1b2010-08-09 20:18:08611 NormalSpdyTransactionHelper helper(CreateGetRequest(),
612 BoundNetLog(), GetParam());
613 helper.RunPreTestSetup();
614 helper.AddData(data.get());
615 // We require placeholder data because three get requests are sent out, so
616 // there needs to be three sets of SSL connection data.
617 helper.AddData(data_placeholder.get());
618 helper.AddData(data_placeholder.get());
619 scoped_ptr<HttpNetworkTransaction> trans1(
620 new HttpNetworkTransaction(helper.session()));
621 scoped_ptr<HttpNetworkTransaction> trans2(
622 new HttpNetworkTransaction(helper.session()));
623 scoped_ptr<HttpNetworkTransaction> trans3(
624 new HttpNetworkTransaction(helper.session()));
[email protected]2bd93022010-07-17 00:58:44625
[email protected]bdebd1b2010-08-09 20:18:08626 TestCompletionCallback callback1;
627 TestCompletionCallback callback2;
628 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:44629
[email protected]bdebd1b2010-08-09 20:18:08630 HttpRequestInfo httpreq1 = CreateGetRequest();
631 HttpRequestInfo httpreq2 = CreateGetRequest();
632 HttpRequestInfo httpreq3 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:44633
[email protected]bdebd1b2010-08-09 20:18:08634 out.rv = trans1->Start(&httpreq1, &callback1, log);
635 ASSERT_EQ(ERR_IO_PENDING, out.rv);
636 out.rv = trans2->Start(&httpreq2, &callback2, log);
637 ASSERT_EQ(ERR_IO_PENDING, out.rv);
638 out.rv = trans3->Start(&httpreq3, &callback3, log);
639 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]2bd93022010-07-17 00:58:44640
[email protected]bdebd1b2010-08-09 20:18:08641 out.rv = callback1.WaitForResult();
642 ASSERT_EQ(OK, out.rv);
643 out.rv = callback3.WaitForResult();
644 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:44645
[email protected]bdebd1b2010-08-09 20:18:08646 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
647 EXPECT_TRUE(response1->headers != NULL);
648 EXPECT_TRUE(response1->was_fetched_via_spdy);
649 out.status_line = response1->headers->GetStatusLine();
650 out.response_info = *response1;
[email protected]2bd93022010-07-17 00:58:44651
[email protected]bdebd1b2010-08-09 20:18:08652 trans2->GetResponseInfo();
[email protected]2bd93022010-07-17 00:58:44653
[email protected]bdebd1b2010-08-09 20:18:08654 out.rv = ReadTransaction(trans1.get(), &out.response_data);
655 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:44656 EXPECT_EQ(OK, out.rv);
657
[email protected]2bd93022010-07-17 00:58:44658 EXPECT_EQ(OK, out.rv);
659 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
660 EXPECT_EQ("hello!hello!", out.response_data);
661}
662
[email protected]2bd93022010-07-17 00:58:44663// Similar to ThreeGets above, however this test adds a SETTINGS
664// frame. The SETTINGS frame is read during the IO loop waiting on
665// the first transaction completion, and sets a maximum concurrent
666// stream limit of 1. This means that our IO loop exists after the
667// second transaction completes, so we can assert on read_index().
[email protected]9e9e842e2010-07-23 23:09:15668TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
[email protected]2bd93022010-07-17 00:58:44669 // Construct the request.
670 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
671 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
672 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
673 scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
674
675 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
676 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
677 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
678 scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
679
680 scoped_ptr<spdy::SpdyFrame> req3(ConstructSpdyGet(NULL, 0, false, 5, LOWEST));
681 scoped_ptr<spdy::SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 5));
682 scoped_ptr<spdy::SpdyFrame> body3(ConstructSpdyBodyFrame(5, false));
683 scoped_ptr<spdy::SpdyFrame> fbody3(ConstructSpdyBodyFrame(5, true));
684
685 spdy::SpdySettings settings;
686 spdy::SettingsFlagsAndId id(0);
687 id.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS);
688 const size_t max_concurrent_streams = 1;
689
690 settings.push_back(spdy::SpdySetting(id, max_concurrent_streams));
691 scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
692
693 MockWrite writes[] = { CreateMockWrite(*req),
694 CreateMockWrite(*req2),
695 CreateMockWrite(*req3),
696 };
697 MockRead reads[] = {
[email protected]bdebd1b2010-08-09 20:18:08698 CreateMockRead(*settings_frame, 1),
[email protected]2bd93022010-07-17 00:58:44699 CreateMockRead(*resp),
700 CreateMockRead(*body),
701 CreateMockRead(*fbody),
[email protected]bdebd1b2010-08-09 20:18:08702 CreateMockRead(*resp2, 7),
[email protected]2bd93022010-07-17 00:58:44703 CreateMockRead(*body2),
704 CreateMockRead(*fbody2),
[email protected]bdebd1b2010-08-09 20:18:08705 CreateMockRead(*resp3, 12),
[email protected]2bd93022010-07-17 00:58:44706 CreateMockRead(*body3),
707 CreateMockRead(*fbody3),
708
709 MockRead(true, 0, 0), // EOF
710 };
711
712 scoped_refptr<OrderedSocketData> data(
713 new OrderedSocketData(reads, arraysize(reads),
714 writes, arraysize(writes)));
[email protected]bdebd1b2010-08-09 20:18:08715 scoped_refptr<OrderedSocketData> data_placeholder(
716 new OrderedSocketData(NULL, 0, NULL, 0));
[email protected]2bd93022010-07-17 00:58:44717
718 BoundNetLog log;
719 TransactionHelperResult out;
720 {
[email protected]bdebd1b2010-08-09 20:18:08721 NormalSpdyTransactionHelper helper(CreateGetRequest(),
722 BoundNetLog(), GetParam());
723 helper.RunPreTestSetup();
724 helper.AddData(data.get());
725 // We require placeholder data because three get requests are sent out, so
726 // there needs to be three sets of SSL connection data.
727 helper.AddData(data_placeholder.get());
728 helper.AddData(data_placeholder.get());
729 scoped_ptr<HttpNetworkTransaction> trans1(
730 new HttpNetworkTransaction(helper.session()));
731 scoped_ptr<HttpNetworkTransaction> trans2(
732 new HttpNetworkTransaction(helper.session()));
733 scoped_ptr<HttpNetworkTransaction> trans3(
734 new HttpNetworkTransaction(helper.session()));
[email protected]2bd93022010-07-17 00:58:44735
736 TestCompletionCallback callback1;
737 TestCompletionCallback callback2;
738 TestCompletionCallback callback3;
739
740 HttpRequestInfo httpreq1 = CreateGetRequest();
741 HttpRequestInfo httpreq2 = CreateGetRequest();
742 HttpRequestInfo httpreq3 = CreateGetRequest();
743
744 out.rv = trans1->Start(&httpreq1, &callback1, log);
745 ASSERT_EQ(out.rv, ERR_IO_PENDING);
746 // run transaction 1 through quickly to force a read of our SETTINGS
747 // frame
748 out.rv = callback1.WaitForResult();
[email protected]bdebd1b2010-08-09 20:18:08749 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:44750
751 out.rv = trans2->Start(&httpreq2, &callback2, log);
752 ASSERT_EQ(out.rv, ERR_IO_PENDING);
753 out.rv = trans3->Start(&httpreq3, &callback3, log);
754 ASSERT_EQ(out.rv, ERR_IO_PENDING);
755 out.rv = callback2.WaitForResult();
756 ASSERT_EQ(OK, out.rv);
757 EXPECT_EQ(7U, data->read_index()); // i.e. the third trans was queued
758
759 out.rv = callback3.WaitForResult();
760 ASSERT_EQ(OK, out.rv);
761
762 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
[email protected]bdebd1b2010-08-09 20:18:08763 ASSERT_TRUE(response1 != NULL);
[email protected]2bd93022010-07-17 00:58:44764 EXPECT_TRUE(response1->headers != NULL);
765 EXPECT_TRUE(response1->was_fetched_via_spdy);
766 out.status_line = response1->headers->GetStatusLine();
767 out.response_info = *response1;
768 out.rv = ReadTransaction(trans1.get(), &out.response_data);
769 EXPECT_EQ(OK, out.rv);
770 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
771 EXPECT_EQ("hello!hello!", out.response_data);
772
773 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
774 out.status_line = response2->headers->GetStatusLine();
775 out.response_info = *response2;
776 out.rv = ReadTransaction(trans2.get(), &out.response_data);
777 EXPECT_EQ(OK, out.rv);
778 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
779 EXPECT_EQ("hello!hello!", out.response_data);
780
781 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
782 out.status_line = response3->headers->GetStatusLine();
783 out.response_info = *response3;
784 out.rv = ReadTransaction(trans3.get(), &out.response_data);
785 EXPECT_EQ(OK, out.rv);
786 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
787 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]044dcc52010-09-17 15:44:26788
789 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:44790 }
791 EXPECT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:44792}
793
794// Similar to ThreeGetsWithMaxConcurrent above, however this test adds
795// a fourth transaction. The third and fourth transactions have
796// different data ("hello!" vs "hello!hello!") and because of the
797// user specified priority, we expect to see them inverted in
798// the response from the server.
[email protected]9e9e842e2010-07-23 23:09:15799TEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
[email protected]2bd93022010-07-17 00:58:44800 // Construct the request.
801 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
802 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
803 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
804 scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
805
806 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
807 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
808 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
809 scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
810
811 scoped_ptr<spdy::SpdyFrame> req4(
812 ConstructSpdyGet(NULL, 0, false, 5, HIGHEST));
813 scoped_ptr<spdy::SpdyFrame> resp4(ConstructSpdyGetSynReply(NULL, 0, 5));
814 scoped_ptr<spdy::SpdyFrame> fbody4(ConstructSpdyBodyFrame(5, true));
815
816 scoped_ptr<spdy::SpdyFrame> req3(ConstructSpdyGet(NULL, 0, false, 7, LOWEST));
817 scoped_ptr<spdy::SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 7));
818 scoped_ptr<spdy::SpdyFrame> body3(ConstructSpdyBodyFrame(7, false));
819 scoped_ptr<spdy::SpdyFrame> fbody3(ConstructSpdyBodyFrame(7, true));
820
821
822 spdy::SpdySettings settings;
823 spdy::SettingsFlagsAndId id(0);
824 id.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS);
825 const size_t max_concurrent_streams = 1;
826
827 settings.push_back(spdy::SpdySetting(id, max_concurrent_streams));
828 scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
829
830 MockWrite writes[] = { CreateMockWrite(*req),
[email protected]bdebd1b2010-08-09 20:18:08831 CreateMockWrite(*req2),
832 CreateMockWrite(*req4),
833 CreateMockWrite(*req3),
[email protected]2bd93022010-07-17 00:58:44834 };
835 MockRead reads[] = {
[email protected]bdebd1b2010-08-09 20:18:08836 CreateMockRead(*settings_frame, 1),
[email protected]2bd93022010-07-17 00:58:44837 CreateMockRead(*resp),
838 CreateMockRead(*body),
839 CreateMockRead(*fbody),
[email protected]bdebd1b2010-08-09 20:18:08840 CreateMockRead(*resp2, 7),
[email protected]2bd93022010-07-17 00:58:44841 CreateMockRead(*body2),
842 CreateMockRead(*fbody2),
[email protected]bdebd1b2010-08-09 20:18:08843 CreateMockRead(*resp4, 13),
[email protected]2bd93022010-07-17 00:58:44844 CreateMockRead(*fbody4),
[email protected]bdebd1b2010-08-09 20:18:08845 CreateMockRead(*resp3, 16),
[email protected]2bd93022010-07-17 00:58:44846 CreateMockRead(*body3),
847 CreateMockRead(*fbody3),
848
849 MockRead(true, 0, 0), // EOF
850 };
851
852 scoped_refptr<OrderedSocketData> data(
853 new OrderedSocketData(reads, arraysize(reads),
[email protected]bdebd1b2010-08-09 20:18:08854 writes, arraysize(writes)));
855 scoped_refptr<OrderedSocketData> data_placeholder(
856 new OrderedSocketData(NULL, 0, NULL, 0));
[email protected]2bd93022010-07-17 00:58:44857
858 BoundNetLog log;
859 TransactionHelperResult out;
[email protected]bdebd1b2010-08-09 20:18:08860 NormalSpdyTransactionHelper helper(CreateGetRequest(),
861 BoundNetLog(), GetParam());
862 helper.RunPreTestSetup();
863 helper.AddData(data.get());
864 // We require placeholder data because four get requests are sent out, so
865 // there needs to be four sets of SSL connection data.
866 helper.AddData(data_placeholder.get());
867 helper.AddData(data_placeholder.get());
868 helper.AddData(data_placeholder.get());
869 scoped_ptr<HttpNetworkTransaction> trans1(
870 new HttpNetworkTransaction(helper.session()));
871 scoped_ptr<HttpNetworkTransaction> trans2(
872 new HttpNetworkTransaction(helper.session()));
873 scoped_ptr<HttpNetworkTransaction> trans3(
874 new HttpNetworkTransaction(helper.session()));
875 scoped_ptr<HttpNetworkTransaction> trans4(
876 new HttpNetworkTransaction(helper.session()));
[email protected]2bd93022010-07-17 00:58:44877
[email protected]bdebd1b2010-08-09 20:18:08878 TestCompletionCallback callback1;
879 TestCompletionCallback callback2;
880 TestCompletionCallback callback3;
881 TestCompletionCallback callback4;
[email protected]2bd93022010-07-17 00:58:44882
[email protected]bdebd1b2010-08-09 20:18:08883 HttpRequestInfo httpreq1 = CreateGetRequest();
884 HttpRequestInfo httpreq2 = CreateGetRequest();
885 HttpRequestInfo httpreq3 = CreateGetRequest();
886 HttpRequestInfo httpreq4 = CreateGetRequest();
887 httpreq4.priority = HIGHEST;
[email protected]2bd93022010-07-17 00:58:44888
[email protected]bdebd1b2010-08-09 20:18:08889 out.rv = trans1->Start(&httpreq1, &callback1, log);
890 ASSERT_EQ(ERR_IO_PENDING, out.rv);
891 // run transaction 1 through quickly to force a read of our SETTINGS
892 // frame
893 out.rv = callback1.WaitForResult();
894 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:44895
[email protected]bdebd1b2010-08-09 20:18:08896 out.rv = trans2->Start(&httpreq2, &callback2, log);
897 ASSERT_EQ(ERR_IO_PENDING, out.rv);
898 out.rv = trans3->Start(&httpreq3, &callback3, log);
899 ASSERT_EQ(ERR_IO_PENDING, out.rv);
900 out.rv = trans4->Start(&httpreq4, &callback4, log);
901 ASSERT_EQ(ERR_IO_PENDING, out.rv);
[email protected]2bd93022010-07-17 00:58:44902
[email protected]bdebd1b2010-08-09 20:18:08903 out.rv = callback2.WaitForResult();
904 ASSERT_EQ(OK, out.rv);
905 EXPECT_EQ(data->read_index(), 7U); // i.e. the third & fourth trans queued
[email protected]2bd93022010-07-17 00:58:44906
[email protected]bdebd1b2010-08-09 20:18:08907 out.rv = callback3.WaitForResult();
908 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:44909
[email protected]bdebd1b2010-08-09 20:18:08910 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
911 EXPECT_TRUE(response1->headers != NULL);
912 EXPECT_TRUE(response1->was_fetched_via_spdy);
913 out.status_line = response1->headers->GetStatusLine();
914 out.response_info = *response1;
915 out.rv = ReadTransaction(trans1.get(), &out.response_data);
916 EXPECT_EQ(OK, out.rv);
917 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
918 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:44919
[email protected]bdebd1b2010-08-09 20:18:08920 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
921 out.status_line = response2->headers->GetStatusLine();
922 out.response_info = *response2;
923 out.rv = ReadTransaction(trans2.get(), &out.response_data);
924 EXPECT_EQ(OK, out.rv);
925 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
926 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:44927
[email protected]bdebd1b2010-08-09 20:18:08928 // notice: response3 gets two hellos, response4 gets one
929 // hello, so we know dequeuing priority was respected.
930 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
931 out.status_line = response3->headers->GetStatusLine();
932 out.response_info = *response3;
933 out.rv = ReadTransaction(trans3.get(), &out.response_data);
934 EXPECT_EQ(OK, out.rv);
935 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
936 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:44937
[email protected]bdebd1b2010-08-09 20:18:08938 out.rv = callback4.WaitForResult();
939 EXPECT_EQ(OK, out.rv);
940 const HttpResponseInfo* response4 = trans4->GetResponseInfo();
941 out.status_line = response4->headers->GetStatusLine();
942 out.response_info = *response4;
943 out.rv = ReadTransaction(trans4.get(), &out.response_data);
944 EXPECT_EQ(OK, out.rv);
945 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
946 EXPECT_EQ("hello!", out.response_data);
947 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:44948 EXPECT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:44949}
950
951// Similar to ThreeGetsMaxConcurrrent above, however, this test
952// deletes a session in the middle of the transaction to insure
953// that we properly remove pendingcreatestream objects from
954// the spdy_session
[email protected]9e9e842e2010-07-23 23:09:15955TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
[email protected]2bd93022010-07-17 00:58:44956 // Construct the request.
957 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
958 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
959 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
960 scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
961
962 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
963 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
964 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
965 scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
966
[email protected]2bd93022010-07-17 00:58:44967 spdy::SpdySettings settings;
968 spdy::SettingsFlagsAndId id(0);
969 id.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS);
970 const size_t max_concurrent_streams = 1;
971
972 settings.push_back(spdy::SpdySetting(id, max_concurrent_streams));
973 scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
974
975 MockWrite writes[] = { CreateMockWrite(*req),
[email protected]bdebd1b2010-08-09 20:18:08976 CreateMockWrite(*req2),
[email protected]2bd93022010-07-17 00:58:44977 };
978 MockRead reads[] = {
[email protected]bdebd1b2010-08-09 20:18:08979 CreateMockRead(*settings_frame, 1),
[email protected]2bd93022010-07-17 00:58:44980 CreateMockRead(*resp),
981 CreateMockRead(*body),
982 CreateMockRead(*fbody),
[email protected]bdebd1b2010-08-09 20:18:08983 CreateMockRead(*resp2, 7),
[email protected]2bd93022010-07-17 00:58:44984 CreateMockRead(*body2),
985 CreateMockRead(*fbody2),
986 MockRead(true, 0, 0), // EOF
987 };
988
989 scoped_refptr<OrderedSocketData> data(
990 new OrderedSocketData(reads, arraysize(reads),
[email protected]bdebd1b2010-08-09 20:18:08991 writes, arraysize(writes)));
992 scoped_refptr<OrderedSocketData> data_placeholder(
993 new OrderedSocketData(NULL, 0, NULL, 0));
[email protected]2bd93022010-07-17 00:58:44994
995 BoundNetLog log;
996 TransactionHelperResult out;
[email protected]bdebd1b2010-08-09 20:18:08997 NormalSpdyTransactionHelper helper(CreateGetRequest(),
998 BoundNetLog(), GetParam());
999 helper.RunPreTestSetup();
1000 helper.AddData(data.get());
1001 // We require placeholder data because three get requests are sent out, so
1002 // there needs to be three sets of SSL connection data.
1003 helper.AddData(data_placeholder.get());
1004 helper.AddData(data_placeholder.get());
1005 scoped_ptr<HttpNetworkTransaction> trans1(
1006 new HttpNetworkTransaction(helper.session()));
1007 scoped_ptr<HttpNetworkTransaction> trans2(
1008 new HttpNetworkTransaction(helper.session()));
1009 scoped_ptr<HttpNetworkTransaction> trans3(
1010 new HttpNetworkTransaction(helper.session()));
[email protected]2bd93022010-07-17 00:58:441011
[email protected]bdebd1b2010-08-09 20:18:081012 TestCompletionCallback callback1;
1013 TestCompletionCallback callback2;
1014 TestCompletionCallback callback3;
[email protected]2bd93022010-07-17 00:58:441015
[email protected]bdebd1b2010-08-09 20:18:081016 HttpRequestInfo httpreq1 = CreateGetRequest();
1017 HttpRequestInfo httpreq2 = CreateGetRequest();
1018 HttpRequestInfo httpreq3 = CreateGetRequest();
[email protected]2bd93022010-07-17 00:58:441019
[email protected]bdebd1b2010-08-09 20:18:081020 out.rv = trans1->Start(&httpreq1, &callback1, log);
1021 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1022 // run transaction 1 through quickly to force a read of our SETTINGS
1023 // frame
1024 out.rv = callback1.WaitForResult();
1025 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441026
[email protected]bdebd1b2010-08-09 20:18:081027 out.rv = trans2->Start(&httpreq2, &callback2, log);
1028 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1029 out.rv = trans3->Start(&httpreq3, &callback3, log);
1030 delete trans3.release();
1031 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1032 out.rv = callback2.WaitForResult();
1033 ASSERT_EQ(OK, out.rv);
[email protected]2bd93022010-07-17 00:58:441034
[email protected]bdebd1b2010-08-09 20:18:081035 EXPECT_EQ(8U, data->read_index());
[email protected]2bd93022010-07-17 00:58:441036
[email protected]bdebd1b2010-08-09 20:18:081037 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1038 ASSERT_TRUE(response1 != NULL);
1039 EXPECT_TRUE(response1->headers != NULL);
1040 EXPECT_TRUE(response1->was_fetched_via_spdy);
1041 out.status_line = response1->headers->GetStatusLine();
1042 out.response_info = *response1;
1043 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1044 EXPECT_EQ(OK, out.rv);
1045 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1046 EXPECT_EQ("hello!hello!", out.response_data);
[email protected]2bd93022010-07-17 00:58:441047
[email protected]bdebd1b2010-08-09 20:18:081048 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1049 ASSERT_TRUE(response2 != NULL);
1050 out.status_line = response2->headers->GetStatusLine();
1051 out.response_info = *response2;
1052 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1053 EXPECT_EQ(OK, out.rv);
1054 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1055 EXPECT_EQ("hello!hello!", out.response_data);
1056 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441057 EXPECT_EQ(OK, out.rv);
[email protected]044dcc52010-09-17 15:44:261058}
[email protected]2bd93022010-07-17 00:58:441059
[email protected]044dcc52010-09-17 15:44:261060// The KillerCallback will delete the transaction on error as part of the
1061// callback.
1062class KillerCallback : public TestCompletionCallback {
1063 public:
1064 explicit KillerCallback(HttpNetworkTransaction* transaction)
1065 : transaction_(transaction) {}
1066
1067 virtual void RunWithParams(const Tuple1<int>& params) {
1068 if (params.a < 0)
1069 delete transaction_;
1070 TestCompletionCallback::RunWithParams(params);
1071 }
1072
1073 private:
1074 HttpNetworkTransaction* transaction_;
1075};
1076
1077// Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1078// closes the socket while we have a pending transaction waiting for
1079// a pending stream creation. http://crbug.com/52901
1080TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
1081 // Construct the request.
1082 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1083 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1084 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
1085 scoped_ptr<spdy::SpdyFrame> fin_body(ConstructSpdyBodyFrame(1, true));
1086
1087 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
1088 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
1089
1090 spdy::SpdySettings settings;
1091 spdy::SettingsFlagsAndId id(0);
1092 id.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS);
1093 const size_t max_concurrent_streams = 1;
1094
1095 settings.push_back(spdy::SpdySetting(id, max_concurrent_streams));
1096 scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
1097
1098 MockWrite writes[] = { CreateMockWrite(*req),
1099 CreateMockWrite(*req2),
1100 };
1101 MockRead reads[] = {
1102 CreateMockRead(*settings_frame, 1),
1103 CreateMockRead(*resp),
1104 CreateMockRead(*body),
1105 CreateMockRead(*fin_body),
1106 CreateMockRead(*resp2, 7),
1107 MockRead(true, ERR_CONNECTION_RESET, 0), // Abort!
1108 };
1109
1110 scoped_refptr<OrderedSocketData> data(
1111 new OrderedSocketData(reads, arraysize(reads),
1112 writes, arraysize(writes)));
1113 scoped_refptr<OrderedSocketData> data_placeholder(
1114 new OrderedSocketData(NULL, 0, NULL, 0));
1115
1116 BoundNetLog log;
1117 TransactionHelperResult out;
1118 NormalSpdyTransactionHelper helper(CreateGetRequest(),
1119 BoundNetLog(), GetParam());
1120 helper.RunPreTestSetup();
1121 helper.AddData(data.get());
1122 // We require placeholder data because three get requests are sent out, so
1123 // there needs to be three sets of SSL connection data.
1124 helper.AddData(data_placeholder.get());
1125 helper.AddData(data_placeholder.get());
1126 HttpNetworkTransaction trans1(helper.session());
1127 HttpNetworkTransaction trans2(helper.session());
1128 HttpNetworkTransaction* trans3(new HttpNetworkTransaction(helper.session()));
1129
1130 TestCompletionCallback callback1;
1131 TestCompletionCallback callback2;
1132 KillerCallback callback3(trans3);
1133
1134 HttpRequestInfo httpreq1 = CreateGetRequest();
1135 HttpRequestInfo httpreq2 = CreateGetRequest();
1136 HttpRequestInfo httpreq3 = CreateGetRequest();
1137
1138 out.rv = trans1.Start(&httpreq1, &callback1, log);
1139 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1140 // run transaction 1 through quickly to force a read of our SETTINGS
1141 // frame
1142 out.rv = callback1.WaitForResult();
1143 ASSERT_EQ(OK, out.rv);
1144
1145 out.rv = trans2.Start(&httpreq2, &callback2, log);
1146 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1147 out.rv = trans3->Start(&httpreq3, &callback3, log);
1148 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1149 out.rv = callback3.WaitForResult();
1150 ASSERT_EQ(ERR_ABORTED, out.rv);
1151
1152 EXPECT_EQ(6U, data->read_index());
1153
1154 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
1155 ASSERT_TRUE(response1 != NULL);
1156 EXPECT_TRUE(response1->headers != NULL);
1157 EXPECT_TRUE(response1->was_fetched_via_spdy);
1158 out.status_line = response1->headers->GetStatusLine();
1159 out.response_info = *response1;
1160 out.rv = ReadTransaction(&trans1, &out.response_data);
1161 EXPECT_EQ(OK, out.rv);
1162
1163 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
1164 ASSERT_TRUE(response2 != NULL);
1165 out.status_line = response2->headers->GetStatusLine();
1166 out.response_info = *response2;
1167 out.rv = ReadTransaction(&trans2, &out.response_data);
1168 EXPECT_EQ(ERR_CONNECTION_RESET, out.rv);
1169
1170 helper.VerifyDataConsumed();
[email protected]2bd93022010-07-17 00:58:441171}
1172
[email protected]d8ef27b2010-08-06 17:34:391173// Test that a simple PUT request works.
1174TEST_P(SpdyNetworkTransactionTest, Put) {
1175 // Setup the request
1176 HttpRequestInfo request;
1177 request.method = "PUT";
1178 request.url = GURL("http://www.google.com/");
1179
1180 const SpdyHeaderInfo kSynStartHeader = {
1181 spdy::SYN_STREAM, // Kind = Syn
1182 1, // Stream ID
1183 0, // Associated stream ID
1184 net::ConvertRequestPriorityToSpdyPriority(LOWEST), // Priority
1185 spdy::CONTROL_FLAG_FIN, // Control Flags
1186 false, // Compressed
1187 spdy::INVALID, // Status
1188 NULL, // Data
1189 0, // Length
1190 spdy::DATA_FLAG_NONE // Data Flags
1191 };
1192 const char* const kPutHeaders[] = {
1193 "method", "PUT",
1194 "url", "/",
1195 "host", "www.google.com",
1196 "scheme", "http",
1197 "version", "HTTP/1.1",
1198 "content-length", "0"
1199 };
1200 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPacket(kSynStartHeader, NULL, 0,
1201 kPutHeaders, arraysize(kPutHeaders)/2));
1202 MockWrite writes[] = {
1203 CreateMockWrite(*req)
1204 };
1205
1206 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1207 const SpdyHeaderInfo kSynReplyHeader = {
1208 spdy::SYN_REPLY, // Kind = SynReply
1209 1, // Stream ID
1210 0, // Associated stream ID
1211 net::ConvertRequestPriorityToSpdyPriority(LOWEST), // Priority
1212 spdy::CONTROL_FLAG_NONE, // Control Flags
1213 false, // Compressed
1214 spdy::INVALID, // Status
1215 NULL, // Data
1216 0, // Length
1217 spdy::DATA_FLAG_NONE // Data Flags
1218 };
1219 static const char* const kStandardGetHeaders[] = {
1220 "status", "200",
1221 "version", "HTTP/1.1"
1222 "content-length", "1234"
1223 };
1224 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPacket(kSynReplyHeader,
1225 NULL, 0, kStandardGetHeaders, arraysize(kStandardGetHeaders)/2));
1226 MockRead reads[] = {
1227 CreateMockRead(*resp),
1228 CreateMockRead(*body),
1229 MockRead(true, 0, 0) // EOF
1230 };
1231
1232 scoped_refptr<DelayedSocketData> data(
1233 new DelayedSocketData(1, reads, arraysize(reads),
1234 writes, arraysize(writes)));
1235 NormalSpdyTransactionHelper helper(request,
1236 BoundNetLog(), GetParam());
1237 helper.RunToCompletion(data.get());
1238 TransactionHelperResult out = helper.output();
1239
1240 EXPECT_EQ(OK, out.rv);
1241 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1242}
1243
1244// Test that a simple HEAD request works.
1245TEST_P(SpdyNetworkTransactionTest, Head) {
1246 // Setup the request
1247 HttpRequestInfo request;
1248 request.method = "HEAD";
1249 request.url = GURL("http://www.google.com/");
1250
1251 const SpdyHeaderInfo kSynStartHeader = {
1252 spdy::SYN_STREAM, // Kind = Syn
1253 1, // Stream ID
1254 0, // Associated stream ID
1255 net::ConvertRequestPriorityToSpdyPriority(LOWEST), // Priority
1256 spdy::CONTROL_FLAG_FIN, // Control Flags
1257 false, // Compressed
1258 spdy::INVALID, // Status
1259 NULL, // Data
1260 0, // Length
1261 spdy::DATA_FLAG_NONE // Data Flags
1262 };
1263 const char* const kHeadHeaders[] = {
1264 "method", "HEAD",
1265 "url", "/",
1266 "host", "www.google.com",
1267 "scheme", "http",
1268 "version", "HTTP/1.1",
1269 "content-length", "0"
1270 };
1271 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPacket(kSynStartHeader, NULL, 0,
1272 kHeadHeaders, arraysize(kHeadHeaders)/2));
1273 MockWrite writes[] = {
1274 CreateMockWrite(*req)
1275 };
1276
1277 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1278 const SpdyHeaderInfo kSynReplyHeader = {
1279 spdy::SYN_REPLY, // Kind = SynReply
1280 1, // Stream ID
1281 0, // Associated stream ID
1282 net::ConvertRequestPriorityToSpdyPriority(LOWEST), // Priority
1283 spdy::CONTROL_FLAG_NONE, // Control Flags
1284 false, // Compressed
1285 spdy::INVALID, // Status
1286 NULL, // Data
1287 0, // Length
1288 spdy::DATA_FLAG_NONE // Data Flags
1289 };
1290 static const char* const kStandardGetHeaders[] = {
1291 "status", "200",
1292 "version", "HTTP/1.1"
1293 "content-length", "1234"
1294 };
1295 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPacket(kSynReplyHeader,
1296 NULL, 0, kStandardGetHeaders, arraysize(kStandardGetHeaders)/2));
1297 MockRead reads[] = {
1298 CreateMockRead(*resp),
1299 CreateMockRead(*body),
1300 MockRead(true, 0, 0) // EOF
1301 };
1302
1303 scoped_refptr<DelayedSocketData> data(
1304 new DelayedSocketData(1, reads, arraysize(reads),
1305 writes, arraysize(writes)));
1306 NormalSpdyTransactionHelper helper(request,
1307 BoundNetLog(), GetParam());
1308 helper.RunToCompletion(data.get());
1309 TransactionHelperResult out = helper.output();
1310
1311 EXPECT_EQ(OK, out.rv);
1312 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1313}
1314
[email protected]72552f02009-10-28 15:25:011315// Test that a simple POST works.
[email protected]9e9e842e2010-07-23 23:09:151316TEST_P(SpdyNetworkTransactionTest, Post) {
[email protected]310240592010-08-05 21:04:191317 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(kUploadDataSize, NULL, 0));
[email protected]2bd93022010-07-17 00:58:441318 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]ff57bb82009-11-12 06:52:141319 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:131320 CreateMockWrite(*req),
1321 CreateMockWrite(*body), // POST upload frame
[email protected]ff57bb82009-11-12 06:52:141322 };
[email protected]72552f02009-10-28 15:25:011323
[email protected]a4aeaf42010-06-30 19:57:281324 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
[email protected]ff57bb82009-11-12 06:52:141325 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:131326 CreateMockRead(*resp),
1327 CreateMockRead(*body),
[email protected]72552f02009-10-28 15:25:011328 MockRead(true, 0, 0) // EOF
[email protected]aea80602009-09-18 00:55:081329 };
1330
[email protected]bf2491a92009-11-29 16:39:481331 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:391332 new DelayedSocketData(2, reads, arraysize(reads),
1333 writes, arraysize(writes)));
[email protected]310240592010-08-05 21:04:191334 NormalSpdyTransactionHelper helper(CreatePostRequest(),
[email protected]9e9e842e2010-07-23 23:09:151335 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:471336 helper.RunToCompletion(data.get());
1337 TransactionHelperResult out = helper.output();
[email protected]aea80602009-09-18 00:55:081338 EXPECT_EQ(OK, out.rv);
1339 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1340 EXPECT_EQ("hello!", out.response_data);
1341}
1342
[email protected]a33cad2b62010-07-30 22:24:391343// Test that a POST without any post data works.
1344TEST_P(SpdyNetworkTransactionTest, NullPost) {
1345 // Setup the request
1346 HttpRequestInfo request;
1347 request.method = "POST";
1348 request.url = GURL("http://www.google.com/");
1349 // Create an empty UploadData.
1350 request.upload_data = NULL;
1351
1352 // When request.upload_data is NULL for post, content-length is
1353 // expected to be 0.
1354 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(0, NULL, 0));
1355 // Set the FIN bit since there will be no body.
1356 req->set_flags(spdy::CONTROL_FLAG_FIN);
1357 MockWrite writes[] = {
1358 CreateMockWrite(*req),
1359 };
1360
1361 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
1362 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1363 MockRead reads[] = {
1364 CreateMockRead(*resp),
1365 CreateMockRead(*body),
1366 MockRead(true, 0, 0) // EOF
1367 };
1368
1369 scoped_refptr<DelayedSocketData> data(
1370 new DelayedSocketData(1, reads, arraysize(reads),
1371 writes, arraysize(writes)));
1372
1373 NormalSpdyTransactionHelper helper(request,
1374 BoundNetLog(), GetParam());
1375 helper.RunToCompletion(data.get());
1376 TransactionHelperResult out = helper.output();
1377 EXPECT_EQ(OK, out.rv);
1378 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1379 EXPECT_EQ("hello!", out.response_data);
1380}
1381
[email protected]edd3b0a52009-11-24 18:56:361382// Test that a simple POST works.
[email protected]9e9e842e2010-07-23 23:09:151383TEST_P(SpdyNetworkTransactionTest, EmptyPost) {
[email protected]edd3b0a52009-11-24 18:56:361384 // Setup the request
1385 HttpRequestInfo request;
1386 request.method = "POST";
1387 request.url = GURL("http://www.google.com/");
1388 // Create an empty UploadData.
1389 request.upload_data = new UploadData();
1390
[email protected]a33cad2b62010-07-30 22:24:391391 // Http POST Content-Length is using UploadDataStream::size().
1392 // It is the same as request.upload_data->GetContentLength().
[email protected]219ba8cb2010-07-31 04:51:461393 scoped_ptr<UploadDataStream> stream(UploadDataStream::Create(
1394 request.upload_data, NULL));
1395 ASSERT_EQ(request.upload_data->GetContentLength(), stream->size());
[email protected]a33cad2b62010-07-30 22:24:391396
1397 scoped_ptr<spdy::SpdyFrame>
1398 req(ConstructSpdyPost(request.upload_data->GetContentLength(), NULL, 0));
[email protected]a4aeaf42010-06-30 19:57:281399 // Set the FIN bit since there will be no body.
1400 req->set_flags(spdy::CONTROL_FLAG_FIN);
[email protected]edd3b0a52009-11-24 18:56:361401 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:131402 CreateMockWrite(*req),
[email protected]edd3b0a52009-11-24 18:56:361403 };
1404
[email protected]a4aeaf42010-06-30 19:57:281405 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
[email protected]2bd93022010-07-17 00:58:441406 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]edd3b0a52009-11-24 18:56:361407 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:131408 CreateMockRead(*resp),
1409 CreateMockRead(*body),
[email protected]edd3b0a52009-11-24 18:56:361410 MockRead(true, 0, 0) // EOF
1411 };
1412
[email protected]bf2491a92009-11-29 16:39:481413 scoped_refptr<DelayedSocketData> data(
[email protected]3f662f12010-03-25 19:56:121414 new DelayedSocketData(1, reads, arraysize(reads),
1415 writes, arraysize(writes)));
[email protected]bf2491a92009-11-29 16:39:481416
[email protected]3caf5542010-07-16 15:19:471417 NormalSpdyTransactionHelper helper(request,
[email protected]9e9e842e2010-07-23 23:09:151418 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:471419 helper.RunToCompletion(data.get());
1420 TransactionHelperResult out = helper.output();
[email protected]edd3b0a52009-11-24 18:56:361421 EXPECT_EQ(OK, out.rv);
1422 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1423 EXPECT_EQ("hello!", out.response_data);
1424}
1425
[email protected]a5566f9702010-05-05 22:25:431426// While we're doing a post, the server sends back a SYN_REPLY.
[email protected]9e9e842e2010-07-23 23:09:151427TEST_P(SpdyNetworkTransactionTest, PostWithEarlySynReply) {
[email protected]a4aeaf42010-06-30 19:57:281428 static const char upload[] = { "hello!" };
[email protected]a5566f9702010-05-05 22:25:431429
1430 // Setup the request
1431 HttpRequestInfo request;
1432 request.method = "POST";
1433 request.url = GURL("http://www.google.com/");
1434 request.upload_data = new UploadData();
1435 request.upload_data->AppendBytes(upload, sizeof(upload));
1436
[email protected]a33cad2b62010-07-30 22:24:391437 // Http POST Content-Length is using UploadDataStream::size().
1438 // It is the same as request.upload_data->GetContentLength().
[email protected]219ba8cb2010-07-31 04:51:461439 scoped_ptr<UploadDataStream> stream(UploadDataStream::Create(
1440 request.upload_data, NULL));
1441 ASSERT_EQ(request.upload_data->GetContentLength(), stream->size());
[email protected]82918cc2010-08-25 17:24:501442 scoped_ptr<spdy::SpdyFrame> stream_reply(ConstructSpdyPostSynReply(NULL, 0));
1443 scoped_ptr<spdy::SpdyFrame> stream_body(ConstructSpdyBodyFrame(1, true));
[email protected]a5566f9702010-05-05 22:25:431444 MockRead reads[] = {
[email protected]82918cc2010-08-25 17:24:501445 CreateMockRead(*stream_reply, 2),
1446 CreateMockRead(*stream_body, 3),
[email protected]a5566f9702010-05-05 22:25:431447 MockRead(false, 0, 0) // EOF
1448 };
1449
1450 scoped_refptr<DelayedSocketData> data(
[email protected]8e6441ca2010-08-19 05:56:381451 new DelayedSocketData(0, reads, arraysize(reads), NULL, 0));
[email protected]3caf5542010-07-16 15:19:471452 NormalSpdyTransactionHelper helper(request,
[email protected]9e9e842e2010-07-23 23:09:151453 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:471454 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:581455 helper.AddData(data.get());
[email protected]3caf5542010-07-16 15:19:471456 helper.RunDefaultTest();
[email protected]310240592010-08-05 21:04:191457 helper.VerifyDataConsumed();
1458
[email protected]3caf5542010-07-16 15:19:471459 TransactionHelperResult out = helper.output();
[email protected]82918cc2010-08-25 17:24:501460 EXPECT_EQ(ERR_SYN_REPLY_NOT_RECEIVED, out.rv);
[email protected]a5566f9702010-05-05 22:25:431461}
1462
[email protected]f9a26d72010-08-03 18:07:131463// The client upon cancellation tries to send a RST_STREAM frame. The mock
1464// socket causes the TCP write to return zero. This test checks that the client
1465// tries to queue up the RST_STREAM frame again.
[email protected]3b7828432010-08-18 18:33:271466TEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
[email protected]f9a26d72010-08-03 18:07:131467 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1468 scoped_ptr<spdy::SpdyFrame> rst(
1469 ConstructSpdyRstStream(1, spdy::CANCEL));
1470 MockWrite writes[] = {
[email protected]3b7828432010-08-18 18:33:271471 CreateMockWrite(*req.get(), 0, false),
1472 MockWrite(false, 0, 0, 2),
1473 CreateMockWrite(*rst.get(), 3, false),
[email protected]f9a26d72010-08-03 18:07:131474 };
1475
1476 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1477 MockRead reads[] = {
[email protected]5e6609582010-10-05 18:14:201478 CreateMockRead(*resp.get(), 1, true),
1479 MockRead(true, 0, 0, 4) // EOF
[email protected]f9a26d72010-08-03 18:07:131480 };
1481
[email protected]3b7828432010-08-18 18:33:271482 scoped_refptr<DeterministicSocketData> data(
1483 new DeterministicSocketData(reads, arraysize(reads),
[email protected]f9a26d72010-08-03 18:07:131484 writes, arraysize(writes)));
1485 NormalSpdyTransactionHelper helper(CreateGetRequest(),
1486 BoundNetLog(), GetParam());
[email protected]3b7828432010-08-18 18:33:271487 helper.SetDeterministic();
[email protected]f9a26d72010-08-03 18:07:131488 helper.RunPreTestSetup();
[email protected]3b7828432010-08-18 18:33:271489 helper.AddDeterministicData(data.get());
[email protected]f9a26d72010-08-03 18:07:131490 HttpNetworkTransaction* trans = helper.trans();
1491
1492 TestCompletionCallback callback;
1493 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
1494 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3b7828432010-08-18 18:33:271495
1496 data->SetStop(2);
1497 data->Run();
[email protected]f9a26d72010-08-03 18:07:131498 helper.ResetTrans();
[email protected]3b7828432010-08-18 18:33:271499 data->SetStop(20);
1500 data->Run();
1501
[email protected]f9a26d72010-08-03 18:07:131502 helper.VerifyDataConsumed();
1503}
1504
[email protected]93300672009-10-24 13:22:511505// Test that the transaction doesn't crash when we don't have a reply.
[email protected]9e9e842e2010-07-23 23:09:151506TEST_P(SpdyNetworkTransactionTest, ResponseWithoutSynReply) {
[email protected]2bd93022010-07-17 00:58:441507 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]ff57bb82009-11-12 06:52:141508 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:131509 CreateMockRead(*body),
[email protected]72552f02009-10-28 15:25:011510 MockRead(true, 0, 0) // EOF
[email protected]93300672009-10-24 13:22:511511 };
1512
[email protected]bf2491a92009-11-29 16:39:481513 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:391514 new DelayedSocketData(1, reads, arraysize(reads), NULL, 0));
[email protected]3caf5542010-07-16 15:19:471515 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:151516 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:471517 helper.RunToCompletion(data.get());
1518 TransactionHelperResult out = helper.output();
[email protected]93300672009-10-24 13:22:511519 EXPECT_EQ(ERR_SYN_REPLY_NOT_RECEIVED, out.rv);
1520}
1521
[email protected]d30022352010-06-24 19:17:581522// Test that the transaction doesn't crash when we get two replies on the same
1523// stream ID. See http://crbug.com/45639.
[email protected]9e9e842e2010-07-23 23:09:151524TEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
[email protected]2bd93022010-07-17 00:58:441525 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:131526 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]d30022352010-06-24 19:17:581527
[email protected]2bd93022010-07-17 00:58:441528 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1529 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]d30022352010-06-24 19:17:581530 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:131531 CreateMockRead(*resp),
1532 CreateMockRead(*resp),
1533 CreateMockRead(*body),
[email protected]d30022352010-06-24 19:17:581534 MockRead(true, 0, 0) // EOF
1535 };
1536
[email protected]d30022352010-06-24 19:17:581537 scoped_refptr<DelayedSocketData> data(
1538 new DelayedSocketData(1, reads, arraysize(reads),
1539 writes, arraysize(writes)));
[email protected]d30022352010-06-24 19:17:581540
[email protected]3caf5542010-07-16 15:19:471541 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:151542 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:471543 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:581544 helper.AddData(data.get());
[email protected]3caf5542010-07-16 15:19:471545
1546 HttpNetworkTransaction* trans = helper.trans();
[email protected]d30022352010-06-24 19:17:581547
1548 TestCompletionCallback callback;
[email protected]3caf5542010-07-16 15:19:471549 int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
[email protected]d30022352010-06-24 19:17:581550 EXPECT_EQ(ERR_IO_PENDING, rv);
1551 rv = callback.WaitForResult();
1552 EXPECT_EQ(OK, rv);
1553
1554 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a5c493b92010-08-06 23:04:291555 ASSERT_TRUE(response != NULL);
[email protected]d30022352010-06-24 19:17:581556 EXPECT_TRUE(response->headers != NULL);
1557 EXPECT_TRUE(response->was_fetched_via_spdy);
1558 std::string response_data;
[email protected]3caf5542010-07-16 15:19:471559 rv = ReadTransaction(trans, &response_data);
[email protected]d30022352010-06-24 19:17:581560 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
[email protected]3caf5542010-07-16 15:19:471561
1562 helper.VerifyDataConsumed();
[email protected]d30022352010-06-24 19:17:581563}
1564
[email protected]7349c6b12010-07-22 02:29:161565// Test that sent data frames and received WINDOW_UPDATE frames change
1566// the send_window_size_ correctly.
[email protected]6abf5372010-08-17 15:44:251567
1568// WINDOW_UPDATE is different than most other frames in that it can arrive
1569// while the client is still sending the request body. In order to enforce
1570// this scenario, we feed a couple of dummy frames and give a delay of 0 to
1571// socket data provider, so that initial read that is done as soon as the
1572// stream is created, succeeds and schedules another read. This way reads
1573// and writes are interleaved; after doing a full frame write, SpdyStream
1574// will break out of DoLoop and will read and process a WINDOW_UPDATE.
1575// Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
1576// since request has not been completely written, therefore we feed
1577// enough number of WINDOW_UPDATEs to finish the first read and cause a
1578// write, leading to a complete write of request body; after that we send
1579// a reply with a body, to cause a graceful shutdown.
1580
1581// TODO(agayev): develop a socket data provider where both, reads and
[email protected]450c5022010-08-26 02:38:281582// writes are ordered so that writing tests like these are easy and rewrite
1583// all these tests using it. Right now we are working around the
1584// limitations as described above and it's not deterministic, tests may
1585// fail under specific circumstances.
1586TEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) {
1587 SpdySession::set_flow_control(true);
[email protected]5af3c572010-07-20 14:16:271588
[email protected]6abf5372010-08-17 15:44:251589 static int kFrameCount = 2;
1590 scoped_ptr<std::string> content(
1591 new std::string(kMaxSpdyFrameChunkSize, 'a'));
1592 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(
1593 kMaxSpdyFrameChunkSize * kFrameCount, NULL, 0));
1594 scoped_ptr<spdy::SpdyFrame> body(
1595 ConstructSpdyBodyFrame(1, content->c_str(), content->size(), false));
1596 scoped_ptr<spdy::SpdyFrame> body_end(
1597 ConstructSpdyBodyFrame(1, content->c_str(), content->size(), true));
1598
[email protected]5af3c572010-07-20 14:16:271599 MockWrite writes[] = {
1600 CreateMockWrite(*req),
1601 CreateMockWrite(*body),
[email protected]6abf5372010-08-17 15:44:251602 CreateMockWrite(*body_end),
[email protected]5af3c572010-07-20 14:16:271603 };
1604
[email protected]5af3c572010-07-20 14:16:271605 static const int kDeltaWindowSize = 0xff;
[email protected]6abf5372010-08-17 15:44:251606 static const int kDeltaCount = 4;
[email protected]5af3c572010-07-20 14:16:271607 scoped_ptr<spdy::SpdyFrame> window_update(
1608 ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
[email protected]6abf5372010-08-17 15:44:251609 scoped_ptr<spdy::SpdyFrame> window_update_dummy(
1610 ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
1611 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
[email protected]5af3c572010-07-20 14:16:271612 MockRead reads[] = {
[email protected]6abf5372010-08-17 15:44:251613 CreateMockRead(*window_update_dummy),
1614 CreateMockRead(*window_update_dummy),
[email protected]450c5022010-08-26 02:38:281615 CreateMockRead(*window_update_dummy),
[email protected]6abf5372010-08-17 15:44:251616 CreateMockRead(*window_update), // Four updates, therefore window
1617 CreateMockRead(*window_update), // size should increase by
1618 CreateMockRead(*window_update), // kDeltaWindowSize * 4
[email protected]5af3c572010-07-20 14:16:271619 CreateMockRead(*window_update),
[email protected]6abf5372010-08-17 15:44:251620 CreateMockRead(*resp),
1621 CreateMockRead(*body_end),
[email protected]5af3c572010-07-20 14:16:271622 MockRead(true, 0, 0) // EOF
1623 };
1624
1625 scoped_refptr<DelayedSocketData> data(
[email protected]6abf5372010-08-17 15:44:251626 new DelayedSocketData(0, reads, arraysize(reads),
[email protected]5af3c572010-07-20 14:16:271627 writes, arraysize(writes)));
[email protected]5af3c572010-07-20 14:16:271628
[email protected]6abf5372010-08-17 15:44:251629 // Setup the request
1630 HttpRequestInfo request;
1631 request.method = "POST";
1632 request.url = GURL(kDefaultURL);
1633 request.upload_data = new UploadData();
1634 for (int i = 0; i < kFrameCount; ++i)
1635 request.upload_data->AppendBytes(content->c_str(), content->size());
1636
1637 NormalSpdyTransactionHelper helper(request, BoundNetLog(), GetParam());
[email protected]310240592010-08-05 21:04:191638 helper.AddData(data.get());
1639 helper.RunPreTestSetup();
1640
1641 HttpNetworkTransaction* trans = helper.trans();
[email protected]5af3c572010-07-20 14:16:271642
1643 TestCompletionCallback callback;
[email protected]310240592010-08-05 21:04:191644 int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
[email protected]5af3c572010-07-20 14:16:271645
1646 EXPECT_EQ(ERR_IO_PENDING, rv);
1647 rv = callback.WaitForResult();
1648 EXPECT_EQ(OK, rv);
1649
[email protected]4d4a5162010-09-21 22:44:041650 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
[email protected]6abf5372010-08-17 15:44:251651 ASSERT_TRUE(stream != NULL);
1652 ASSERT_TRUE(stream->stream() != NULL);
1653 EXPECT_EQ(spdy::kInitialWindowSize +
1654 kDeltaWindowSize * kDeltaCount -
1655 kMaxSpdyFrameChunkSize * kFrameCount,
1656 stream->stream()->send_window_size());
[email protected]310240592010-08-05 21:04:191657 helper.VerifyDataConsumed();
[email protected]450c5022010-08-26 02:38:281658 SpdySession::set_flow_control(false);
1659}
1660
1661// Test that received data frames and sent WINDOW_UPDATE frames change
1662// the recv_window_size_ correctly.
1663TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) {
1664 SpdySession::set_flow_control(true);
1665
1666 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1667 scoped_ptr<spdy::SpdyFrame> window_update(
1668 ConstructSpdyWindowUpdate(1, kUploadDataSize));
1669
1670 MockWrite writes[] = {
1671 CreateMockWrite(*req),
1672 CreateMockWrite(*window_update),
1673 };
1674
1675 scoped_ptr<spdy::SpdyFrame> resp(
1676 ConstructSpdyGetSynReply(NULL, 0, 1));
1677 scoped_ptr<spdy::SpdyFrame> body_no_fin(
1678 ConstructSpdyBodyFrame(1, false));
1679 scoped_ptr<spdy::SpdyFrame> body_fin(
1680 ConstructSpdyBodyFrame(1, NULL, 0, true));
1681 MockRead reads[] = {
1682 CreateMockRead(*resp),
1683 CreateMockRead(*body_no_fin),
1684 MockRead(true, ERR_IO_PENDING, 0), // Force a pause
1685 CreateMockRead(*body_fin),
1686 MockRead(true, ERR_IO_PENDING, 0), // Force a pause
1687 MockRead(true, 0, 0) // EOF
1688 };
1689
1690 scoped_refptr<DelayedSocketData> data(
1691 new DelayedSocketData(1, reads, arraysize(reads),
1692 writes, arraysize(writes)));
1693
1694 NormalSpdyTransactionHelper helper(CreateGetRequest(),
1695 BoundNetLog(), GetParam());
1696 helper.AddData(data.get());
1697 helper.RunPreTestSetup();
1698 HttpNetworkTransaction* trans = helper.trans();
1699
1700 TestCompletionCallback callback;
1701 int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
1702
1703 EXPECT_EQ(ERR_IO_PENDING, rv);
1704 rv = callback.WaitForResult();
1705 EXPECT_EQ(OK, rv);
1706
1707 SpdyHttpStream* stream =
[email protected]4d4a5162010-09-21 22:44:041708 static_cast<SpdyHttpStream*>(trans->stream_.get());
[email protected]450c5022010-08-26 02:38:281709 ASSERT_TRUE(stream != NULL);
1710 ASSERT_TRUE(stream->stream() != NULL);
1711
1712 EXPECT_EQ(spdy::kInitialWindowSize - kUploadDataSize,
1713 stream->stream()->recv_window_size());
1714
1715 const HttpResponseInfo* response = trans->GetResponseInfo();
1716 ASSERT_TRUE(response != NULL);
1717 ASSERT_TRUE(response->headers != NULL);
1718 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1719 EXPECT_TRUE(response->was_fetched_via_spdy);
1720
1721 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
1722 // size increased to default.
[email protected]ad8e04a2010-11-01 04:16:271723 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kUploadDataSize));
[email protected]450c5022010-08-26 02:38:281724 rv = trans->Read(buf, kUploadDataSize, NULL);
1725 EXPECT_EQ(kUploadDataSize, rv);
1726 std::string content(buf->data(), buf->data()+kUploadDataSize);
1727 EXPECT_STREQ(kUploadData, content.c_str());
1728
1729 // Schedule the reading of empty data frame with FIN
1730 data->CompleteRead();
1731
1732 // Force write of WINDOW_UPDATE which was scheduled during the above
1733 // read.
1734 MessageLoop::current()->RunAllPending();
1735
1736 // Read EOF.
1737 data->CompleteRead();
1738
1739 helper.VerifyDataConsumed();
1740 SpdySession::set_flow_control(false);
[email protected]5af3c572010-07-20 14:16:271741}
1742
[email protected]6abf5372010-08-17 15:44:251743// Test that WINDOW_UPDATE frame causing overflow is handled correctly. We
1744// use the same trick as in the above test to enforce our scenario.
[email protected]9e9e842e2010-07-23 23:09:151745TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
[email protected]450c5022010-08-26 02:38:281746 SpdySession::set_flow_control(true);
[email protected]5af3c572010-07-20 14:16:271747
[email protected]310240592010-08-05 21:04:191748 // number of full frames we hope to write (but will not, used to
1749 // set content-length header correctly)
1750 static int kFrameCount = 3;
[email protected]5af3c572010-07-20 14:16:271751
[email protected]310240592010-08-05 21:04:191752 scoped_ptr<std::string> content(
1753 new std::string(kMaxSpdyFrameChunkSize, 'a'));
[email protected]310240592010-08-05 21:04:191754 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(
1755 kMaxSpdyFrameChunkSize * kFrameCount, NULL, 0));
[email protected]310240592010-08-05 21:04:191756 scoped_ptr<spdy::SpdyFrame> body(
1757 ConstructSpdyBodyFrame(1, content->c_str(), content->size(), false));
[email protected]5af3c572010-07-20 14:16:271758 scoped_ptr<spdy::SpdyFrame> rst(
1759 ConstructSpdyRstStream(1, spdy::FLOW_CONTROL_ERROR));
[email protected]310240592010-08-05 21:04:191760
1761 // We're not going to write a data frame with FIN, we'll receive a bad
1762 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
[email protected]5af3c572010-07-20 14:16:271763 MockWrite writes[] = {
1764 CreateMockWrite(*req),
1765 CreateMockWrite(*body),
1766 CreateMockWrite(*rst),
1767 };
1768
[email protected]a33cad2b62010-07-30 22:24:391769 static const int kDeltaWindowSize = 0x7fffffff; // cause an overflow
[email protected]5af3c572010-07-20 14:16:271770 scoped_ptr<spdy::SpdyFrame> window_update(
1771 ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
[email protected]310240592010-08-05 21:04:191772 scoped_ptr<spdy::SpdyFrame> window_update2(
1773 ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
[email protected]5af3c572010-07-20 14:16:271774 scoped_ptr<spdy::SpdyFrame> reply(ConstructSpdyPostSynReply(NULL, 0));
[email protected]310240592010-08-05 21:04:191775
[email protected]5af3c572010-07-20 14:16:271776 MockRead reads[] = {
[email protected]310240592010-08-05 21:04:191777 CreateMockRead(*window_update2),
1778 CreateMockRead(*window_update2),
[email protected]5af3c572010-07-20 14:16:271779 CreateMockRead(*window_update),
[email protected]310240592010-08-05 21:04:191780 CreateMockRead(*window_update),
1781 CreateMockRead(*window_update),
[email protected]8e6441ca2010-08-19 05:56:381782 MockRead(true, ERR_IO_PENDING, 0), // Wait for the RST to be written.
[email protected]5af3c572010-07-20 14:16:271783 MockRead(true, 0, 0) // EOF
1784 };
1785
1786 scoped_refptr<DelayedSocketData> data(
[email protected]310240592010-08-05 21:04:191787 new DelayedSocketData(0, reads, arraysize(reads),
[email protected]5af3c572010-07-20 14:16:271788 writes, arraysize(writes)));
[email protected]5af3c572010-07-20 14:16:271789
[email protected]310240592010-08-05 21:04:191790 // Setup the request
1791 HttpRequestInfo request;
1792 request.method = "POST";
1793 request.url = GURL("http://www.google.com/");
1794 request.upload_data = new UploadData();
1795 for (int i = 0; i < kFrameCount; ++i)
1796 request.upload_data->AppendBytes(content->c_str(), content->size());
1797
1798 NormalSpdyTransactionHelper helper(request,
1799 BoundNetLog(), GetParam());
1800 helper.AddData(data.get());
1801 helper.RunPreTestSetup();
1802
1803 HttpNetworkTransaction* trans = helper.trans();
[email protected]5af3c572010-07-20 14:16:271804
1805 TestCompletionCallback callback;
[email protected]310240592010-08-05 21:04:191806 int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
[email protected]5af3c572010-07-20 14:16:271807
1808 EXPECT_EQ(ERR_IO_PENDING, rv);
1809 rv = callback.WaitForResult();
1810 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
1811
[email protected]8e6441ca2010-08-19 05:56:381812 data->CompleteRead();
1813
[email protected]310240592010-08-05 21:04:191814 ASSERT_TRUE(helper.session() != NULL);
1815 ASSERT_TRUE(helper.session()->spdy_session_pool() != NULL);
[email protected]a01ea222010-08-19 16:50:531816 helper.session()->spdy_session_pool()->CloseAllSessions();
[email protected]310240592010-08-05 21:04:191817 helper.VerifyDataConsumed();
[email protected]5af3c572010-07-20 14:16:271818
[email protected]450c5022010-08-26 02:38:281819 SpdySession::set_flow_control(false);
[email protected]310240592010-08-05 21:04:191820}
1821
1822// Test that after hitting a send window size of 0, the write process
1823// stalls and upon receiving WINDOW_UPDATE frame write resumes.
[email protected]6abf5372010-08-17 15:44:251824
[email protected]310240592010-08-05 21:04:191825// This test constructs a POST request followed by enough data frames
1826// containing 'a' that would make the window size 0, followed by another
1827// data frame containing default content (which is "hello!") and this frame
1828// also contains a FIN flag. DelayedSocketData is used to enforce all
1829// writes go through before a read could happen. However, the last frame
1830// ("hello!") is not supposed to go through since by the time its turn
1831// arrives, window size is 0. At this point MessageLoop::Run() called via
1832// callback would block. Therefore we call MessageLoop::RunAllPending()
1833// which returns after performing all possible writes. We use DCHECKS to
1834// ensure that last data frame is still there and stream has stalled.
1835// After that, next read is artifically enforced, which causes a
1836// WINDOW_UPDATE to be read and I/O process resumes.
1837TEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) {
[email protected]450c5022010-08-26 02:38:281838 SpdySession::set_flow_control(true);
[email protected]310240592010-08-05 21:04:191839
1840 // Number of frames we need to send to zero out the window size: data
1841 // frames plus SYN_STREAM plus the last data frame; also we need another
1842 // data frame that we will send once the WINDOW_UPDATE is received,
1843 // therefore +3.
1844 size_t nwrites = spdy::kInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
1845
1846 // Calculate last frame's size; 0 size data frame is legal.
1847 size_t last_frame_size = spdy::kInitialWindowSize % kMaxSpdyFrameChunkSize;
1848
1849 // Construct content for a data frame of maximum size.
1850 scoped_ptr<std::string> content(
1851 new std::string(kMaxSpdyFrameChunkSize, 'a'));
1852
1853 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(
1854 spdy::kInitialWindowSize + kUploadDataSize, NULL, 0));
1855
1856 // Full frames.
1857 scoped_ptr<spdy::SpdyFrame> body1(
1858 ConstructSpdyBodyFrame(1, content->c_str(), content->size(), false));
1859
1860 // Last frame to zero out the window size.
1861 scoped_ptr<spdy::SpdyFrame> body2(
1862 ConstructSpdyBodyFrame(1, content->c_str(), last_frame_size, false));
1863
1864 // Data frame to be sent once WINDOW_UPDATE frame is received.
1865 scoped_ptr<spdy::SpdyFrame> body3(ConstructSpdyBodyFrame(1, true));
1866
1867 // Fill in mock writes.
1868 scoped_array<MockWrite> writes(new MockWrite[nwrites]);
1869 size_t i = 0;
1870 writes[i] = CreateMockWrite(*req);
1871 for (i = 1; i < nwrites-2; i++)
1872 writes[i] = CreateMockWrite(*body1);
1873 writes[i++] = CreateMockWrite(*body2);
1874 writes[i] = CreateMockWrite(*body3);
1875
[email protected]6abf5372010-08-17 15:44:251876 // Construct read frame, give enough space to upload the rest of the
[email protected]310240592010-08-05 21:04:191877 // data.
1878 scoped_ptr<spdy::SpdyFrame> window_update(
1879 ConstructSpdyWindowUpdate(1, kUploadDataSize));
1880 scoped_ptr<spdy::SpdyFrame> reply(ConstructSpdyPostSynReply(NULL, 0));
1881 MockRead reads[] = {
1882 CreateMockRead(*window_update),
1883 CreateMockRead(*window_update),
1884 CreateMockRead(*reply),
1885 CreateMockRead(*body2),
1886 CreateMockRead(*body3),
1887 MockRead(true, 0, 0) // EOF
1888 };
1889
1890 // Force all writes to happen before any read, last write will not
1891 // actually queue a frame, due to window size being 0.
1892 scoped_refptr<DelayedSocketData> data(
1893 new DelayedSocketData(nwrites, reads, arraysize(reads),
1894 writes.get(), nwrites));
1895
1896 HttpRequestInfo request;
1897 request.method = "POST";
1898 request.url = GURL("http://www.google.com/");
1899 request.upload_data = new UploadData();
1900 scoped_ptr<std::string> upload_data(
1901 new std::string(spdy::kInitialWindowSize, 'a'));
1902 upload_data->append(kUploadData, kUploadDataSize);
1903 request.upload_data->AppendBytes(upload_data->c_str(), upload_data->size());
1904 NormalSpdyTransactionHelper helper(request,
1905 BoundNetLog(), GetParam());
1906 helper.AddData(data.get());
1907 helper.RunPreTestSetup();
1908
1909 HttpNetworkTransaction* trans = helper.trans();
1910
1911 TestCompletionCallback callback;
1912 int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
1913 EXPECT_EQ(ERR_IO_PENDING, rv);
1914
1915 MessageLoop::current()->RunAllPending(); // Write as much as we can.
[email protected]6abf5372010-08-17 15:44:251916
[email protected]4d4a5162010-09-21 22:44:041917 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
[email protected]6abf5372010-08-17 15:44:251918 ASSERT_TRUE(stream != NULL);
1919 ASSERT_TRUE(stream->stream() != NULL);
1920 EXPECT_EQ(0, stream->stream()->send_window_size());
1921 EXPECT_FALSE(stream->request_body_stream_->eof());
[email protected]310240592010-08-05 21:04:191922
1923 data->ForceNextRead(); // Read in WINDOW_UPDATE frame.
1924 rv = callback.WaitForResult();
1925 helper.VerifyDataConsumed();
[email protected]7349c6b12010-07-22 02:29:161926
[email protected]450c5022010-08-26 02:38:281927 SpdySession::set_flow_control(false);
[email protected]5af3c572010-07-20 14:16:271928}
1929
[email protected]9e9e842e2010-07-23 23:09:151930TEST_P(SpdyNetworkTransactionTest, CancelledTransaction) {
[email protected]75f30cc22010-06-28 21:41:381931 // Construct the request.
[email protected]2bd93022010-07-17 00:58:441932 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]34437af82009-11-06 02:28:491933 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:131934 CreateMockWrite(*req),
[email protected]34437af82009-11-06 02:28:491935 };
1936
[email protected]2bd93022010-07-17 00:58:441937 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]34437af82009-11-06 02:28:491938 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:131939 CreateMockRead(*resp),
[email protected]34437af82009-11-06 02:28:491940 // This following read isn't used by the test, except during the
[email protected]955fc2e72010-02-08 20:37:301941 // RunAllPending() call at the end since the SpdySession survives the
[email protected]3caf5542010-07-16 15:19:471942 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
[email protected]34437af82009-11-06 02:28:491943 // MockRead will do here.
1944 MockRead(true, 0, 0) // EOF
1945 };
1946
[email protected]31a2bfe2010-02-09 08:03:391947 StaticSocketDataProvider data(reads, arraysize(reads),
1948 writes, arraysize(writes));
[email protected]3caf5542010-07-16 15:19:471949
1950 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:151951 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:471952 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:581953 helper.AddData(&data);
[email protected]3caf5542010-07-16 15:19:471954 HttpNetworkTransaction* trans = helper.trans();
[email protected]34437af82009-11-06 02:28:491955
1956 TestCompletionCallback callback;
[email protected]d3cee19d2010-06-22 18:42:181957 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
[email protected]34437af82009-11-06 02:28:491958 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3caf5542010-07-16 15:19:471959 helper.ResetTrans(); // Cancel the transaction.
[email protected]34437af82009-11-06 02:28:491960
[email protected]30c942b2010-07-21 16:59:591961 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]34437af82009-11-06 02:28:491962 // MockClientSocketFactory) are still alive.
1963 MessageLoop::current()->RunAllPending();
[email protected]3caf5542010-07-16 15:19:471964 helper.VerifyDataNotConsumed();
[email protected]34437af82009-11-06 02:28:491965}
[email protected]72552f02009-10-28 15:25:011966
[email protected]6c6ea172010-07-27 20:04:031967// Verify that the client sends a Rst Frame upon cancelling the stream.
[email protected]3b7828432010-08-18 18:33:271968TEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
[email protected]6c6ea172010-07-27 20:04:031969 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1970 scoped_ptr<spdy::SpdyFrame> rst(
1971 ConstructSpdyRstStream(1, spdy::CANCEL));
1972 MockWrite writes[] = {
[email protected]3b7828432010-08-18 18:33:271973 CreateMockWrite(*req, 0, false),
1974 CreateMockWrite(*rst, 2, false),
[email protected]6c6ea172010-07-27 20:04:031975 };
1976
1977 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1978 MockRead reads[] = {
[email protected]5e6609582010-10-05 18:14:201979 CreateMockRead(*resp, 1, true),
1980 MockRead(true, 0, 0, 3) // EOF
[email protected]6c6ea172010-07-27 20:04:031981 };
1982
[email protected]3b7828432010-08-18 18:33:271983 scoped_refptr<DeterministicSocketData> data(
1984 new DeterministicSocketData(reads, arraysize(reads),
[email protected]6c6ea172010-07-27 20:04:031985 writes, arraysize(writes)));
1986
1987 NormalSpdyTransactionHelper helper(CreateGetRequest(),
1988 BoundNetLog(),
1989 GetParam());
[email protected]3b7828432010-08-18 18:33:271990 helper.SetDeterministic();
[email protected]6c6ea172010-07-27 20:04:031991 helper.RunPreTestSetup();
[email protected]3b7828432010-08-18 18:33:271992 helper.AddDeterministicData(data.get());
[email protected]6c6ea172010-07-27 20:04:031993 HttpNetworkTransaction* trans = helper.trans();
1994
1995 TestCompletionCallback callback;
1996
1997 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
1998 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]6c6ea172010-07-27 20:04:031999
[email protected]3b7828432010-08-18 18:33:272000 data->SetStop(2);
2001 data->Run();
2002 helper.ResetTrans();
2003 data->SetStop(20);
2004 data->Run();
2005
[email protected]6c6ea172010-07-27 20:04:032006 helper.VerifyDataConsumed();
2007}
2008
[email protected]3caf5542010-07-16 15:19:472009class SpdyNetworkTransactionTest::StartTransactionCallback
2010 : public CallbackRunner< Tuple1<int> > {
[email protected]b278eb72010-07-09 20:17:002011 public:
2012 explicit StartTransactionCallback(
[email protected]19ec8a72010-08-23 03:38:232013 const scoped_refptr<HttpNetworkSession>& session,
[email protected]3caf5542010-07-16 15:19:472014 NormalSpdyTransactionHelper& helper)
2015 : session_(session), helper_(helper) {}
[email protected]b278eb72010-07-09 20:17:002016
2017 // We try to start another transaction, which should succeed.
2018 virtual void RunWithParams(const Tuple1<int>& params) {
[email protected]3caf5542010-07-16 15:19:472019 scoped_ptr<HttpNetworkTransaction> trans(
2020 new HttpNetworkTransaction(session_));
[email protected]b278eb72010-07-09 20:17:002021 TestCompletionCallback callback;
2022 HttpRequestInfo request;
2023 request.method = "GET";
2024 request.url = GURL("http://www.google.com/");
2025 request.load_flags = 0;
2026 int rv = trans->Start(&request, &callback, BoundNetLog());
2027 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3caf5542010-07-16 15:19:472028 rv = callback.WaitForResult();
[email protected]b278eb72010-07-09 20:17:002029 }
2030
2031 private:
[email protected]19ec8a72010-08-23 03:38:232032 const scoped_refptr<HttpNetworkSession>& session_;
[email protected]3caf5542010-07-16 15:19:472033 NormalSpdyTransactionHelper& helper_;
[email protected]b278eb72010-07-09 20:17:002034};
2035
2036// Verify that the client can correctly deal with the user callback attempting
2037// to start another transaction on a session that is closing down. See
2038// http://crbug.com/47455
[email protected]9e9e842e2010-07-23 23:09:152039TEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
[email protected]2bd93022010-07-17 00:58:442040 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]b278eb72010-07-09 20:17:002041 MockWrite writes[] = { CreateMockWrite(*req) };
2042 MockWrite writes2[] = { CreateMockWrite(*req) };
2043
2044 // The indicated length of this packet is longer than its actual length. When
2045 // the session receives an empty packet after this one, it shuts down the
2046 // session, and calls the read callback with the incomplete data.
2047 const uint8 kGetBodyFrame2[] = {
2048 0x00, 0x00, 0x00, 0x01,
2049 0x01, 0x00, 0x00, 0x07,
2050 'h', 'e', 'l', 'l', 'o', '!',
2051 };
2052
[email protected]2bd93022010-07-17 00:58:442053 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]b278eb72010-07-09 20:17:002054 MockRead reads[] = {
2055 CreateMockRead(*resp, 2),
2056 MockRead(true, ERR_IO_PENDING, 3), // Force a pause
2057 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame2),
2058 arraysize(kGetBodyFrame2), 4),
[email protected]3caf5542010-07-16 15:19:472059 MockRead(true, ERR_IO_PENDING, 5), // Force a pause
2060 MockRead(true, 0, 0, 6), // EOF
[email protected]b278eb72010-07-09 20:17:002061 };
2062 MockRead reads2[] = {
2063 CreateMockRead(*resp, 2),
2064 MockRead(true, 0, 0, 3), // EOF
2065 };
2066
[email protected]b278eb72010-07-09 20:17:002067 scoped_refptr<OrderedSocketData> data(
2068 new OrderedSocketData(reads, arraysize(reads),
2069 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:472070 scoped_refptr<DelayedSocketData> data2(
[email protected]8e6441ca2010-08-19 05:56:382071 new DelayedSocketData(1, reads2, arraysize(reads2),
[email protected]b278eb72010-07-09 20:17:002072 writes2, arraysize(writes2)));
[email protected]3caf5542010-07-16 15:19:472073
2074 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:152075 BoundNetLog(), GetParam());
[email protected]e3ebba0f2010-08-05 17:59:582076 helper.RunPreTestSetup();
[email protected]3caf5542010-07-16 15:19:472077 helper.AddData(data.get());
2078 helper.AddData(data2.get());
[email protected]3caf5542010-07-16 15:19:472079 HttpNetworkTransaction* trans = helper.trans();
[email protected]b278eb72010-07-09 20:17:002080
2081 // Start the transaction with basic parameters.
2082 TestCompletionCallback callback;
[email protected]3caf5542010-07-16 15:19:472083 int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
[email protected]b278eb72010-07-09 20:17:002084 EXPECT_EQ(ERR_IO_PENDING, rv);
2085 rv = callback.WaitForResult();
2086
[email protected]3caf5542010-07-16 15:19:472087 StartTransactionCallback callback2(helper.session(), helper);
[email protected]b278eb72010-07-09 20:17:002088 const int kSize = 3000;
[email protected]ad8e04a2010-11-01 04:16:272089 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
[email protected]b278eb72010-07-09 20:17:002090 rv = trans->Read(buf, kSize, &callback2);
[email protected]3caf5542010-07-16 15:19:472091 // This forces an err_IO_pending, which sets the callback.
[email protected]b278eb72010-07-09 20:17:002092 data->CompleteRead();
[email protected]3caf5542010-07-16 15:19:472093 // This finishes the read.
2094 data->CompleteRead();
2095 helper.VerifyDataConsumed();
[email protected]b278eb72010-07-09 20:17:002096}
2097
[email protected]3caf5542010-07-16 15:19:472098class SpdyNetworkTransactionTest::DeleteSessionCallback
2099 : public CallbackRunner< Tuple1<int> > {
[email protected]9be804c82010-06-24 17:59:462100 public:
[email protected]3caf5542010-07-16 15:19:472101 explicit DeleteSessionCallback(NormalSpdyTransactionHelper& helper) :
2102 helper_(helper) {}
[email protected]9be804c82010-06-24 17:59:462103
[email protected]b278eb72010-07-09 20:17:002104 // We kill the transaction, which deletes the session and stream.
[email protected]9be804c82010-06-24 17:59:462105 virtual void RunWithParams(const Tuple1<int>& params) {
[email protected]3caf5542010-07-16 15:19:472106 helper_.ResetTrans();
[email protected]9be804c82010-06-24 17:59:462107 }
2108
2109 private:
[email protected]3caf5542010-07-16 15:19:472110 NormalSpdyTransactionHelper& helper_;
[email protected]9be804c82010-06-24 17:59:462111};
2112
2113// Verify that the client can correctly deal with the user callback deleting the
2114// transaction. Failures will usually be valgrind errors. See
2115// http://crbug.com/46925
[email protected]9e9e842e2010-07-23 23:09:152116TEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
[email protected]2bd93022010-07-17 00:58:442117 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:132118 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]9be804c82010-06-24 17:59:462119
[email protected]2bd93022010-07-17 00:58:442120 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2121 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]9be804c82010-06-24 17:59:462122 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:132123 CreateMockRead(*resp.get(), 2),
[email protected]9be804c82010-06-24 17:59:462124 MockRead(true, ERR_IO_PENDING, 3), // Force a pause
[email protected]e7f75092010-07-01 22:39:132125 CreateMockRead(*body.get(), 4),
[email protected]9be804c82010-06-24 17:59:462126 MockRead(true, 0, 0, 5), // EOF
2127 };
2128
[email protected]9be804c82010-06-24 17:59:462129 scoped_refptr<OrderedSocketData> data(
2130 new OrderedSocketData(reads, arraysize(reads),
2131 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:472132
2133 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:152134 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:472135 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:582136 helper.AddData(data.get());
[email protected]3caf5542010-07-16 15:19:472137 HttpNetworkTransaction* trans = helper.trans();
[email protected]9be804c82010-06-24 17:59:462138
2139 // Start the transaction with basic parameters.
2140 TestCompletionCallback callback;
[email protected]3caf5542010-07-16 15:19:472141 int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
[email protected]9be804c82010-06-24 17:59:462142 EXPECT_EQ(ERR_IO_PENDING, rv);
2143 rv = callback.WaitForResult();
2144
2145 // Setup a user callback which will delete the session, and clear out the
2146 // memory holding the stream object. Note that the callback deletes trans.
[email protected]3caf5542010-07-16 15:19:472147 DeleteSessionCallback callback2(helper);
[email protected]9be804c82010-06-24 17:59:462148 const int kSize = 3000;
[email protected]ad8e04a2010-11-01 04:16:272149 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
[email protected]9be804c82010-06-24 17:59:462150 rv = trans->Read(buf, kSize, &callback2);
2151 ASSERT_EQ(ERR_IO_PENDING, rv);
2152 data->CompleteRead();
2153
2154 // Finish running rest of tasks.
2155 MessageLoop::current()->RunAllPending();
[email protected]3caf5542010-07-16 15:19:472156 helper.VerifyDataConsumed();
[email protected]9be804c82010-06-24 17:59:462157}
2158
[email protected]e3ebba0f2010-08-05 17:59:582159// Send a spdy request to www.google.com that gets redirected to www.foo.com.
2160TEST_P(SpdyNetworkTransactionTest, RedirectGetRequest) {
[email protected]6981d9632010-11-30 21:34:022161 // These are headers which the net::URLRequest tacks on.
[email protected]e3ebba0f2010-08-05 17:59:582162 const char* const kExtraHeaders[] = {
2163 "accept-charset",
2164 "",
2165 "accept-encoding",
2166 "gzip,deflate",
2167 "accept-language",
2168 "",
2169 };
2170 const SpdyHeaderInfo kSynStartHeader = make_spdy_header(spdy::SYN_STREAM);
2171 const char* const kStandardGetHeaders[] = {
2172 "host",
2173 "www.google.com",
2174 "method",
2175 "GET",
2176 "scheme",
2177 "http",
2178 "url",
2179 "/",
2180 "user-agent",
2181 "",
2182 "version",
2183 "HTTP/1.1"
2184 };
2185 const char* const kStandardGetHeaders2[] = {
2186 "host",
2187 "www.foo.com",
2188 "method",
2189 "GET",
2190 "scheme",
2191 "http",
2192 "url",
2193 "/index.php",
2194 "user-agent",
2195 "",
2196 "version",
2197 "HTTP/1.1"
2198 };
2199
2200 // Setup writes/reads to www.google.com
2201 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPacket(
2202 kSynStartHeader, kExtraHeaders, arraysize(kExtraHeaders)/2,
2203 kStandardGetHeaders, arraysize(kStandardGetHeaders)/2));
2204 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyPacket(
2205 kSynStartHeader, kExtraHeaders, arraysize(kExtraHeaders)/2,
2206 kStandardGetHeaders2, arraysize(kStandardGetHeaders2)/2));
2207 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReplyRedirect(1));
2208 MockWrite writes[] = {
2209 CreateMockWrite(*req, 1),
2210 };
2211 MockRead reads[] = {
2212 CreateMockRead(*resp, 2),
2213 MockRead(true, 0, 0, 3) // EOF
2214 };
2215
2216 // Setup writes/reads to www.foo.com
2217 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 1));
2218 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(1, true));
2219 MockWrite writes2[] = {
2220 CreateMockWrite(*req2, 1),
2221 };
2222 MockRead reads2[] = {
2223 CreateMockRead(*resp2, 2),
2224 CreateMockRead(*body2, 3),
2225 MockRead(true, 0, 0, 4) // EOF
2226 };
2227 scoped_refptr<OrderedSocketData> data(
2228 new OrderedSocketData(reads, arraysize(reads),
2229 writes, arraysize(writes)));
2230 scoped_refptr<OrderedSocketData> data2(
2231 new OrderedSocketData(reads2, arraysize(reads2),
2232 writes2, arraysize(writes2)));
2233
2234 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
[email protected]8e6441ca2010-08-19 05:56:382235 HttpStreamFactory::set_force_spdy_over_ssl(false);
2236 HttpStreamFactory::set_force_spdy_always(true);
[email protected]e3ebba0f2010-08-05 17:59:582237 TestDelegate d;
2238 {
[email protected]6981d9632010-11-30 21:34:022239 net::URLRequest r(GURL("http://www.google.com/"), &d);
[email protected]e3ebba0f2010-08-05 17:59:582240 SpdyURLRequestContext* spdy_url_request_context =
2241 new SpdyURLRequestContext();
2242 r.set_context(spdy_url_request_context);
2243 spdy_url_request_context->socket_factory().
2244 AddSocketDataProvider(data.get());
2245 spdy_url_request_context->socket_factory().
2246 AddSocketDataProvider(data2.get());
2247
2248 d.set_quit_on_redirect(true);
2249 r.Start();
2250 MessageLoop::current()->Run();
2251
2252 EXPECT_EQ(1, d.received_redirect_count());
2253
2254 r.FollowDeferredRedirect();
2255 MessageLoop::current()->Run();
2256 EXPECT_EQ(1, d.response_started_count());
2257 EXPECT_FALSE(d.received_data_before_response());
2258 EXPECT_EQ(URLRequestStatus::SUCCESS, r.status().status());
2259 std::string contents("hello!");
2260 EXPECT_EQ(contents, d.data_received());
2261 }
2262 EXPECT_TRUE(data->at_read_eof());
2263 EXPECT_TRUE(data->at_write_eof());
2264 EXPECT_TRUE(data2->at_read_eof());
2265 EXPECT_TRUE(data2->at_write_eof());
2266}
2267
2268// Send a spdy request to www.google.com. Get a pushed stream that redirects to
2269// www.foo.com.
2270TEST_P(SpdyNetworkTransactionTest, RedirectServerPush) {
[email protected]6981d9632010-11-30 21:34:022271 // These are headers which the net::URLRequest tacks on.
[email protected]e3ebba0f2010-08-05 17:59:582272 const char* const kExtraHeaders[] = {
2273 "accept-charset",
2274 "",
2275 "accept-encoding",
2276 "gzip,deflate",
2277 "accept-language",
2278 "",
2279 };
2280 const SpdyHeaderInfo kSynStartHeader = make_spdy_header(spdy::SYN_STREAM);
2281 const char* const kStandardGetHeaders[] = {
2282 "host",
2283 "www.google.com",
2284 "method",
2285 "GET",
2286 "scheme",
2287 "http",
2288 "url",
2289 "/",
2290 "user-agent",
2291 "",
2292 "version",
2293 "HTTP/1.1"
2294 };
2295 const char* const kStandardGetHeaders2[] = {
2296 "host",
2297 "www.foo.com",
2298 "method",
2299 "GET",
2300 "scheme",
2301 "http",
2302 "url",
2303 "/index.php",
2304 "user-agent",
2305 "",
2306 "version",
2307 "HTTP/1.1"
2308 };
2309
2310 // Setup writes/reads to www.google.com
2311 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPacket(
2312 kSynStartHeader, kExtraHeaders, arraysize(kExtraHeaders)/2,
2313 kStandardGetHeaders, arraysize(kStandardGetHeaders)/2));
2314 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyPacket(
2315 kSynStartHeader, kExtraHeaders, arraysize(kExtraHeaders)/2,
2316 kStandardGetHeaders2, arraysize(kStandardGetHeaders2)/2));
2317 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2318 scoped_ptr<spdy::SpdyFrame> rep(ConstructSpdyPush(NULL, 0, 2, 1, "/foo.dat",
2319 "301 Moved Permanently", "http://www.foo.com/index.php",
2320 "http://www.foo.com/index.php"));
2321 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582322 MockWrite writes[] = {
2323 CreateMockWrite(*req, 1),
[email protected]e3ebba0f2010-08-05 17:59:582324 };
2325 MockRead reads[] = {
2326 CreateMockRead(*resp, 2),
2327 CreateMockRead(*rep, 3),
2328 CreateMockRead(*body, 4),
2329 MockRead(true, ERR_IO_PENDING, 5), // Force a pause
[email protected]0b0bf032010-09-21 18:08:502330 MockRead(true, 0, 0, 6) // EOF
[email protected]e3ebba0f2010-08-05 17:59:582331 };
2332
2333 // Setup writes/reads to www.foo.com
2334 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 1));
2335 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(1, true));
2336 MockWrite writes2[] = {
2337 CreateMockWrite(*req2, 1),
2338 };
2339 MockRead reads2[] = {
2340 CreateMockRead(*resp2, 2),
2341 CreateMockRead(*body2, 3),
2342 MockRead(true, 0, 0, 5) // EOF
2343 };
2344 scoped_refptr<OrderedSocketData> data(
2345 new OrderedSocketData(reads, arraysize(reads),
2346 writes, arraysize(writes)));
2347 scoped_refptr<OrderedSocketData> data2(
2348 new OrderedSocketData(reads2, arraysize(reads2),
2349 writes2, arraysize(writes2)));
2350
2351 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
[email protected]8e6441ca2010-08-19 05:56:382352 HttpStreamFactory::set_force_spdy_over_ssl(false);
2353 HttpStreamFactory::set_force_spdy_always(true);
[email protected]e3ebba0f2010-08-05 17:59:582354 TestDelegate d;
2355 TestDelegate d2;
[email protected]2431756e2010-09-29 20:26:132356 scoped_refptr<SpdyURLRequestContext> spdy_url_request_context(
2357 new SpdyURLRequestContext());
[email protected]e3ebba0f2010-08-05 17:59:582358 {
[email protected]6981d9632010-11-30 21:34:022359 net::URLRequest r(GURL("http://www.google.com/"), &d);
[email protected]e3ebba0f2010-08-05 17:59:582360 r.set_context(spdy_url_request_context);
2361 spdy_url_request_context->socket_factory().
2362 AddSocketDataProvider(data.get());
2363
2364 r.Start();
2365 MessageLoop::current()->Run();
2366
2367 EXPECT_EQ(0, d.received_redirect_count());
2368 std::string contents("hello!");
2369 EXPECT_EQ(contents, d.data_received());
2370
[email protected]6981d9632010-11-30 21:34:022371 net::URLRequest r2(GURL("http://www.google.com/foo.dat"), &d2);
[email protected]e3ebba0f2010-08-05 17:59:582372 r2.set_context(spdy_url_request_context);
2373 spdy_url_request_context->socket_factory().
2374 AddSocketDataProvider(data2.get());
2375
2376 d2.set_quit_on_redirect(true);
2377 r2.Start();
2378 MessageLoop::current()->Run();
2379 EXPECT_EQ(1, d2.received_redirect_count());
2380
2381 r2.FollowDeferredRedirect();
2382 MessageLoop::current()->Run();
2383 EXPECT_EQ(1, d2.response_started_count());
2384 EXPECT_FALSE(d2.received_data_before_response());
2385 EXPECT_EQ(URLRequestStatus::SUCCESS, r2.status().status());
2386 std::string contents2("hello!");
2387 EXPECT_EQ(contents2, d2.data_received());
2388 }
2389 data->CompleteRead();
2390 data2->CompleteRead();
2391 EXPECT_TRUE(data->at_read_eof());
2392 EXPECT_TRUE(data->at_write_eof());
2393 EXPECT_TRUE(data2->at_read_eof());
2394 EXPECT_TRUE(data2->at_write_eof());
2395}
2396
2397TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
2398 static const unsigned char kPushBodyFrame[] = {
2399 0x00, 0x00, 0x00, 0x02, // header, ID
[email protected]19ec8a72010-08-23 03:38:232400 0x01, 0x00, 0x00, 0x06, // FIN, length
2401 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
[email protected]e3ebba0f2010-08-05 17:59:582402 };
[email protected]19ec8a72010-08-23 03:38:232403 scoped_ptr<spdy::SpdyFrame>
2404 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2405 scoped_ptr<spdy::SpdyFrame>
2406 stream1_body(ConstructSpdyBodyFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582407 MockWrite writes[] = {
[email protected]19ec8a72010-08-23 03:38:232408 CreateMockWrite(*stream1_syn, 1),
[email protected]e3ebba0f2010-08-05 17:59:582409 };
2410
[email protected]19ec8a72010-08-23 03:38:232411 scoped_ptr<spdy::SpdyFrame>
2412 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
2413 scoped_ptr<spdy::SpdyFrame>
2414 stream2_syn(ConstructSpdyPush(NULL, 0, 2, 1, "/foo.dat"));
[email protected]e3ebba0f2010-08-05 17:59:582415 MockRead reads[] = {
[email protected]19ec8a72010-08-23 03:38:232416 CreateMockRead(*stream1_reply, 2),
2417 CreateMockRead(*stream2_syn, 3),
2418 CreateMockRead(*stream1_body, 4, false),
[email protected]e3ebba0f2010-08-05 17:59:582419 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame),
[email protected]19ec8a72010-08-23 03:38:232420 arraysize(kPushBodyFrame), 5),
[email protected]e3ebba0f2010-08-05 17:59:582421 MockRead(true, ERR_IO_PENDING, 6), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582422 };
2423
2424 HttpResponseInfo response;
2425 HttpResponseInfo response2;
[email protected]19ec8a72010-08-23 03:38:232426 std::string expected_push_result("pushed");
[email protected]e3ebba0f2010-08-05 17:59:582427 RunServerPushTest(writes, arraysize(writes), reads, arraysize(reads),
2428 &response, &response2, expected_push_result);
2429
2430 // Verify the SYN_REPLY.
2431 EXPECT_TRUE(response.headers != NULL);
2432 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2433
2434 // Verify the pushed stream.
2435 EXPECT_TRUE(response2.headers != NULL);
2436 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2437}
2438
[email protected]82918cc2010-08-25 17:24:502439TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
2440 static const unsigned char kPushBodyFrame[] = {
2441 0x00, 0x00, 0x00, 0x02, // header, ID
2442 0x01, 0x00, 0x00, 0x06, // FIN, length
2443 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
2444 };
2445 scoped_ptr<spdy::SpdyFrame>
2446 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2447 MockWrite writes[] = {
2448 CreateMockWrite(*stream1_syn, 1),
2449 };
2450
2451 scoped_ptr<spdy::SpdyFrame>
2452 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
2453 scoped_ptr<spdy::SpdyFrame>
2454 stream2_syn(ConstructSpdyPush(NULL, 0, 2, 1, "/foo.dat"));
2455 scoped_ptr<spdy::SpdyFrame>
2456 stream1_body(ConstructSpdyBodyFrame(1, true));
2457 MockRead reads[] = {
2458 CreateMockRead(*stream1_reply, 2),
2459 CreateMockRead(*stream2_syn, 3),
2460 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame),
2461 arraysize(kPushBodyFrame), 5),
2462 CreateMockRead(*stream1_body, 4, false),
2463 MockRead(true, ERR_IO_PENDING, 6), // Force a pause
2464 };
2465
2466 HttpResponseInfo response;
2467 HttpResponseInfo response2;
2468 std::string expected_push_result("pushed");
2469 RunServerPushTest(writes, arraysize(writes), reads, arraysize(reads),
2470 &response, &response2, expected_push_result);
2471
2472 // Verify the SYN_REPLY.
2473 EXPECT_TRUE(response.headers != NULL);
2474 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2475
2476 // Verify the pushed stream.
2477 EXPECT_TRUE(response2.headers != NULL);
2478 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2479}
2480
[email protected]19ec8a72010-08-23 03:38:232481TEST_P(SpdyNetworkTransactionTest, ServerPushServerAborted) {
2482 scoped_ptr<spdy::SpdyFrame>
2483 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2484 scoped_ptr<spdy::SpdyFrame>
2485 stream1_body(ConstructSpdyBodyFrame(1, true));
[email protected]e3ebba0f2010-08-05 17:59:582486 MockWrite writes[] = {
[email protected]19ec8a72010-08-23 03:38:232487 CreateMockWrite(*stream1_syn, 1),
[email protected]e3ebba0f2010-08-05 17:59:582488 };
2489
[email protected]19ec8a72010-08-23 03:38:232490 scoped_ptr<spdy::SpdyFrame>
2491 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
2492 scoped_ptr<spdy::SpdyFrame>
2493 stream2_syn(ConstructSpdyPush(NULL, 0, 2, 1, "/foo.dat"));
2494 scoped_ptr<spdy::SpdyFrame>
2495 stream2_rst(ConstructSpdyRstStream(2, spdy::PROTOCOL_ERROR));
[email protected]e3ebba0f2010-08-05 17:59:582496 MockRead reads[] = {
[email protected]19ec8a72010-08-23 03:38:232497 CreateMockRead(*stream1_reply, 2),
2498 CreateMockRead(*stream2_syn, 3),
2499 CreateMockRead(*stream2_rst, 4),
2500 CreateMockRead(*stream1_body, 5, false),
2501 MockRead(true, ERR_IO_PENDING, 6), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582502 };
2503
2504 scoped_refptr<OrderedSocketData> data(
2505 new OrderedSocketData(reads, arraysize(reads),
2506 writes, arraysize(writes)));
2507 NormalSpdyTransactionHelper helper(CreateGetRequest(),
2508 BoundNetLog(), GetParam());
2509
2510 helper.RunPreTestSetup();
2511 helper.AddData(data.get());
2512
2513 HttpNetworkTransaction* trans = helper.trans();
2514
2515 // Start the transaction with basic parameters.
2516 TestCompletionCallback callback;
2517 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
2518 EXPECT_EQ(ERR_IO_PENDING, rv);
2519 rv = callback.WaitForResult();
[email protected]19ec8a72010-08-23 03:38:232520 EXPECT_EQ(OK, rv);
2521
2522 // Verify that we consumed all test data.
2523 EXPECT_TRUE(data->at_read_eof()) << "Read count: "
2524 << data->read_count()
2525 << " Read index: "
2526 << data->read_index();
2527 EXPECT_TRUE(data->at_write_eof()) << "Write count: "
2528 << data->write_count()
2529 << " Write index: "
2530 << data->write_index();
2531
2532 // Verify the SYN_REPLY.
2533 HttpResponseInfo response = *trans->GetResponseInfo();
2534 EXPECT_TRUE(response.headers != NULL);
2535 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2536}
2537
[email protected]fdc165a2010-09-03 03:51:292538TEST_P(SpdyNetworkTransactionTest, ServerPushDuplicate) {
2539 // Verify that we don't leak streams and that we properly send a reset
2540 // if the server pushes the same stream twice.
2541 static const unsigned char kPushBodyFrame[] = {
2542 0x00, 0x00, 0x00, 0x02, // header, ID
2543 0x01, 0x00, 0x00, 0x06, // FIN, length
2544 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
2545 };
2546
2547 scoped_ptr<spdy::SpdyFrame>
2548 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2549 scoped_ptr<spdy::SpdyFrame>
2550 stream1_body(ConstructSpdyBodyFrame(1, true));
2551 scoped_ptr<spdy::SpdyFrame>
2552 stream3_rst(ConstructSpdyRstStream(4, spdy::PROTOCOL_ERROR));
2553 MockWrite writes[] = {
2554 CreateMockWrite(*stream1_syn, 1),
2555 CreateMockWrite(*stream3_rst, 5),
2556 };
2557
2558 scoped_ptr<spdy::SpdyFrame>
2559 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
2560 scoped_ptr<spdy::SpdyFrame>
2561 stream2_syn(ConstructSpdyPush(NULL, 0, 2, 1, "/foo.dat"));
2562 scoped_ptr<spdy::SpdyFrame>
2563 stream3_syn(ConstructSpdyPush(NULL, 0, 4, 1, "/foo.dat"));
2564 MockRead reads[] = {
2565 CreateMockRead(*stream1_reply, 2),
2566 CreateMockRead(*stream2_syn, 3),
2567 CreateMockRead(*stream3_syn, 4),
2568 CreateMockRead(*stream1_body, 6, false),
2569 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame),
2570 arraysize(kPushBodyFrame), 7),
2571 MockRead(true, ERR_IO_PENDING, 8), // Force a pause
2572 };
2573
2574 HttpResponseInfo response;
2575 HttpResponseInfo response2;
2576 std::string expected_push_result("pushed");
2577 RunServerPushTest(writes, arraysize(writes), reads, arraysize(reads),
2578 &response, &response2, expected_push_result);
2579
2580 // Verify the SYN_REPLY.
2581 EXPECT_TRUE(response.headers != NULL);
2582 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2583
2584 // Verify the pushed stream.
2585 EXPECT_TRUE(response2.headers != NULL);
2586 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2587}
2588
[email protected]19ec8a72010-08-23 03:38:232589TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
2590 static const unsigned char kPushBodyFrame1[] = {
2591 0x00, 0x00, 0x00, 0x02, // header, ID
2592 0x01, 0x00, 0x00, 0x1F, // FIN, length
2593 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
2594 };
2595 static const char kPushBodyFrame2[] = " my darling";
2596 static const char kPushBodyFrame3[] = " hello";
2597 static const char kPushBodyFrame4[] = " my baby";
2598
2599 scoped_ptr<spdy::SpdyFrame>
2600 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2601 scoped_ptr<spdy::SpdyFrame>
2602 stream1_body(ConstructSpdyBodyFrame(1, true));
2603 MockWrite writes[] = {
2604 CreateMockWrite(*stream1_syn, 1),
2605 };
2606
2607 scoped_ptr<spdy::SpdyFrame>
2608 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
2609 scoped_ptr<spdy::SpdyFrame>
2610 stream2_syn(ConstructSpdyPush(NULL, 0, 2, 1, "/foo.dat"));
2611 MockRead reads[] = {
2612 CreateMockRead(*stream1_reply, 2),
2613 CreateMockRead(*stream2_syn, 3),
2614 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame1),
2615 arraysize(kPushBodyFrame1), 4),
2616 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame2),
2617 arraysize(kPushBodyFrame2) - 1, 5),
2618 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame3),
2619 arraysize(kPushBodyFrame3) - 1, 6),
2620 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame4),
2621 arraysize(kPushBodyFrame4) - 1, 7),
2622 CreateMockRead(*stream1_body, 8, false),
2623 MockRead(true, ERR_IO_PENDING, 9), // Force a pause
2624 };
2625
2626 HttpResponseInfo response;
2627 HttpResponseInfo response2;
2628 std::string expected_push_result("pushed my darling hello my baby");
2629 RunServerPushTest(writes, arraysize(writes), reads, arraysize(reads),
2630 &response, &response2, expected_push_result);
2631
2632 // Verify the SYN_REPLY.
2633 EXPECT_TRUE(response.headers != NULL);
2634 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2635
2636 // Verify the pushed stream.
2637 EXPECT_TRUE(response2.headers != NULL);
2638 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2639}
2640
2641TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
2642 static const unsigned char kPushBodyFrame1[] = {
2643 0x00, 0x00, 0x00, 0x02, // header, ID
2644 0x01, 0x00, 0x00, 0x1F, // FIN, length
2645 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
2646 };
2647 static const char kPushBodyFrame2[] = " my darling";
2648 static const char kPushBodyFrame3[] = " hello";
2649 static const char kPushBodyFrame4[] = " my baby";
2650
2651 scoped_ptr<spdy::SpdyFrame>
2652 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2653 scoped_ptr<spdy::SpdyFrame>
2654 stream1_body(ConstructSpdyBodyFrame(1, true));
2655 MockWrite writes[] = {
2656 CreateMockWrite(*stream1_syn, 1),
2657 };
2658
2659 scoped_ptr<spdy::SpdyFrame>
2660 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
2661 scoped_ptr<spdy::SpdyFrame>
2662 stream2_syn(ConstructSpdyPush(NULL, 0, 2, 1, "/foo.dat"));
2663 MockRead reads[] = {
2664 CreateMockRead(*stream1_reply, 2),
2665 CreateMockRead(*stream2_syn, 3),
2666 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame1),
2667 arraysize(kPushBodyFrame1), 4),
2668 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame2),
2669 arraysize(kPushBodyFrame2) - 1, 5),
2670 MockRead(true, ERR_IO_PENDING, 6), // Force a pause
2671 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame3),
2672 arraysize(kPushBodyFrame3) - 1, 7),
2673 MockRead(true, reinterpret_cast<const char*>(kPushBodyFrame4),
2674 arraysize(kPushBodyFrame4) - 1, 8),
2675 CreateMockRead(*stream1_body.get(), 9, false),
2676 MockRead(true, ERR_IO_PENDING, 10) // Force a pause.
2677 };
2678
2679 HttpResponseInfo response;
2680 HttpResponseInfo response2;
2681 std::string expected_push_result("pushed my darling hello my baby");
2682 RunServerPushTest(writes, arraysize(writes), reads, arraysize(reads),
2683 &response, &response2, expected_push_result);
2684
2685 // Verify the SYN_REPLY.
2686 EXPECT_TRUE(response.headers != NULL);
2687 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2688
2689 // Verify the pushed stream.
2690 EXPECT_TRUE(response2.headers != NULL);
2691 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2692}
2693
2694TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
2695 scoped_ptr<spdy::SpdyFrame>
2696 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2697 scoped_ptr<spdy::SpdyFrame>
2698 stream1_body(ConstructSpdyBodyFrame(1, true));
2699 scoped_ptr<spdy::SpdyFrame>
2700 stream2_rst(ConstructSpdyRstStream(2, spdy::INVALID_STREAM));
2701 MockWrite writes[] = {
2702 CreateMockWrite(*stream1_syn, 1),
2703 CreateMockWrite(*stream2_rst, 4),
2704 };
2705
2706 scoped_ptr<spdy::SpdyFrame>
2707 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
2708 scoped_ptr<spdy::SpdyFrame>
2709 stream2_syn(ConstructSpdyPush(NULL, 0, 2, 0, "/foo.dat"));
2710 MockRead reads[] = {
2711 CreateMockRead(*stream1_reply, 2),
2712 CreateMockRead(*stream2_syn, 3),
2713 CreateMockRead(*stream1_body, 4),
2714 MockRead(true, ERR_IO_PENDING, 5) // Force a pause
2715 };
2716
2717 scoped_refptr<OrderedSocketData> data(
2718 new OrderedSocketData(reads, arraysize(reads),
2719 writes, arraysize(writes)));
2720 NormalSpdyTransactionHelper helper(CreateGetRequest(),
2721 BoundNetLog(), GetParam());
2722
2723 helper.RunPreTestSetup();
2724 helper.AddData(data.get());
2725
2726 HttpNetworkTransaction* trans = helper.trans();
2727
2728 // Start the transaction with basic parameters.
2729 TestCompletionCallback callback;
2730 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
2731 EXPECT_EQ(ERR_IO_PENDING, rv);
2732 rv = callback.WaitForResult();
[email protected]e3ebba0f2010-08-05 17:59:582733 EXPECT_EQ(OK, rv);
2734
2735 // Verify that we consumed all test data.
2736 EXPECT_TRUE(data->at_read_eof()) << "Read count: "
2737 << data->read_count()
2738 << " Read index: "
2739 << data->read_index();
2740 EXPECT_TRUE(data->at_write_eof()) << "Write count: "
2741 << data->write_count()
2742 << " Write index: "
2743 << data->write_index();
2744
2745 // Verify the SYN_REPLY.
2746 HttpResponseInfo response = *trans->GetResponseInfo();
2747 EXPECT_TRUE(response.headers != NULL);
2748 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2749}
2750
2751TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
[email protected]19ec8a72010-08-23 03:38:232752 scoped_ptr<spdy::SpdyFrame>
2753 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2754 scoped_ptr<spdy::SpdyFrame>
2755 stream1_body(ConstructSpdyBodyFrame(1, true));
2756 scoped_ptr<spdy::SpdyFrame>
2757 stream2_rst(ConstructSpdyRstStream(2, spdy::INVALID_ASSOCIATED_STREAM));
[email protected]e3ebba0f2010-08-05 17:59:582758 MockWrite writes[] = {
[email protected]19ec8a72010-08-23 03:38:232759 CreateMockWrite(*stream1_syn, 1),
2760 CreateMockWrite(*stream2_rst, 4),
[email protected]e3ebba0f2010-08-05 17:59:582761 };
2762
[email protected]19ec8a72010-08-23 03:38:232763 scoped_ptr<spdy::SpdyFrame>
2764 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
2765 scoped_ptr<spdy::SpdyFrame>
2766 stream2_syn(ConstructSpdyPush(NULL, 0, 2, 9, "/foo.dat"));
[email protected]e3ebba0f2010-08-05 17:59:582767 MockRead reads[] = {
[email protected]19ec8a72010-08-23 03:38:232768 CreateMockRead(*stream1_reply, 2),
2769 CreateMockRead(*stream2_syn, 3),
2770 CreateMockRead(*stream1_body, 4),
2771 MockRead(true, ERR_IO_PENDING, 5), // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582772 };
2773
2774 scoped_refptr<OrderedSocketData> data(
2775 new OrderedSocketData(reads, arraysize(reads),
2776 writes, arraysize(writes)));
2777 NormalSpdyTransactionHelper helper(CreateGetRequest(),
2778 BoundNetLog(), GetParam());
2779
2780 helper.RunPreTestSetup();
2781 helper.AddData(data.get());
2782
2783 HttpNetworkTransaction* trans = helper.trans();
2784
2785 // Start the transaction with basic parameters.
2786 TestCompletionCallback callback;
2787 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
2788 EXPECT_EQ(ERR_IO_PENDING, rv);
2789 rv = callback.WaitForResult();
[email protected]e3ebba0f2010-08-05 17:59:582790 EXPECT_EQ(OK, rv);
2791
2792 // Verify that we consumed all test data.
2793 EXPECT_TRUE(data->at_read_eof()) << "Read count: "
2794 << data->read_count()
2795 << " Read index: "
2796 << data->read_index();
2797 EXPECT_TRUE(data->at_write_eof()) << "Write count: "
2798 << data->write_count()
2799 << " Write index: "
2800 << data->write_index();
2801
2802 // Verify the SYN_REPLY.
2803 HttpResponseInfo response = *trans->GetResponseInfo();
2804 EXPECT_TRUE(response.headers != NULL);
2805 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2806}
2807
2808TEST_P(SpdyNetworkTransactionTest, ServerPushNoURL) {
[email protected]19ec8a72010-08-23 03:38:232809 scoped_ptr<spdy::SpdyFrame>
2810 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2811 scoped_ptr<spdy::SpdyFrame>
2812 stream1_body(ConstructSpdyBodyFrame(1, true));
2813 scoped_ptr<spdy::SpdyFrame>
2814 stream2_rst(ConstructSpdyRstStream(2, spdy::PROTOCOL_ERROR));
[email protected]e3ebba0f2010-08-05 17:59:582815 MockWrite writes[] = {
[email protected]19ec8a72010-08-23 03:38:232816 CreateMockWrite(*stream1_syn, 1),
2817 CreateMockWrite(*stream2_rst, 4),
[email protected]e3ebba0f2010-08-05 17:59:582818 };
2819
[email protected]19ec8a72010-08-23 03:38:232820 scoped_ptr<spdy::SpdyFrame>
2821 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
2822 scoped_ptr<spdy::SpdyFrame>
2823 stream2_syn(ConstructSpdyPush(NULL, 0, 2, 1));
[email protected]e3ebba0f2010-08-05 17:59:582824 MockRead reads[] = {
[email protected]19ec8a72010-08-23 03:38:232825 CreateMockRead(*stream1_reply, 2),
2826 CreateMockRead(*stream2_syn, 3),
2827 CreateMockRead(*stream1_body, 4),
2828 MockRead(true, ERR_IO_PENDING, 5) // Force a pause
[email protected]e3ebba0f2010-08-05 17:59:582829 };
2830
2831 scoped_refptr<OrderedSocketData> data(
2832 new OrderedSocketData(reads, arraysize(reads),
2833 writes, arraysize(writes)));
2834 NormalSpdyTransactionHelper helper(CreateGetRequest(),
2835 BoundNetLog(), GetParam());
2836
2837 helper.RunPreTestSetup();
2838 helper.AddData(data.get());
2839
2840 HttpNetworkTransaction* trans = helper.trans();
2841
2842 // Start the transaction with basic parameters.
2843 TestCompletionCallback callback;
2844 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
2845 EXPECT_EQ(ERR_IO_PENDING, rv);
2846 rv = callback.WaitForResult();
[email protected]e3ebba0f2010-08-05 17:59:582847 EXPECT_EQ(OK, rv);
2848 // Verify that we consumed all test data.
2849 EXPECT_TRUE(data->at_read_eof()) << "Read count: "
2850 << data->read_count()
2851 << " Read index: "
2852 << data->read_index();
2853 EXPECT_TRUE(data->at_write_eof()) << "Write count: "
2854 << data->write_count()
2855 << " Write index: "
2856 << data->write_index();
2857
2858 // Verify the SYN_REPLY.
2859 HttpResponseInfo response = *trans->GetResponseInfo();
2860 EXPECT_TRUE(response.headers != NULL);
2861 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2862}
2863
[email protected]8b070372009-11-16 22:01:252864// Verify that various SynReply headers parse correctly through the
2865// HTTP layer.
[email protected]9e9e842e2010-07-23 23:09:152866TEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) {
[email protected]e7f75092010-07-01 22:39:132867 struct SynReplyHeadersTests {
2868 int num_headers;
2869 const char* extra_headers[5];
[email protected]8b070372009-11-16 22:01:252870 const char* expected_headers;
2871 } test_cases[] = {
[email protected]e7f75092010-07-01 22:39:132872 // This uses a multi-valued cookie header.
2873 { 2,
2874 { "cookie", "val1",
2875 "cookie", "val2", // will get appended separated by NULL
2876 NULL
2877 },
[email protected]8b070372009-11-16 22:01:252878 "cookie: val1\n"
2879 "cookie: val2\n"
[email protected]e7f75092010-07-01 22:39:132880 "hello: bye\n"
[email protected]8b070372009-11-16 22:01:252881 "status: 200\n"
2882 "url: /index.php\n"
2883 "version: HTTP/1.1\n"
2884 },
[email protected]e7f75092010-07-01 22:39:132885 // This is the minimalist set of headers.
2886 { 0,
2887 { NULL },
2888 "hello: bye\n"
[email protected]8b070372009-11-16 22:01:252889 "status: 200\n"
2890 "url: /index.php\n"
2891 "version: HTTP/1.1\n"
2892 },
[email protected]e7f75092010-07-01 22:39:132893 // Headers with a comma separated list.
2894 { 1,
2895 { "cookie", "val1,val2",
2896 NULL
2897 },
[email protected]8b070372009-11-16 22:01:252898 "cookie: val1,val2\n"
[email protected]e7f75092010-07-01 22:39:132899 "hello: bye\n"
[email protected]8b070372009-11-16 22:01:252900 "status: 200\n"
2901 "url: /index.php\n"
2902 "version: HTTP/1.1\n"
2903 }
2904 };
2905
2906 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
[email protected]2bd93022010-07-17 00:58:442907 scoped_ptr<spdy::SpdyFrame> req(
2908 ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:132909 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]8b070372009-11-16 22:01:252910
[email protected]e7f75092010-07-01 22:39:132911 scoped_ptr<spdy::SpdyFrame> resp(
2912 ConstructSpdyGetSynReply(test_cases[i].extra_headers,
[email protected]2bd93022010-07-17 00:58:442913 test_cases[i].num_headers,
2914 1));
2915 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]8b070372009-11-16 22:01:252916 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:132917 CreateMockRead(*resp),
2918 CreateMockRead(*body),
[email protected]8b070372009-11-16 22:01:252919 MockRead(true, 0, 0) // EOF
2920 };
2921
[email protected]bf2491a92009-11-29 16:39:482922 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:392923 new DelayedSocketData(1, reads, arraysize(reads),
2924 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:472925 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:152926 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:472927 helper.RunToCompletion(data.get());
2928 TransactionHelperResult out = helper.output();
2929
[email protected]8b070372009-11-16 22:01:252930 EXPECT_EQ(OK, out.rv);
2931 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
2932 EXPECT_EQ("hello!", out.response_data);
2933
2934 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
2935 EXPECT_TRUE(headers.get() != NULL);
2936 void* iter = NULL;
2937 std::string name, value, lines;
2938 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
2939 lines.append(name);
2940 lines.append(": ");
2941 lines.append(value);
2942 lines.append("\n");
2943 }
2944 EXPECT_EQ(std::string(test_cases[i].expected_headers), lines);
2945 }
2946}
2947
[email protected]3f662f12010-03-25 19:56:122948// Verify that various SynReply headers parse vary fields correctly
2949// through the HTTP layer, and the response matches the request.
[email protected]9e9e842e2010-07-23 23:09:152950TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) {
[email protected]3f662f12010-03-25 19:56:122951 static const SpdyHeaderInfo syn_reply_info = {
2952 spdy::SYN_REPLY, // Syn Reply
2953 1, // Stream ID
2954 0, // Associated Stream ID
[email protected]c9c6f5c2010-07-31 01:30:032955 net::ConvertRequestPriorityToSpdyPriority(LOWEST),
2956 // Priority
[email protected]3f662f12010-03-25 19:56:122957 spdy::CONTROL_FLAG_NONE, // Control Flags
2958 false, // Compressed
[email protected]75f30cc22010-06-28 21:41:382959 spdy::INVALID, // Status
[email protected]3f662f12010-03-25 19:56:122960 NULL, // Data
2961 0, // Data Length
2962 spdy::DATA_FLAG_NONE // Data Flags
2963 };
2964 // Modify the following data to change/add test cases:
2965 struct SynReplyTests {
2966 const SpdyHeaderInfo* syn_reply;
2967 bool vary_matches;
2968 int num_headers[2];
2969 const char* extra_headers[2][16];
2970 } test_cases[] = {
2971 // Test the case of a multi-valued cookie. When the value is delimited
2972 // with NUL characters, it needs to be unfolded into multiple headers.
2973 {
2974 &syn_reply_info,
2975 true,
[email protected]8c76ae22010-04-20 22:15:432976 { 1, 4 },
2977 { { "cookie", "val1,val2",
[email protected]3f662f12010-03-25 19:56:122978 NULL
2979 },
2980 { "vary", "cookie",
2981 "status", "200",
2982 "url", "/index.php",
2983 "version", "HTTP/1.1",
2984 NULL
2985 }
2986 }
2987 }, { // Multiple vary fields.
2988 &syn_reply_info,
2989 true,
2990 { 2, 5 },
2991 { { "friend", "barney",
2992 "enemy", "snaggletooth",
2993 NULL
2994 },
2995 { "vary", "friend",
2996 "vary", "enemy",
2997 "status", "200",
2998 "url", "/index.php",
2999 "version", "HTTP/1.1",
3000 NULL
3001 }
3002 }
3003 }, { // Test a '*' vary field.
3004 &syn_reply_info,
3005 false,
3006 { 1, 4 },
3007 { { "cookie", "val1,val2",
3008 NULL
3009 },
3010 { "vary", "*",
3011 "status", "200",
3012 "url", "/index.php",
3013 "version", "HTTP/1.1",
3014 NULL
3015 }
3016 }
3017 }, { // Multiple comma-separated vary fields.
3018 &syn_reply_info,
3019 true,
3020 { 2, 4 },
3021 { { "friend", "barney",
3022 "enemy", "snaggletooth",
3023 NULL
3024 },
3025 { "vary", "friend,enemy",
3026 "status", "200",
3027 "url", "/index.php",
3028 "version", "HTTP/1.1",
3029 NULL
3030 }
3031 }
3032 }
3033 };
3034
3035 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
[email protected]3f662f12010-03-25 19:56:123036 // Construct the request.
3037 scoped_ptr<spdy::SpdyFrame> frame_req(
3038 ConstructSpdyGet(test_cases[i].extra_headers[0],
[email protected]2bd93022010-07-17 00:58:443039 test_cases[i].num_headers[0],
3040 false, 1, LOWEST));
[email protected]3f662f12010-03-25 19:56:123041
3042 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:133043 CreateMockWrite(*frame_req),
[email protected]3f662f12010-03-25 19:56:123044 };
3045
3046 // Construct the reply.
3047 scoped_ptr<spdy::SpdyFrame> frame_reply(
[email protected]a4aeaf42010-06-30 19:57:283048 ConstructSpdyPacket(*test_cases[i].syn_reply,
[email protected]3f662f12010-03-25 19:56:123049 test_cases[i].extra_headers[1],
3050 test_cases[i].num_headers[1],
3051 NULL,
3052 0));
3053
[email protected]2bd93022010-07-17 00:58:443054 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]3f662f12010-03-25 19:56:123055 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133056 CreateMockRead(*frame_reply),
3057 CreateMockRead(*body),
[email protected]3f662f12010-03-25 19:56:123058 MockRead(true, 0, 0) // EOF
3059 };
3060
[email protected]3f662f12010-03-25 19:56:123061 // Attach the headers to the request.
[email protected]8c76ae22010-04-20 22:15:433062 int header_count = test_cases[i].num_headers[0];
[email protected]3f662f12010-03-25 19:56:123063
[email protected]d3cee19d2010-06-22 18:42:183064 HttpRequestInfo request = CreateGetRequest();
[email protected]8c76ae22010-04-20 22:15:433065 for (int ct = 0; ct < header_count; ct++) {
3066 const char* header_key = test_cases[i].extra_headers[0][ct * 2];
3067 const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1];
3068 request.extra_headers.SetHeader(header_key, header_value);
[email protected]3f662f12010-03-25 19:56:123069 }
3070
3071 scoped_refptr<DelayedSocketData> data(
3072 new DelayedSocketData(1, reads, arraysize(reads),
3073 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:473074 NormalSpdyTransactionHelper helper(request,
[email protected]9e9e842e2010-07-23 23:09:153075 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:473076 helper.RunToCompletion(data.get());
3077 TransactionHelperResult out = helper.output();
3078
[email protected]3f662f12010-03-25 19:56:123079 EXPECT_EQ(OK, out.rv) << i;
3080 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line) << i;
3081 EXPECT_EQ("hello!", out.response_data) << i;
3082
3083 // Test the response information.
3084 EXPECT_TRUE(out.response_info.response_time >
3085 out.response_info.request_time) << i;
3086 base::TimeDelta test_delay = out.response_info.response_time -
3087 out.response_info.request_time;
3088 base::TimeDelta min_expected_delay;
3089 min_expected_delay.FromMilliseconds(10);
3090 EXPECT_GT(test_delay.InMillisecondsF(),
3091 min_expected_delay.InMillisecondsF()) << i;
3092 EXPECT_EQ(out.response_info.vary_data.is_valid(),
3093 test_cases[i].vary_matches) << i;
3094
3095 // Check the headers.
3096 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3097 ASSERT_TRUE(headers.get() != NULL) << i;
3098 void* iter = NULL;
3099 std::string name, value, lines;
3100 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3101 lines.append(name);
3102 lines.append(": ");
3103 lines.append(value);
3104 lines.append("\n");
3105 }
3106
3107 // Construct the expected header reply string.
3108 char reply_buffer[256] = "";
[email protected]75f30cc22010-06-28 21:41:383109 ConstructSpdyReplyString(test_cases[i].extra_headers[1],
3110 test_cases[i].num_headers[1],
3111 reply_buffer,
3112 256);
[email protected]3f662f12010-03-25 19:56:123113
3114 EXPECT_EQ(std::string(reply_buffer), lines) << i;
3115 }
3116}
3117
[email protected]dd11b932009-11-30 19:39:483118// Verify that we don't crash on invalid SynReply responses.
[email protected]9e9e842e2010-07-23 23:09:153119TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) {
[email protected]e7f75092010-07-01 22:39:133120 const SpdyHeaderInfo kSynStartHeader = {
3121 spdy::SYN_REPLY, // Kind = SynReply
3122 1, // Stream ID
3123 0, // Associated stream ID
[email protected]c9c6f5c2010-07-31 01:30:033124 net::ConvertRequestPriorityToSpdyPriority(LOWEST),
3125 // Priority
[email protected]e7f75092010-07-01 22:39:133126 spdy::CONTROL_FLAG_NONE, // Control Flags
3127 false, // Compressed
3128 spdy::INVALID, // Status
3129 NULL, // Data
3130 0, // Length
3131 spdy::DATA_FLAG_NONE // Data Flags
[email protected]dd11b932009-11-30 19:39:483132 };
3133
[email protected]e7f75092010-07-01 22:39:133134 struct InvalidSynReplyTests {
3135 int num_headers;
3136 const char* headers[10];
[email protected]dd11b932009-11-30 19:39:483137 } test_cases[] = {
[email protected]e7f75092010-07-01 22:39:133138 // SYN_REPLY missing status header
3139 { 4,
3140 { "cookie", "val1",
3141 "cookie", "val2",
3142 "url", "/index.php",
3143 "version", "HTTP/1.1",
3144 NULL
3145 },
3146 },
3147 // SYN_REPLY missing version header
3148 { 2,
3149 { "status", "200",
3150 "url", "/index.php",
3151 NULL
3152 },
3153 },
[email protected]0d384bb2010-07-14 01:51:123154 // SYN_REPLY with no headers
3155 { 0, { NULL }, },
[email protected]dd11b932009-11-30 19:39:483156 };
3157
3158 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
[email protected]2bd93022010-07-17 00:58:443159 scoped_ptr<spdy::SpdyFrame> req(
3160 ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]dd11b932009-11-30 19:39:483161 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:133162 CreateMockWrite(*req),
[email protected]dd11b932009-11-30 19:39:483163 };
3164
[email protected]e7f75092010-07-01 22:39:133165 scoped_ptr<spdy::SpdyFrame> resp(
3166 ConstructSpdyPacket(kSynStartHeader,
3167 NULL, 0,
3168 test_cases[i].headers,
3169 test_cases[i].num_headers));
[email protected]2bd93022010-07-17 00:58:443170 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]dd11b932009-11-30 19:39:483171 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133172 CreateMockRead(*resp),
3173 CreateMockRead(*body),
[email protected]dd11b932009-11-30 19:39:483174 MockRead(true, 0, 0) // EOF
3175 };
3176
[email protected]dd11b932009-11-30 19:39:483177 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:393178 new DelayedSocketData(1, reads, arraysize(reads),
3179 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:473180 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:153181 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:473182 helper.RunToCompletion(data.get());
3183 TransactionHelperResult out = helper.output();
[email protected]dd11b932009-11-30 19:39:483184 EXPECT_EQ(ERR_INVALID_RESPONSE, out.rv);
3185 }
3186}
3187
[email protected]94d78132010-01-22 00:53:003188// Verify that we don't crash on some corrupt frames.
[email protected]6f0a3f42010-07-08 21:44:443189// TODO(eroman): Renable this test, see http://crbug.com/48588
[email protected]9e9e842e2010-07-23 23:09:153190TEST_P(SpdyNetworkTransactionTest, DISABLED_CorruptFrameSessionError) {
[email protected]e7f75092010-07-01 22:39:133191 // This is the length field with a big number
3192 scoped_ptr<spdy::SpdyFrame> syn_reply_massive_length(
[email protected]2bd93022010-07-17 00:58:443193 ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]e7f75092010-07-01 22:39:133194 syn_reply_massive_length->set_length(0x111126);
[email protected]94d78132010-01-22 00:53:003195
3196 struct SynReplyTests {
[email protected]e7f75092010-07-01 22:39:133197 const spdy::SpdyFrame* syn_reply;
[email protected]94d78132010-01-22 00:53:003198 } test_cases[] = {
[email protected]e7f75092010-07-01 22:39:133199 { syn_reply_massive_length.get(), },
[email protected]94d78132010-01-22 00:53:003200 };
3201
3202 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
[email protected]2bd93022010-07-17 00:58:443203 scoped_ptr<spdy::SpdyFrame> req(
3204 ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]94d78132010-01-22 00:53:003205 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:133206 CreateMockWrite(*req),
[email protected]94d78132010-01-22 00:53:003207 MockWrite(true, 0, 0) // EOF
3208 };
3209
[email protected]2bd93022010-07-17 00:58:443210 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]94d78132010-01-22 00:53:003211 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133212 CreateMockRead(*test_cases[i].syn_reply),
3213 CreateMockRead(*body),
[email protected]94d78132010-01-22 00:53:003214 MockRead(true, 0, 0) // EOF
3215 };
3216
[email protected]94d78132010-01-22 00:53:003217 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:393218 new DelayedSocketData(1, reads, arraysize(reads),
3219 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:473220 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:153221 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:473222 helper.RunToCompletion(data.get());
3223 TransactionHelperResult out = helper.output();
[email protected]955fc2e72010-02-08 20:37:303224 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]94d78132010-01-22 00:53:003225 }
3226}
3227
[email protected]bf2491a92009-11-29 16:39:483228// Test that we shutdown correctly on write errors.
[email protected]b2776002010-09-10 23:08:493229TEST_P(SpdyNetworkTransactionTest, WriteError) {
[email protected]2bd93022010-07-17 00:58:443230 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]bf2491a92009-11-29 16:39:483231 MockWrite writes[] = {
3232 // We'll write 10 bytes successfully
[email protected]75f30cc22010-06-28 21:41:383233 MockWrite(true, req->data(), 10),
[email protected]bf2491a92009-11-29 16:39:483234 // Followed by ERROR!
3235 MockWrite(true, ERR_FAILED),
[email protected]bf2491a92009-11-29 16:39:483236 };
3237
[email protected]bf2491a92009-11-29 16:39:483238 scoped_refptr<DelayedSocketData> data(
[email protected]3caf5542010-07-16 15:19:473239 new DelayedSocketData(2, NULL, 0,
[email protected]31a2bfe2010-02-09 08:03:393240 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:473241 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:153242 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:473243 helper.RunToCompletion(data.get());
3244 TransactionHelperResult out = helper.output();
[email protected]bf2491a92009-11-29 16:39:483245 EXPECT_EQ(ERR_FAILED, out.rv);
[email protected]32100cb2009-11-30 18:24:463246 data->Reset();
[email protected]bf2491a92009-11-29 16:39:483247}
3248
3249// Test that partial writes work.
[email protected]9e9e842e2010-07-23 23:09:153250TEST_P(SpdyNetworkTransactionTest, PartialWrite) {
[email protected]bf2491a92009-11-29 16:39:483251 // Chop the SYN_STREAM frame into 5 chunks.
[email protected]2bd93022010-07-17 00:58:443252 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]bf2491a92009-11-29 16:39:483253 const int kChunks = 5;
[email protected]e7f75092010-07-01 22:39:133254 scoped_array<MockWrite> writes(ChopWriteFrame(*req.get(), kChunks));
[email protected]bf2491a92009-11-29 16:39:483255
[email protected]2bd93022010-07-17 00:58:443256 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
3257 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]bf2491a92009-11-29 16:39:483258 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133259 CreateMockRead(*resp),
3260 CreateMockRead(*body),
[email protected]bf2491a92009-11-29 16:39:483261 MockRead(true, 0, 0) // EOF
3262 };
3263
[email protected]bf2491a92009-11-29 16:39:483264 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:393265 new DelayedSocketData(kChunks, reads, arraysize(reads),
3266 writes.get(), kChunks));
[email protected]3caf5542010-07-16 15:19:473267 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:153268 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:473269 helper.RunToCompletion(data.get());
3270 TransactionHelperResult out = helper.output();
[email protected]bf2491a92009-11-29 16:39:483271 EXPECT_EQ(OK, out.rv);
3272 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3273 EXPECT_EQ("hello!", out.response_data);
3274}
3275
[email protected]94d78132010-01-22 00:53:003276// In this test, we enable compression, but get a uncompressed SynReply from
3277// the server. Verify that teardown is all clean.
[email protected]9e9e842e2010-07-23 23:09:153278TEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) {
[email protected]a4aeaf42010-06-30 19:57:283279 // For this test, we turn on the normal compression.
3280 EnableCompression(true);
3281
[email protected]2bd93022010-07-17 00:58:443282 scoped_ptr<spdy::SpdyFrame> compressed(
3283 ConstructSpdyGet(NULL, 0, true, 1, LOWEST));
[email protected]6c6ea172010-07-27 20:04:033284 scoped_ptr<spdy::SpdyFrame> rst(
3285 ConstructSpdyRstStream(1, spdy::PROTOCOL_ERROR));
[email protected]94d78132010-01-22 00:53:003286 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:133287 CreateMockWrite(*compressed),
[email protected]6c6ea172010-07-27 20:04:033288 CreateMockWrite(*rst),
[email protected]94d78132010-01-22 00:53:003289 };
3290
[email protected]2bd93022010-07-17 00:58:443291 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
3292 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]94d78132010-01-22 00:53:003293 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133294 CreateMockRead(*resp),
3295 CreateMockRead(*body),
[email protected]58cebf8f2010-07-31 19:20:163296 MockRead(true, 0, 0)
[email protected]94d78132010-01-22 00:53:003297 };
3298
[email protected]94d78132010-01-22 00:53:003299 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:393300 new DelayedSocketData(1, reads, arraysize(reads),
3301 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:473302 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:153303 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:473304 helper.RunToCompletion(data.get());
3305 TransactionHelperResult out = helper.output();
[email protected]6c6ea172010-07-27 20:04:033306 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]94d78132010-01-22 00:53:003307 data->Reset();
3308
3309 EnableCompression(false);
3310}
3311
[email protected]9e743cd2010-03-16 07:03:533312// Test that the NetLog contains good data for a simple GET request.
[email protected]9e9e842e2010-07-23 23:09:153313TEST_P(SpdyNetworkTransactionTest, NetLog) {
[email protected]3deb9a52010-11-11 00:24:403314 static const char* const kExtraHeaders[] = {
3315 "user-agent", "Chrome",
3316 };
3317 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(kExtraHeaders, 1, false, 1,
3318 LOWEST));
[email protected]e7f75092010-07-01 22:39:133319 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]dac358042009-12-18 02:07:483320
[email protected]2bd93022010-07-17 00:58:443321 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
3322 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]dac358042009-12-18 02:07:483323 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133324 CreateMockRead(*resp),
3325 CreateMockRead(*body),
[email protected]dac358042009-12-18 02:07:483326 MockRead(true, 0, 0) // EOF
3327 };
3328
[email protected]9e743cd2010-03-16 07:03:533329 net::CapturingBoundNetLog log(net::CapturingNetLog::kUnbounded);
[email protected]dac358042009-12-18 02:07:483330
[email protected]dac358042009-12-18 02:07:483331 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:393332 new DelayedSocketData(1, reads, arraysize(reads),
3333 writes, arraysize(writes)));
[email protected]3deb9a52010-11-11 00:24:403334 NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(),
[email protected]9e9e842e2010-07-23 23:09:153335 log.bound(), GetParam());
[email protected]3caf5542010-07-16 15:19:473336 helper.RunToCompletion(data.get());
3337 TransactionHelperResult out = helper.output();
[email protected]dac358042009-12-18 02:07:483338 EXPECT_EQ(OK, out.rv);
3339 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3340 EXPECT_EQ("hello!", out.response_data);
3341
[email protected]9e743cd2010-03-16 07:03:533342 // Check that the NetLog was filled reasonably.
[email protected]3caf5542010-07-16 15:19:473343 // This test is intentionally non-specific about the exact ordering of the
3344 // log; instead we just check to make sure that certain events exist, and that
3345 // they are in the right order.
[email protected]b2fcd0e2010-12-01 15:19:403346 net::CapturingNetLog::EntryList entries;
3347 log.GetEntries(&entries);
3348
3349 EXPECT_LT(0u, entries.size());
[email protected]dac358042009-12-18 02:07:483350 int pos = 0;
[email protected]b2fcd0e2010-12-01 15:19:403351 pos = net::ExpectLogContainsSomewhere(entries, 0,
[email protected]351ab642010-08-05 16:55:313352 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
[email protected]9e743cd2010-03-16 07:03:533353 net::NetLog::PHASE_BEGIN);
[email protected]b2fcd0e2010-12-01 15:19:403354 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
[email protected]351ab642010-08-05 16:55:313355 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
[email protected]9e743cd2010-03-16 07:03:533356 net::NetLog::PHASE_END);
[email protected]b2fcd0e2010-12-01 15:19:403357 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
[email protected]351ab642010-08-05 16:55:313358 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
[email protected]9e743cd2010-03-16 07:03:533359 net::NetLog::PHASE_BEGIN);
[email protected]b2fcd0e2010-12-01 15:19:403360 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
[email protected]351ab642010-08-05 16:55:313361 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
[email protected]9e743cd2010-03-16 07:03:533362 net::NetLog::PHASE_END);
[email protected]b2fcd0e2010-12-01 15:19:403363 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
[email protected]351ab642010-08-05 16:55:313364 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
[email protected]9e743cd2010-03-16 07:03:533365 net::NetLog::PHASE_BEGIN);
[email protected]b2fcd0e2010-12-01 15:19:403366 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
[email protected]351ab642010-08-05 16:55:313367 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
[email protected]9e743cd2010-03-16 07:03:533368 net::NetLog::PHASE_END);
[email protected]3deb9a52010-11-11 00:24:403369
3370 // Check that we logged all the headers correctly
3371 pos = net::ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:403372 entries, 0,
[email protected]3deb9a52010-11-11 00:24:403373 net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM,
3374 net::NetLog::PHASE_NONE);
[email protected]b2fcd0e2010-12-01 15:19:403375 CapturingNetLog::Entry entry = entries[pos];
[email protected]3deb9a52010-11-11 00:24:403376 NetLogSpdySynParameter* request_params =
3377 static_cast<NetLogSpdySynParameter*>(entry.extra_parameters.get());
3378 spdy::SpdyHeaderBlock* headers =
3379 request_params->GetHeaders().get();
3380
3381 spdy::SpdyHeaderBlock expected;
3382 expected["host"] = "www.google.com";
3383 expected["url"] = "/";
3384 expected["scheme"] = "http";
3385 expected["version"] = "HTTP/1.1";
3386 expected["method"] = "GET";
3387 expected["user-agent"] = "Chrome";
3388 EXPECT_EQ(expected.size(), headers->size());
3389 spdy::SpdyHeaderBlock::const_iterator end = expected.end();
3390 for (spdy::SpdyHeaderBlock::const_iterator it = expected.begin();
3391 it != end;
3392 ++it) {
3393 EXPECT_EQ(it->second, (*headers)[it->first]);
3394 }
[email protected]dac358042009-12-18 02:07:483395}
3396
[email protected]79d84222010-02-26 00:01:443397// Since we buffer the IO from the stream to the renderer, this test verifies
3398// that when we read out the maximum amount of data (e.g. we received 50 bytes
3399// on the network, but issued a Read for only 5 of those bytes) that the data
3400// flow still works correctly.
[email protected]9e9e842e2010-07-23 23:09:153401TEST_P(SpdyNetworkTransactionTest, BufferFull) {
[email protected]20d005f2010-07-02 19:55:433402 spdy::SpdyFramer framer;
3403
[email protected]2bd93022010-07-17 00:58:443404 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:133405 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]79d84222010-02-26 00:01:443406
[email protected]20d005f2010-07-02 19:55:433407 // 2 data frames in a single read.
3408 scoped_ptr<spdy::SpdyFrame> data_frame_1(
3409 framer.CreateDataFrame(1, "goodby", 6, spdy::DATA_FLAG_NONE));
3410 scoped_ptr<spdy::SpdyFrame> data_frame_2(
3411 framer.CreateDataFrame(1, "e worl", 6, spdy::DATA_FLAG_NONE));
3412 const spdy::SpdyFrame* data_frames[2] = {
3413 data_frame_1.get(),
3414 data_frame_2.get(),
[email protected]79d84222010-02-26 00:01:443415 };
[email protected]20d005f2010-07-02 19:55:433416 char combined_data_frames[100];
3417 int combined_data_frames_len =
3418 CombineFrames(data_frames, arraysize(data_frames),
3419 combined_data_frames, arraysize(combined_data_frames));
3420 scoped_ptr<spdy::SpdyFrame> last_frame(
3421 framer.CreateDataFrame(1, "d", 1, spdy::DATA_FLAG_FIN));
[email protected]79d84222010-02-26 00:01:443422
[email protected]2bd93022010-07-17 00:58:443423 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]79d84222010-02-26 00:01:443424 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133425 CreateMockRead(*resp),
[email protected]79d84222010-02-26 00:01:443426 MockRead(true, ERR_IO_PENDING), // Force a pause
[email protected]20d005f2010-07-02 19:55:433427 MockRead(true, combined_data_frames, combined_data_frames_len),
[email protected]79d84222010-02-26 00:01:443428 MockRead(true, ERR_IO_PENDING), // Force a pause
[email protected]20d005f2010-07-02 19:55:433429 CreateMockRead(*last_frame),
[email protected]79d84222010-02-26 00:01:443430 MockRead(true, 0, 0) // EOF
3431 };
3432
[email protected]79d84222010-02-26 00:01:443433 scoped_refptr<DelayedSocketData> data(
3434 new DelayedSocketData(1, reads, arraysize(reads),
3435 writes, arraysize(writes)));
3436
[email protected]79d84222010-02-26 00:01:443437
3438 TestCompletionCallback callback;
3439
[email protected]3caf5542010-07-16 15:19:473440 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:153441 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:473442 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:583443 helper.AddData(data.get());
[email protected]3caf5542010-07-16 15:19:473444 HttpNetworkTransaction* trans = helper.trans();
[email protected]d3cee19d2010-06-22 18:42:183445 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
[email protected]79d84222010-02-26 00:01:443446 EXPECT_EQ(ERR_IO_PENDING, rv);
3447
[email protected]3caf5542010-07-16 15:19:473448 TransactionHelperResult out = helper.output();
[email protected]79d84222010-02-26 00:01:443449 out.rv = callback.WaitForResult();
3450 EXPECT_EQ(out.rv, OK);
3451
3452 const HttpResponseInfo* response = trans->GetResponseInfo();
3453 EXPECT_TRUE(response->headers != NULL);
3454 EXPECT_TRUE(response->was_fetched_via_spdy);
3455 out.status_line = response->headers->GetStatusLine();
3456 out.response_info = *response; // Make a copy so we can verify.
3457
3458 // Read Data
3459 TestCompletionCallback read_callback;
3460
3461 std::string content;
3462 do {
3463 // Read small chunks at a time.
3464 const int kSmallReadSize = 3;
[email protected]ad8e04a2010-11-01 04:16:273465 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
[email protected]79d84222010-02-26 00:01:443466 rv = trans->Read(buf, kSmallReadSize, &read_callback);
3467 if (rv == net::ERR_IO_PENDING) {
3468 data->CompleteRead();
3469 rv = read_callback.WaitForResult();
3470 }
3471 if (rv > 0) {
3472 content.append(buf->data(), rv);
3473 } else if (rv < 0) {
3474 NOTREACHED();
3475 }
3476 } while (rv > 0);
3477
3478 out.response_data.swap(content);
3479
[email protected]30c942b2010-07-21 16:59:593480 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553481 // MockClientSocketFactory) are still alive.
3482 MessageLoop::current()->RunAllPending();
3483
[email protected]79d84222010-02-26 00:01:443484 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473485 helper.VerifyDataConsumed();
[email protected]79d84222010-02-26 00:01:443486
3487 EXPECT_EQ(OK, out.rv);
3488 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3489 EXPECT_EQ("goodbye world", out.response_data);
3490}
3491
[email protected]9e9e842e2010-07-23 23:09:153492TEST_P(SpdyNetworkTransactionTest, ConnectFailureFallbackToHttp) {
[email protected]e6b06862010-07-20 16:32:583493 MockConnect connects[] = {
3494 MockConnect(true, ERR_NAME_NOT_RESOLVED),
3495 MockConnect(false, ERR_NAME_NOT_RESOLVED),
3496 MockConnect(true, ERR_INTERNET_DISCONNECTED),
3497 MockConnect(false, ERR_INTERNET_DISCONNECTED)
3498 };
3499
3500 for (size_t index = 0; index < arraysize(connects); ++index) {
3501 scoped_ptr<spdy::SpdyFrame> req(
3502 ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3503 MockWrite writes[] = {
3504 CreateMockWrite(*req),
3505 MockWrite(true, 0, 0) // EOF
3506 };
3507
3508 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
3509 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3510 MockRead reads[] = {
3511 CreateMockRead(*resp),
3512 CreateMockRead(*body),
3513 MockRead(true, 0, 0) // EOF
3514 };
3515
3516 scoped_refptr<DelayedSocketData> data(
3517 new DelayedSocketData(connects[index], 1, reads, arraysize(reads),
3518 writes, arraysize(writes)));
3519 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:153520 BoundNetLog(), GetParam());
[email protected]e6b06862010-07-20 16:32:583521 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:583522 helper.AddData(data.get());
[email protected]e6b06862010-07-20 16:32:583523
3524 // Set up http fallback data.
3525 MockRead http_fallback_data[] = {
3526 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
3527 MockRead("hello world!!!"),
3528 MockRead(true, OK),
3529 };
3530
3531 scoped_ptr<StaticSocketDataProvider> http_fallback(
3532 new StaticSocketDataProvider(http_fallback_data,
3533 arraysize(http_fallback_data),
3534 NULL, 0));
3535 helper.AddDataNoSSL(http_fallback.get());
3536 HttpNetworkTransaction* trans = helper.trans();
3537 TestCompletionCallback callback;
3538
3539 int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
3540 EXPECT_EQ(rv, ERR_IO_PENDING);
3541 rv = callback.WaitForResult();
3542 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]9e9e842e2010-07-23 23:09:153543 if (GetParam() == SPDYNOSSL || GetParam() == SPDYSSL) {
3544 ASSERT_TRUE(response == NULL);
3545 return;
3546 }
3547 if (GetParam() != SPDYNPN)
3548 NOTREACHED();
[email protected]e6b06862010-07-20 16:32:583549 ASSERT_TRUE(response != NULL);
3550 ASSERT_TRUE(response->headers != NULL);
3551 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3552 std::string response_data;
3553 rv = ReadTransaction(trans, &response_data);
3554 EXPECT_EQ(OK, rv);
3555
3556 EXPECT_TRUE(!response->was_fetched_via_spdy);
3557 EXPECT_TRUE(!response->was_npn_negotiated);
3558 EXPECT_TRUE(response->was_alternate_protocol_available);
3559 EXPECT_TRUE(http_fallback->at_read_eof());
3560 EXPECT_EQ(0u, data->read_index());
3561 EXPECT_EQ(0u, data->write_index());
3562 EXPECT_EQ("hello world!!!", response_data);
3563 }
3564}
3565
[email protected]8918d282010-03-02 00:57:553566// Verify that basic buffering works; when multiple data frames arrive
3567// at the same time, ensure that we don't notify a read completion for
3568// each data frame individually.
[email protected]9e9e842e2010-07-23 23:09:153569TEST_P(SpdyNetworkTransactionTest, Buffering) {
[email protected]20d005f2010-07-02 19:55:433570 spdy::SpdyFramer framer;
3571
[email protected]2bd93022010-07-17 00:58:443572 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:133573 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]8918d282010-03-02 00:57:553574
3575 // 4 data frames in a single read.
[email protected]20d005f2010-07-02 19:55:433576 scoped_ptr<spdy::SpdyFrame> data_frame(
3577 framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE));
3578 scoped_ptr<spdy::SpdyFrame> data_frame_fin(
3579 framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_FIN));
3580 const spdy::SpdyFrame* data_frames[4] = {
3581 data_frame.get(),
3582 data_frame.get(),
3583 data_frame.get(),
3584 data_frame_fin.get()
[email protected]8918d282010-03-02 00:57:553585 };
[email protected]20d005f2010-07-02 19:55:433586 char combined_data_frames[100];
3587 int combined_data_frames_len =
3588 CombineFrames(data_frames, arraysize(data_frames),
3589 combined_data_frames, arraysize(combined_data_frames));
[email protected]8918d282010-03-02 00:57:553590
[email protected]2bd93022010-07-17 00:58:443591 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8918d282010-03-02 00:57:553592 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133593 CreateMockRead(*resp),
[email protected]8918d282010-03-02 00:57:553594 MockRead(true, ERR_IO_PENDING), // Force a pause
[email protected]20d005f2010-07-02 19:55:433595 MockRead(true, combined_data_frames, combined_data_frames_len),
[email protected]8918d282010-03-02 00:57:553596 MockRead(true, 0, 0) // EOF
3597 };
3598
[email protected]8918d282010-03-02 00:57:553599 scoped_refptr<DelayedSocketData> data(
3600 new DelayedSocketData(1, reads, arraysize(reads),
3601 writes, arraysize(writes)));
3602
[email protected]3caf5542010-07-16 15:19:473603 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:153604 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:473605 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:583606 helper.AddData(data.get());
[email protected]3caf5542010-07-16 15:19:473607 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:553608
3609 TestCompletionCallback callback;
[email protected]d3cee19d2010-06-22 18:42:183610 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
[email protected]8918d282010-03-02 00:57:553611 EXPECT_EQ(ERR_IO_PENDING, rv);
3612
[email protected]3caf5542010-07-16 15:19:473613 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:553614 out.rv = callback.WaitForResult();
3615 EXPECT_EQ(out.rv, OK);
3616
3617 const HttpResponseInfo* response = trans->GetResponseInfo();
3618 EXPECT_TRUE(response->headers != NULL);
3619 EXPECT_TRUE(response->was_fetched_via_spdy);
3620 out.status_line = response->headers->GetStatusLine();
3621 out.response_info = *response; // Make a copy so we can verify.
3622
3623 // Read Data
3624 TestCompletionCallback read_callback;
3625
3626 std::string content;
3627 int reads_completed = 0;
3628 do {
3629 // Read small chunks at a time.
3630 const int kSmallReadSize = 14;
[email protected]ad8e04a2010-11-01 04:16:273631 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
[email protected]8918d282010-03-02 00:57:553632 rv = trans->Read(buf, kSmallReadSize, &read_callback);
3633 if (rv == net::ERR_IO_PENDING) {
3634 data->CompleteRead();
3635 rv = read_callback.WaitForResult();
3636 }
3637 if (rv > 0) {
3638 EXPECT_EQ(kSmallReadSize, rv);
3639 content.append(buf->data(), rv);
3640 } else if (rv < 0) {
3641 FAIL() << "Unexpected read error: " << rv;
3642 }
3643 reads_completed++;
3644 } while (rv > 0);
3645
3646 EXPECT_EQ(3, reads_completed); // Reads are: 14 bytes, 14 bytes, 0 bytes.
3647
3648 out.response_data.swap(content);
3649
[email protected]30c942b2010-07-21 16:59:593650 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553651 // MockClientSocketFactory) are still alive.
3652 MessageLoop::current()->RunAllPending();
3653
3654 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473655 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:553656
3657 EXPECT_EQ(OK, out.rv);
3658 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3659 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3660}
3661
3662// Verify the case where we buffer data but read it after it has been buffered.
[email protected]9e9e842e2010-07-23 23:09:153663TEST_P(SpdyNetworkTransactionTest, BufferedAll) {
[email protected]20d005f2010-07-02 19:55:433664 spdy::SpdyFramer framer;
3665
[email protected]2bd93022010-07-17 00:58:443666 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:133667 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]8918d282010-03-02 00:57:553668
[email protected]20d005f2010-07-02 19:55:433669 // 5 data frames in a single read.
3670 scoped_ptr<spdy::SpdyFrame> syn_reply(
[email protected]2bd93022010-07-17 00:58:443671 ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]20d005f2010-07-02 19:55:433672 syn_reply->set_flags(spdy::CONTROL_FLAG_NONE); // turn off FIN bit
3673 scoped_ptr<spdy::SpdyFrame> data_frame(
3674 framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE));
3675 scoped_ptr<spdy::SpdyFrame> data_frame_fin(
3676 framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_FIN));
3677 const spdy::SpdyFrame* frames[5] = {
3678 syn_reply.get(),
3679 data_frame.get(),
3680 data_frame.get(),
3681 data_frame.get(),
3682 data_frame_fin.get()
[email protected]8918d282010-03-02 00:57:553683 };
[email protected]20d005f2010-07-02 19:55:433684 char combined_frames[200];
3685 int combined_frames_len =
3686 CombineFrames(frames, arraysize(frames),
3687 combined_frames, arraysize(combined_frames));
[email protected]8918d282010-03-02 00:57:553688
3689 MockRead reads[] = {
[email protected]20d005f2010-07-02 19:55:433690 MockRead(true, combined_frames, combined_frames_len),
[email protected]8918d282010-03-02 00:57:553691 MockRead(true, 0, 0) // EOF
3692 };
3693
[email protected]8918d282010-03-02 00:57:553694 scoped_refptr<DelayedSocketData> data(
3695 new DelayedSocketData(1, reads, arraysize(reads),
3696 writes, arraysize(writes)));
3697
[email protected]3caf5542010-07-16 15:19:473698 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:153699 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:473700 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:583701 helper.AddData(data.get());
[email protected]3caf5542010-07-16 15:19:473702 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:553703
3704 TestCompletionCallback callback;
[email protected]d3cee19d2010-06-22 18:42:183705 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
[email protected]8918d282010-03-02 00:57:553706 EXPECT_EQ(ERR_IO_PENDING, rv);
3707
[email protected]3caf5542010-07-16 15:19:473708 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:553709 out.rv = callback.WaitForResult();
3710 EXPECT_EQ(out.rv, OK);
3711
3712 const HttpResponseInfo* response = trans->GetResponseInfo();
3713 EXPECT_TRUE(response->headers != NULL);
3714 EXPECT_TRUE(response->was_fetched_via_spdy);
3715 out.status_line = response->headers->GetStatusLine();
3716 out.response_info = *response; // Make a copy so we can verify.
3717
3718 // Read Data
3719 TestCompletionCallback read_callback;
3720
3721 std::string content;
3722 int reads_completed = 0;
3723 do {
3724 // Read small chunks at a time.
3725 const int kSmallReadSize = 14;
[email protected]ad8e04a2010-11-01 04:16:273726 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
[email protected]8918d282010-03-02 00:57:553727 rv = trans->Read(buf, kSmallReadSize, &read_callback);
3728 if (rv > 0) {
3729 EXPECT_EQ(kSmallReadSize, rv);
3730 content.append(buf->data(), rv);
3731 } else if (rv < 0) {
3732 FAIL() << "Unexpected read error: " << rv;
3733 }
3734 reads_completed++;
3735 } while (rv > 0);
3736
3737 EXPECT_EQ(3, reads_completed);
3738
3739 out.response_data.swap(content);
3740
[email protected]30c942b2010-07-21 16:59:593741 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553742 // MockClientSocketFactory) are still alive.
3743 MessageLoop::current()->RunAllPending();
3744
3745 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473746 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:553747
3748 EXPECT_EQ(OK, out.rv);
3749 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3750 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3751}
3752
3753// Verify the case where we buffer data and close the connection.
[email protected]9e9e842e2010-07-23 23:09:153754TEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
[email protected]20d005f2010-07-02 19:55:433755 spdy::SpdyFramer framer;
3756
[email protected]2bd93022010-07-17 00:58:443757 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:133758 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]8918d282010-03-02 00:57:553759
3760 // All data frames in a single read.
[email protected]20d005f2010-07-02 19:55:433761 // NOTE: We don't FIN the stream.
3762 scoped_ptr<spdy::SpdyFrame> data_frame(
3763 framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE));
3764 const spdy::SpdyFrame* data_frames[4] = {
3765 data_frame.get(),
3766 data_frame.get(),
3767 data_frame.get(),
3768 data_frame.get()
[email protected]8918d282010-03-02 00:57:553769 };
[email protected]20d005f2010-07-02 19:55:433770 char combined_data_frames[100];
3771 int combined_data_frames_len =
3772 CombineFrames(data_frames, arraysize(data_frames),
3773 combined_data_frames, arraysize(combined_data_frames));
[email protected]2bd93022010-07-17 00:58:443774 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8918d282010-03-02 00:57:553775 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133776 CreateMockRead(*resp),
[email protected]8918d282010-03-02 00:57:553777 MockRead(true, ERR_IO_PENDING), // Force a wait
[email protected]20d005f2010-07-02 19:55:433778 MockRead(true, combined_data_frames, combined_data_frames_len),
[email protected]8918d282010-03-02 00:57:553779 MockRead(true, 0, 0) // EOF
3780 };
3781
[email protected]8918d282010-03-02 00:57:553782 scoped_refptr<DelayedSocketData> data(
3783 new DelayedSocketData(1, reads, arraysize(reads),
3784 writes, arraysize(writes)));
3785
[email protected]3caf5542010-07-16 15:19:473786 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:153787 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:473788 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:583789 helper.AddData(data.get());
[email protected]3caf5542010-07-16 15:19:473790 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:553791
3792 TestCompletionCallback callback;
3793
[email protected]d3cee19d2010-06-22 18:42:183794 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
[email protected]8918d282010-03-02 00:57:553795 EXPECT_EQ(ERR_IO_PENDING, rv);
3796
[email protected]3caf5542010-07-16 15:19:473797 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:553798 out.rv = callback.WaitForResult();
3799 EXPECT_EQ(out.rv, OK);
3800
3801 const HttpResponseInfo* response = trans->GetResponseInfo();
3802 EXPECT_TRUE(response->headers != NULL);
3803 EXPECT_TRUE(response->was_fetched_via_spdy);
3804 out.status_line = response->headers->GetStatusLine();
3805 out.response_info = *response; // Make a copy so we can verify.
3806
3807 // Read Data
3808 TestCompletionCallback read_callback;
3809
3810 std::string content;
3811 int reads_completed = 0;
3812 do {
3813 // Read small chunks at a time.
3814 const int kSmallReadSize = 14;
[email protected]ad8e04a2010-11-01 04:16:273815 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
[email protected]8918d282010-03-02 00:57:553816 rv = trans->Read(buf, kSmallReadSize, &read_callback);
3817 if (rv == net::ERR_IO_PENDING) {
3818 data->CompleteRead();
3819 rv = read_callback.WaitForResult();
3820 }
3821 if (rv > 0) {
3822 content.append(buf->data(), rv);
3823 } else if (rv < 0) {
3824 // This test intentionally closes the connection, and will get an error.
3825 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
3826 break;
3827 }
3828 reads_completed++;
3829 } while (rv > 0);
3830
3831 EXPECT_EQ(0, reads_completed);
3832
3833 out.response_data.swap(content);
3834
[email protected]30c942b2010-07-21 16:59:593835 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:553836 // MockClientSocketFactory) are still alive.
3837 MessageLoop::current()->RunAllPending();
3838
3839 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:473840 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:553841}
3842
[email protected]1ed7b3dc2010-03-04 05:41:453843// Verify the case where we buffer data and cancel the transaction.
[email protected]9e9e842e2010-07-23 23:09:153844TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) {
[email protected]20d005f2010-07-02 19:55:433845 spdy::SpdyFramer framer;
3846
[email protected]2bd93022010-07-17 00:58:443847 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:133848 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]1ed7b3dc2010-03-04 05:41:453849
[email protected]20d005f2010-07-02 19:55:433850 // NOTE: We don't FIN the stream.
3851 scoped_ptr<spdy::SpdyFrame> data_frame(
3852 framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE));
[email protected]1ed7b3dc2010-03-04 05:41:453853
[email protected]2bd93022010-07-17 00:58:443854 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]1ed7b3dc2010-03-04 05:41:453855 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133856 CreateMockRead(*resp),
[email protected]1ed7b3dc2010-03-04 05:41:453857 MockRead(true, ERR_IO_PENDING), // Force a wait
[email protected]20d005f2010-07-02 19:55:433858 CreateMockRead(*data_frame),
[email protected]1ed7b3dc2010-03-04 05:41:453859 MockRead(true, 0, 0) // EOF
3860 };
3861
[email protected]1ed7b3dc2010-03-04 05:41:453862 scoped_refptr<DelayedSocketData> data(
3863 new DelayedSocketData(1, reads, arraysize(reads),
3864 writes, arraysize(writes)));
3865
[email protected]3caf5542010-07-16 15:19:473866 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:153867 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:473868 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:583869 helper.AddData(data.get());
[email protected]3caf5542010-07-16 15:19:473870 HttpNetworkTransaction* trans = helper.trans();
[email protected]1ed7b3dc2010-03-04 05:41:453871 TestCompletionCallback callback;
3872
[email protected]d3cee19d2010-06-22 18:42:183873 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
[email protected]1ed7b3dc2010-03-04 05:41:453874 EXPECT_EQ(ERR_IO_PENDING, rv);
3875
[email protected]3caf5542010-07-16 15:19:473876 TransactionHelperResult out = helper.output();
[email protected]1ed7b3dc2010-03-04 05:41:453877 out.rv = callback.WaitForResult();
3878 EXPECT_EQ(out.rv, OK);
3879
3880 const HttpResponseInfo* response = trans->GetResponseInfo();
3881 EXPECT_TRUE(response->headers != NULL);
3882 EXPECT_TRUE(response->was_fetched_via_spdy);
3883 out.status_line = response->headers->GetStatusLine();
3884 out.response_info = *response; // Make a copy so we can verify.
3885
3886 // Read Data
3887 TestCompletionCallback read_callback;
3888
3889 do {
3890 const int kReadSize = 256;
[email protected]ad8e04a2010-11-01 04:16:273891 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kReadSize));
[email protected]1ed7b3dc2010-03-04 05:41:453892 rv = trans->Read(buf, kReadSize, &read_callback);
3893 if (rv == net::ERR_IO_PENDING) {
3894 // Complete the read now, which causes buffering to start.
3895 data->CompleteRead();
3896 // Destroy the transaction, causing the stream to get cancelled
3897 // and orphaning the buffered IO task.
[email protected]3caf5542010-07-16 15:19:473898 helper.ResetTrans();
[email protected]1ed7b3dc2010-03-04 05:41:453899 break;
3900 }
3901 // We shouldn't get here in this test.
3902 FAIL() << "Unexpected read: " << rv;
3903 } while (rv > 0);
3904
3905 // Flush the MessageLoop; this will cause the buffered IO task
3906 // to run for the final time.
3907 MessageLoop::current()->RunAllPending();
[email protected]3caf5542010-07-16 15:19:473908
3909 // Verify that we consumed all test data.
3910 helper.VerifyDataConsumed();
[email protected]1ed7b3dc2010-03-04 05:41:453911}
3912
[email protected]74188f22010-04-09 20:18:503913// Test that if the server requests persistence of settings, that we save
3914// the settings in the SpdySettingsStorage.
[email protected]9e9e842e2010-07-23 23:09:153915TEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
[email protected]74188f22010-04-09 20:18:503916 static const SpdyHeaderInfo kSynReplyInfo = {
3917 spdy::SYN_REPLY, // Syn Reply
3918 1, // Stream ID
3919 0, // Associated Stream ID
[email protected]c9c6f5c2010-07-31 01:30:033920 net::ConvertRequestPriorityToSpdyPriority(LOWEST),
3921 // Priority
[email protected]74188f22010-04-09 20:18:503922 spdy::CONTROL_FLAG_NONE, // Control Flags
3923 false, // Compressed
[email protected]75f30cc22010-06-28 21:41:383924 spdy::INVALID, // Status
[email protected]74188f22010-04-09 20:18:503925 NULL, // Data
3926 0, // Data Length
3927 spdy::DATA_FLAG_NONE // Data Flags
3928 };
3929 static const char* const kExtraHeaders[] = {
3930 "status", "200",
3931 "version", "HTTP/1.1"
3932 };
3933
[email protected]3caf5542010-07-16 15:19:473934 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:153935 BoundNetLog(), GetParam());
[email protected]e3ebba0f2010-08-05 17:59:583936 helper.RunPreTestSetup();
[email protected]74188f22010-04-09 20:18:503937
3938 // Verify that no settings exist initially.
[email protected]9e9e842e2010-07-23 23:09:153939 HostPortPair host_port_pair("www.google.com", helper.port());
[email protected]3caf5542010-07-16 15:19:473940 EXPECT_TRUE(helper.session()->spdy_settings().Get(host_port_pair).empty());
[email protected]74188f22010-04-09 20:18:503941
3942 // Construct the request.
[email protected]2bd93022010-07-17 00:58:443943 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:133944 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]74188f22010-04-09 20:18:503945
3946 // Construct the reply.
3947 scoped_ptr<spdy::SpdyFrame> reply(
[email protected]a4aeaf42010-06-30 19:57:283948 ConstructSpdyPacket(kSynReplyInfo,
[email protected]74188f22010-04-09 20:18:503949 kExtraHeaders,
3950 arraysize(kExtraHeaders) / 2,
3951 NULL,
3952 0));
3953
3954 unsigned int kSampleId1 = 0x1;
3955 unsigned int kSampleValue1 = 0x0a0a0a0a;
3956 unsigned int kSampleId2 = 0x2;
3957 unsigned int kSampleValue2 = 0x0b0b0b0b;
3958 unsigned int kSampleId3 = 0xababab;
3959 unsigned int kSampleValue3 = 0x0c0c0c0c;
3960 scoped_ptr<spdy::SpdyFrame> settings_frame;
3961 {
3962 // Construct the SETTINGS frame.
3963 spdy::SpdySettings settings;
3964 spdy::SettingsFlagsAndId setting(0);
3965 // First add a persisted setting
3966 setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST);
3967 setting.set_id(kSampleId1);
3968 settings.push_back(std::make_pair(setting, kSampleValue1));
3969 // Next add a non-persisted setting
3970 setting.set_flags(0);
3971 setting.set_id(kSampleId2);
3972 settings.push_back(std::make_pair(setting, kSampleValue2));
3973 // Next add another persisted setting
3974 setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST);
3975 setting.set_id(kSampleId3);
3976 settings.push_back(std::make_pair(setting, kSampleValue3));
3977 settings_frame.reset(ConstructSpdySettings(settings));
3978 }
3979
[email protected]2bd93022010-07-17 00:58:443980 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]74188f22010-04-09 20:18:503981 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:133982 CreateMockRead(*reply),
3983 CreateMockRead(*body),
3984 CreateMockRead(*settings_frame),
[email protected]74188f22010-04-09 20:18:503985 MockRead(true, 0, 0) // EOF
3986 };
3987
[email protected]74188f22010-04-09 20:18:503988 scoped_refptr<DelayedSocketData> data(
3989 new DelayedSocketData(1, reads, arraysize(reads),
3990 writes, arraysize(writes)));
[email protected]e3ebba0f2010-08-05 17:59:583991 helper.AddData(data.get());
3992 helper.RunDefaultTest();
3993 helper.VerifyDataConsumed();
[email protected]3caf5542010-07-16 15:19:473994 TransactionHelperResult out = helper.output();
[email protected]74188f22010-04-09 20:18:503995 EXPECT_EQ(OK, out.rv);
3996 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3997 EXPECT_EQ("hello!", out.response_data);
3998
3999 {
4000 // Verify we had two persisted settings.
4001 spdy::SpdySettings saved_settings =
[email protected]3caf5542010-07-16 15:19:474002 helper.session()->spdy_settings().Get(host_port_pair);
[email protected]74188f22010-04-09 20:18:504003 ASSERT_EQ(2u, saved_settings.size());
4004
4005 // Verify the first persisted setting.
4006 spdy::SpdySetting setting = saved_settings.front();
4007 saved_settings.pop_front();
4008 EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags());
4009 EXPECT_EQ(kSampleId1, setting.first.id());
4010 EXPECT_EQ(kSampleValue1, setting.second);
4011
4012 // Verify the second persisted setting.
4013 setting = saved_settings.front();
4014 saved_settings.pop_front();
4015 EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags());
4016 EXPECT_EQ(kSampleId3, setting.first.id());
4017 EXPECT_EQ(kSampleValue3, setting.second);
4018 }
4019}
4020
4021// Test that when there are settings saved that they are sent back to the
4022// server upon session establishment.
[email protected]9e9e842e2010-07-23 23:09:154023TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) {
[email protected]74188f22010-04-09 20:18:504024 static const SpdyHeaderInfo kSynReplyInfo = {
4025 spdy::SYN_REPLY, // Syn Reply
4026 1, // Stream ID
4027 0, // Associated Stream ID
[email protected]c9c6f5c2010-07-31 01:30:034028 net::ConvertRequestPriorityToSpdyPriority(LOWEST),
4029 // Priority
[email protected]74188f22010-04-09 20:18:504030 spdy::CONTROL_FLAG_NONE, // Control Flags
4031 false, // Compressed
[email protected]75f30cc22010-06-28 21:41:384032 spdy::INVALID, // Status
[email protected]74188f22010-04-09 20:18:504033 NULL, // Data
4034 0, // Data Length
4035 spdy::DATA_FLAG_NONE // Data Flags
4036 };
4037 static const char* kExtraHeaders[] = {
4038 "status", "200",
4039 "version", "HTTP/1.1"
4040 };
4041
[email protected]3caf5542010-07-16 15:19:474042 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:154043 BoundNetLog(), GetParam());
[email protected]e3ebba0f2010-08-05 17:59:584044 helper.RunPreTestSetup();
[email protected]74188f22010-04-09 20:18:504045
4046 // Verify that no settings exist initially.
[email protected]9e9e842e2010-07-23 23:09:154047 HostPortPair host_port_pair("www.google.com", helper.port());
[email protected]3caf5542010-07-16 15:19:474048 EXPECT_TRUE(helper.session()->spdy_settings().Get(host_port_pair).empty());
[email protected]74188f22010-04-09 20:18:504049
4050 unsigned int kSampleId1 = 0x1;
4051 unsigned int kSampleValue1 = 0x0a0a0a0a;
4052 unsigned int kSampleId2 = 0xababab;
4053 unsigned int kSampleValue2 = 0x0c0c0c0c;
4054 // Manually insert settings into the SpdySettingsStorage here.
4055 {
4056 spdy::SpdySettings settings;
4057 spdy::SettingsFlagsAndId setting(0);
4058 // First add a persisted setting
4059 setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST);
4060 setting.set_id(kSampleId1);
4061 settings.push_back(std::make_pair(setting, kSampleValue1));
4062 // Next add another persisted setting
4063 setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST);
4064 setting.set_id(kSampleId2);
4065 settings.push_back(std::make_pair(setting, kSampleValue2));
4066
[email protected]3caf5542010-07-16 15:19:474067 helper.session()->mutable_spdy_settings()->Set(host_port_pair, settings);
[email protected]74188f22010-04-09 20:18:504068 }
4069
[email protected]3caf5542010-07-16 15:19:474070 EXPECT_EQ(2u, helper.session()->spdy_settings().Get(host_port_pair).size());
[email protected]74188f22010-04-09 20:18:504071
4072 // Construct the SETTINGS frame.
4073 const spdy::SpdySettings& settings =
[email protected]3caf5542010-07-16 15:19:474074 helper.session()->spdy_settings().Get(host_port_pair);
[email protected]74188f22010-04-09 20:18:504075 scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
4076
4077 // Construct the request.
[email protected]2bd93022010-07-17 00:58:444078 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]74188f22010-04-09 20:18:504079
4080 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:134081 CreateMockWrite(*settings_frame),
4082 CreateMockWrite(*req),
[email protected]74188f22010-04-09 20:18:504083 };
4084
4085 // Construct the reply.
4086 scoped_ptr<spdy::SpdyFrame> reply(
[email protected]a4aeaf42010-06-30 19:57:284087 ConstructSpdyPacket(kSynReplyInfo,
[email protected]74188f22010-04-09 20:18:504088 kExtraHeaders,
4089 arraysize(kExtraHeaders) / 2,
4090 NULL,
4091 0));
4092
[email protected]2bd93022010-07-17 00:58:444093 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]74188f22010-04-09 20:18:504094 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:134095 CreateMockRead(*reply),
4096 CreateMockRead(*body),
[email protected]74188f22010-04-09 20:18:504097 MockRead(true, 0, 0) // EOF
4098 };
4099
[email protected]74188f22010-04-09 20:18:504100 scoped_refptr<DelayedSocketData> data(
4101 new DelayedSocketData(2, reads, arraysize(reads),
4102 writes, arraysize(writes)));
[email protected]e3ebba0f2010-08-05 17:59:584103 helper.AddData(data.get());
4104 helper.RunDefaultTest();
4105 helper.VerifyDataConsumed();
[email protected]3caf5542010-07-16 15:19:474106 TransactionHelperResult out = helper.output();
[email protected]74188f22010-04-09 20:18:504107 EXPECT_EQ(OK, out.rv);
4108 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4109 EXPECT_EQ("hello!", out.response_data);
4110
4111 {
4112 // Verify we had two persisted settings.
4113 spdy::SpdySettings saved_settings =
[email protected]3caf5542010-07-16 15:19:474114 helper.session()->spdy_settings().Get(host_port_pair);
[email protected]74188f22010-04-09 20:18:504115 ASSERT_EQ(2u, saved_settings.size());
4116
4117 // Verify the first persisted setting.
4118 spdy::SpdySetting setting = saved_settings.front();
4119 saved_settings.pop_front();
4120 EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags());
4121 EXPECT_EQ(kSampleId1, setting.first.id());
4122 EXPECT_EQ(kSampleValue1, setting.second);
4123
4124 // Verify the second persisted setting.
4125 setting = saved_settings.front();
4126 saved_settings.pop_front();
4127 EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags());
4128 EXPECT_EQ(kSampleId2, setting.first.id());
4129 EXPECT_EQ(kSampleValue2, setting.second);
4130 }
4131}
4132
[email protected]9e9e842e2010-07-23 23:09:154133TEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
[email protected]2bd93022010-07-17 00:58:444134 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:134135 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]69d717bd2010-04-21 18:43:214136
[email protected]a4aeaf42010-06-30 19:57:284137 scoped_ptr<spdy::SpdyFrame> go_away(ConstructSpdyGoAway());
[email protected]69d717bd2010-04-21 18:43:214138 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:134139 CreateMockRead(*go_away),
[email protected]58cebf8f2010-07-31 19:20:164140 MockRead(true, 0, 0), // EOF
4141 };
4142
[email protected]69d717bd2010-04-21 18:43:214143 scoped_refptr<DelayedSocketData> data(
4144 new DelayedSocketData(1, reads, arraysize(reads),
4145 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:474146 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:154147 BoundNetLog(), GetParam());
[email protected]58cebf8f2010-07-31 19:20:164148 helper.AddData(data);
[email protected]58cebf8f2010-07-31 19:20:164149 helper.RunToCompletion(data.get());
4150 TransactionHelperResult out = helper.output();
[email protected]c9336d22010-08-10 00:04:184151 EXPECT_EQ(ERR_ABORTED, out.rv);
[email protected]69d717bd2010-04-21 18:43:214152}
4153
[email protected]9e9e842e2010-07-23 23:09:154154TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) {
[email protected]2bd93022010-07-17 00:58:444155 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:134156 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]f5ed21552010-05-04 18:39:544157
[email protected]2bd93022010-07-17 00:58:444158 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]f5ed21552010-05-04 18:39:544159 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:134160 CreateMockRead(*resp),
[email protected]f5ed21552010-05-04 18:39:544161 MockRead(false, 0, 0) // EOF
4162 };
4163
[email protected]f5ed21552010-05-04 18:39:544164 scoped_refptr<DelayedSocketData> data(
4165 new DelayedSocketData(1, reads, arraysize(reads),
4166 writes, arraysize(writes)));
[email protected]f5ed21552010-05-04 18:39:544167 BoundNetLog log;
[email protected]3caf5542010-07-16 15:19:474168 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:154169 log, GetParam());
[email protected]3caf5542010-07-16 15:19:474170 helper.RunPreTestSetup();
[email protected]e3ebba0f2010-08-05 17:59:584171 helper.AddData(data.get());
[email protected]3caf5542010-07-16 15:19:474172 HttpNetworkTransaction* trans = helper.trans();
[email protected]f5ed21552010-05-04 18:39:544173
4174 TestCompletionCallback callback;
[email protected]3caf5542010-07-16 15:19:474175 TransactionHelperResult out;
[email protected]d3cee19d2010-06-22 18:42:184176 out.rv = trans->Start(&CreateGetRequest(), &callback, log);
[email protected]3caf5542010-07-16 15:19:474177
[email protected]f5ed21552010-05-04 18:39:544178 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4179 out.rv = callback.WaitForResult();
4180 EXPECT_EQ(out.rv, OK);
4181
4182 const HttpResponseInfo* response = trans->GetResponseInfo();
4183 EXPECT_TRUE(response->headers != NULL);
4184 EXPECT_TRUE(response->was_fetched_via_spdy);
[email protected]3caf5542010-07-16 15:19:474185 out.rv = ReadTransaction(trans, &out.response_data);
[email protected]f5ed21552010-05-04 18:39:544186 EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv);
4187
4188 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:474189 helper.VerifyDataConsumed();
[email protected]f5ed21552010-05-04 18:39:544190}
[email protected]58cebf8f2010-07-31 19:20:164191
[email protected]b261d0e2010-08-02 19:13:244192// Test to make sure we can correctly connect through a proxy.
4193TEST_P(SpdyNetworkTransactionTest, ProxyConnect) {
4194 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4195 BoundNetLog(), GetParam());
4196 helper.session_deps().reset(new SpdySessionDependencies(
[email protected]733b7a6d2010-08-25 01:38:434197 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
[email protected]00cd9c42010-11-02 20:15:574198 helper.SetSession(make_scoped_refptr(
4199 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
[email protected]b261d0e2010-08-02 19:13:244200 helper.RunPreTestSetup();
4201 HttpNetworkTransaction* trans = helper.trans();
4202
4203 const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4204 "Host: www.google.com\r\n"
4205 "Proxy-Connection: keep-alive\r\n\r\n"};
4206 const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4207 "Host: www.google.com\r\n"
4208 "Proxy-Connection: keep-alive\r\n\r\n"};
4209 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4210 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4211 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4212 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4213
4214 MockWrite writes_SPDYNPN[] = {
4215 MockWrite(false, kConnect443, arraysize(kConnect443) - 1, 0),
4216 CreateMockWrite(*req, 2),
4217 };
4218 MockRead reads_SPDYNPN[] = {
4219 MockRead(false, kHTTP200, arraysize(kHTTP200) - 1, 1),
4220 CreateMockRead(*resp, 3),
4221 CreateMockRead(*body.get(), 4),
4222 MockRead(true, 0, 0, 5),
4223 };
4224
4225 MockWrite writes_SPDYSSL[] = {
4226 MockWrite(false, kConnect80, arraysize(kConnect80) - 1, 0),
4227 CreateMockWrite(*req, 2),
4228 };
4229 MockRead reads_SPDYSSL[] = {
4230 MockRead(false, kHTTP200, arraysize(kHTTP200) - 1, 1),
4231 CreateMockRead(*resp, 3),
4232 CreateMockRead(*body.get(), 4),
4233 MockRead(true, 0, 0, 5),
4234 };
4235
4236 MockWrite writes_SPDYNOSSL[] = {
4237 CreateMockWrite(*req, 0),
4238 };
4239
4240 MockRead reads_SPDYNOSSL[] = {
4241 CreateMockRead(*resp, 1),
4242 CreateMockRead(*body.get(), 2),
4243 MockRead(true, 0, 0, 3),
4244 };
4245
4246 scoped_refptr<OrderedSocketData> data;
4247 switch(GetParam()) {
4248 case SPDYNOSSL:
4249 data = new OrderedSocketData(reads_SPDYNOSSL,
4250 arraysize(reads_SPDYNOSSL),
4251 writes_SPDYNOSSL,
4252 arraysize(writes_SPDYNOSSL));
4253 break;
4254 case SPDYSSL:
4255 data = new OrderedSocketData(reads_SPDYSSL, arraysize(reads_SPDYSSL),
4256 writes_SPDYSSL, arraysize(writes_SPDYSSL));
4257 break;
4258 case SPDYNPN:
4259 data = new OrderedSocketData(reads_SPDYNPN, arraysize(reads_SPDYNPN),
4260 writes_SPDYNPN, arraysize(writes_SPDYNPN));
4261 break;
4262 default:
4263 NOTREACHED();
4264 }
4265
4266 helper.AddData(data.get());
4267 TestCompletionCallback callback;
4268
4269 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
4270 EXPECT_EQ(ERR_IO_PENDING, rv);
4271
4272 rv = callback.WaitForResult();
4273 EXPECT_EQ(0, rv);
4274
4275 // Verify the SYN_REPLY.
4276 HttpResponseInfo response = *trans->GetResponseInfo();
4277 EXPECT_TRUE(response.headers != NULL);
4278 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
4279
4280 std::string response_data;
4281 ASSERT_EQ(OK, ReadTransaction(trans, &response_data));
4282 EXPECT_EQ("hello!", response_data);
4283 helper.VerifyDataConsumed();
4284}
4285
4286// Test to make sure we can correctly connect through a proxy to www.google.com,
4287// if there already exists a direct spdy connection to www.google.com. See
4288// http://crbug.com/49874
4289TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
4290 // When setting up the first transaction, we store the SpdySessionPool so that
4291 // we can use the same pool in the second transaction.
4292 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4293 BoundNetLog(), GetParam());
[email protected]733b7a6d2010-08-25 01:38:434294
4295 // Use a proxy service which returns a proxy fallback list from DIRECT to
4296 // myproxy:70. For this test there will be no fallback, so it is equivalent
4297 // to simply DIRECT. The reason for appending the second proxy is to verify
4298 // that the session pool key used does is just "DIRECT".
4299 helper.session_deps().reset(new SpdySessionDependencies(
4300 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
[email protected]00cd9c42010-11-02 20:15:574301 helper.SetSession(make_scoped_refptr(
4302 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
[email protected]733b7a6d2010-08-25 01:38:434303
[email protected]87bfa3f2010-09-30 14:54:564304 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
[email protected]b261d0e2010-08-02 19:13:244305 helper.RunPreTestSetup();
4306
4307 // Construct and send a simple GET request.
4308 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4309 MockWrite writes[] = {
4310 CreateMockWrite(*req, 1),
4311 };
4312
4313 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4314 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4315 MockRead reads[] = {
4316 CreateMockRead(*resp, 2),
4317 CreateMockRead(*body, 3),
4318 MockRead(true, ERR_IO_PENDING, 4), // Force a pause
4319 MockRead(true, 0, 5) // EOF
4320 };
4321 scoped_refptr<OrderedSocketData> data(
4322 new OrderedSocketData(reads, arraysize(reads),
4323 writes, arraysize(writes)));
4324 helper.AddData(data.get());
4325 HttpNetworkTransaction* trans = helper.trans();
4326
4327 TestCompletionCallback callback;
4328 TransactionHelperResult out;
4329 out.rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
4330
4331 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4332 out.rv = callback.WaitForResult();
4333 EXPECT_EQ(out.rv, OK);
4334
4335 const HttpResponseInfo* response = trans->GetResponseInfo();
4336 EXPECT_TRUE(response->headers != NULL);
4337 EXPECT_TRUE(response->was_fetched_via_spdy);
4338 out.rv = ReadTransaction(trans, &out.response_data);
4339 EXPECT_EQ(OK, out.rv);
4340 out.status_line = response->headers->GetStatusLine();
4341 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4342 EXPECT_EQ("hello!", out.response_data);
4343
4344 // Check that the SpdySession is still in the SpdySessionPool.
4345 HostPortPair host_port_pair("www.google.com", helper.port());
[email protected]31e68d72010-08-25 06:36:584346 HostPortProxyPair session_pool_key_direct(
4347 host_port_pair, ProxyServer::Direct());
[email protected]733b7a6d2010-08-25 01:38:434348 EXPECT_TRUE(spdy_session_pool->HasSession(session_pool_key_direct));
[email protected]31e68d72010-08-25 06:36:584349 HostPortProxyPair session_pool_key_proxy(
4350 host_port_pair,
4351 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP));
[email protected]733b7a6d2010-08-25 01:38:434352 EXPECT_FALSE(spdy_session_pool->HasSession(session_pool_key_proxy));
[email protected]b261d0e2010-08-02 19:13:244353
4354 // Set up data for the proxy connection.
4355 const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4356 "Host: www.google.com\r\n"
4357 "Proxy-Connection: keep-alive\r\n\r\n"};
4358 const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4359 "Host: www.google.com\r\n"
4360 "Proxy-Connection: keep-alive\r\n\r\n"};
4361 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4362 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(
4363 "http://www.google.com/foo.dat", false, 1, LOWEST));
4364 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 1));
4365 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(1, true));
4366
4367 MockWrite writes_SPDYNPN[] = {
4368 MockWrite(false, kConnect443, arraysize(kConnect443) - 1, 0),
4369 CreateMockWrite(*req2, 2),
4370 };
4371 MockRead reads_SPDYNPN[] = {
4372 MockRead(false, kHTTP200, arraysize(kHTTP200) - 1, 1),
4373 CreateMockRead(*resp2, 3),
4374 CreateMockRead(*body2, 4),
4375 MockRead(true, 0, 5) // EOF
4376 };
4377
4378 MockWrite writes_SPDYNOSSL[] = {
4379 CreateMockWrite(*req2, 0),
4380 };
4381 MockRead reads_SPDYNOSSL[] = {
4382 CreateMockRead(*resp2, 1),
4383 CreateMockRead(*body2, 2),
4384 MockRead(true, 0, 3) // EOF
4385 };
4386
4387 MockWrite writes_SPDYSSL[] = {
4388 MockWrite(false, kConnect80, arraysize(kConnect80) - 1, 0),
4389 CreateMockWrite(*req2, 2),
4390 };
4391 MockRead reads_SPDYSSL[] = {
4392 MockRead(false, kHTTP200, arraysize(kHTTP200) - 1, 1),
4393 CreateMockRead(*resp2, 3),
4394 CreateMockRead(*body2, 4),
4395 MockRead(true, 0, 0, 5),
4396 };
4397
4398 scoped_refptr<OrderedSocketData> data_proxy;
4399 switch(GetParam()) {
4400 case SPDYNPN:
4401 data_proxy = new OrderedSocketData(reads_SPDYNPN,
4402 arraysize(reads_SPDYNPN),
4403 writes_SPDYNPN,
4404 arraysize(writes_SPDYNPN));
4405 break;
4406 case SPDYNOSSL:
4407 data_proxy = new OrderedSocketData(reads_SPDYNOSSL,
4408 arraysize(reads_SPDYNOSSL),
4409 writes_SPDYNOSSL,
4410 arraysize(writes_SPDYNOSSL));
4411 break;
4412 case SPDYSSL:
4413 data_proxy = new OrderedSocketData(reads_SPDYSSL,
4414 arraysize(reads_SPDYSSL),
4415 writes_SPDYSSL,
4416 arraysize(writes_SPDYSSL));
4417 break;
4418 default:
4419 NOTREACHED();
4420 }
4421
4422 // Create another request to www.google.com, but this time through a proxy.
4423 HttpRequestInfo request_proxy;
4424 request_proxy.method = "GET";
4425 request_proxy.url = GURL("http://www.google.com/foo.dat");
4426 request_proxy.load_flags = 0;
[email protected]87bfa3f2010-09-30 14:54:564427 scoped_ptr<SpdySessionDependencies> ssd_proxy(new SpdySessionDependencies());
[email protected]b261d0e2010-08-02 19:13:244428 // Ensure that this transaction uses the same SpdySessionPool.
[email protected]ad8e04a2010-11-01 04:16:274429 scoped_refptr<HttpNetworkSession> session_proxy(
4430 SpdySessionDependencies::SpdyCreateSession(ssd_proxy.get()));
[email protected]b261d0e2010-08-02 19:13:244431 NormalSpdyTransactionHelper helper_proxy(request_proxy,
4432 BoundNetLog(), GetParam());
[email protected]87bfa3f2010-09-30 14:54:564433 HttpNetworkSessionPeer session_peer(session_proxy);
4434 session_peer.SetProxyService(
4435 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
[email protected]b261d0e2010-08-02 19:13:244436 helper_proxy.session_deps().swap(ssd_proxy);
[email protected]19ec8a72010-08-23 03:38:234437 helper_proxy.SetSession(session_proxy);
[email protected]b261d0e2010-08-02 19:13:244438 helper_proxy.RunPreTestSetup();
4439 helper_proxy.AddData(data_proxy.get());
4440
4441 HttpNetworkTransaction* trans_proxy = helper_proxy.trans();
4442 TestCompletionCallback callback_proxy;
4443 int rv = trans_proxy->Start(&request_proxy, &callback_proxy, BoundNetLog());
4444 EXPECT_EQ(ERR_IO_PENDING, rv);
4445 rv = callback_proxy.WaitForResult();
4446 EXPECT_EQ(0, rv);
4447
4448 HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo();
4449 EXPECT_TRUE(response_proxy.headers != NULL);
4450 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy.headers->GetStatusLine());
4451
4452 std::string response_data;
4453 ASSERT_EQ(OK, ReadTransaction(trans_proxy, &response_data));
4454 EXPECT_EQ("hello!", response_data);
4455
4456 data->CompleteRead();
4457 helper_proxy.VerifyDataConsumed();
4458}
4459
[email protected]58cebf8f2010-07-31 19:20:164460// When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
4461// on a new connection, if the connection was previously known to be good.
4462// This can happen when a server reboots without saying goodbye, or when
4463// we're behind a NAT that masked the RST.
4464TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
4465 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4466 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4467 MockRead reads[] = {
4468 CreateMockRead(*resp),
4469 CreateMockRead(*body),
4470 MockRead(true, ERR_IO_PENDING),
4471 MockRead(true, ERR_CONNECTION_RESET),
4472 };
4473
4474 MockRead reads2[] = {
4475 CreateMockRead(*resp),
4476 CreateMockRead(*body),
4477 MockRead(true, 0, 0) // EOF
4478 };
4479
4480 // This test has a couple of variants.
4481 enum {
4482 // Induce the RST while waiting for our transaction to send.
4483 VARIANT_RST_DURING_SEND_COMPLETION,
4484 // Induce the RST while waiting for our transaction to read.
4485 // In this case, the send completed - everything copied into the SNDBUF.
4486 VARIANT_RST_DURING_READ_COMPLETION
4487 };
4488
4489 for (int variant = VARIANT_RST_DURING_SEND_COMPLETION;
4490 variant <= VARIANT_RST_DURING_READ_COMPLETION;
4491 ++variant) {
4492 scoped_refptr<DelayedSocketData> data1(
4493 new DelayedSocketData(1, reads, arraysize(reads),
4494 NULL, 0));
4495
4496 scoped_refptr<DelayedSocketData> data2(
4497 new DelayedSocketData(1, reads2, arraysize(reads2),
4498 NULL, 0));
4499
4500 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4501 BoundNetLog(), GetParam());
4502 helper.AddData(data1.get());
4503 helper.AddData(data2.get());
4504 helper.RunPreTestSetup();
4505
4506 for (int i = 0; i < 2; ++i) {
4507 scoped_ptr<HttpNetworkTransaction> trans(
4508 new HttpNetworkTransaction(helper.session()));
4509
4510 TestCompletionCallback callback;
4511 int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
4512 EXPECT_EQ(ERR_IO_PENDING, rv);
4513 // On the second transaction, we trigger the RST.
4514 if (i == 1) {
4515 if (variant == VARIANT_RST_DURING_READ_COMPLETION) {
4516 // Writes to the socket complete asynchronously on SPDY by running
4517 // through the message loop. Complete the write here.
4518 MessageLoop::current()->RunAllPending();
4519 }
4520
4521 // Now schedule the ERR_CONNECTION_RESET.
4522 EXPECT_EQ(3u, data1->read_index());
4523 data1->CompleteRead();
4524 EXPECT_EQ(4u, data1->read_index());
4525 }
4526 rv = callback.WaitForResult();
4527 EXPECT_EQ(OK, rv);
4528
4529 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]351ab642010-08-05 16:55:314530 ASSERT_TRUE(response != NULL);
[email protected]58cebf8f2010-07-31 19:20:164531 EXPECT_TRUE(response->headers != NULL);
4532 EXPECT_TRUE(response->was_fetched_via_spdy);
4533 std::string response_data;
4534 rv = ReadTransaction(trans.get(), &response_data);
4535 EXPECT_EQ(OK, rv);
4536 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4537 EXPECT_EQ("hello!", response_data);
4538 }
4539
4540 helper.VerifyDataConsumed();
4541 }
4542}
[email protected]1f418ee2010-10-16 19:46:564543
4544// Test that turning SPDY on and off works properly.
4545TEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) {
4546 net::HttpStreamFactory::set_spdy_enabled(true);
4547 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4548 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
4549
4550 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4551 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4552 MockRead spdy_reads[] = {
4553 CreateMockRead(*resp),
4554 CreateMockRead(*body),
4555 MockRead(true, 0, 0) // EOF
4556 };
4557
4558 scoped_refptr<DelayedSocketData> data(
[email protected]018aabc2010-10-29 16:16:594559 new DelayedSocketData(1,
4560 spdy_reads, arraysize(spdy_reads),
[email protected]1f418ee2010-10-16 19:46:564561 spdy_writes, arraysize(spdy_writes)));
4562 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4563 BoundNetLog(), GetParam());
4564 helper.RunToCompletion(data.get());
4565 TransactionHelperResult out = helper.output();
4566 EXPECT_EQ(OK, out.rv);
4567 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4568 EXPECT_EQ("hello!", out.response_data);
4569
4570 net::HttpStreamFactory::set_spdy_enabled(false);
4571 MockRead http_reads[] = {
4572 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4573 MockRead("hello from http"),
4574 MockRead(false, OK),
4575 };
4576 scoped_refptr<DelayedSocketData> data2(
4577 new DelayedSocketData(1, http_reads, arraysize(http_reads),
4578 NULL, 0));
4579 NormalSpdyTransactionHelper helper2(CreateGetRequest(),
4580 BoundNetLog(), GetParam());
4581 helper2.SetSpdyDisabled();
4582 helper2.RunToCompletion(data2.get());
4583 TransactionHelperResult out2 = helper2.output();
4584 EXPECT_EQ(OK, out2.rv);
4585 EXPECT_EQ("HTTP/1.1 200 OK", out2.status_line);
4586 EXPECT_EQ("hello from http", out2.response_data);
4587
4588 net::HttpStreamFactory::set_spdy_enabled(true);
4589}
[email protected]018aabc2010-10-29 16:16:594590
4591// Tests that Basic authentication works over SPDY
4592TEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) {
4593 net::HttpStreamFactory::set_spdy_enabled(true);
4594
4595 // The first request will be a bare GET, the second request will be a
4596 // GET with an Authorization header.
4597 scoped_ptr<spdy::SpdyFrame> req_get(
4598 ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4599 const char* const kExtraAuthorizationHeaders[] = {
4600 "authorization",
4601 "Basic Zm9vOmJhcg==",
4602 };
4603 scoped_ptr<spdy::SpdyFrame> req_get_authorization(
4604 ConstructSpdyGet(
4605 kExtraAuthorizationHeaders, arraysize(kExtraAuthorizationHeaders)/2,
4606 false, 3, LOWEST));
4607 MockWrite spdy_writes[] = {
4608 CreateMockWrite(*req_get, 1),
4609 CreateMockWrite(*req_get_authorization, 4),
4610 };
4611
4612 // The first response is a 401 authentication challenge, and the second
4613 // response will be a 200 response since the second request includes a valid
4614 // Authorization header.
4615 const char* const kExtraAuthenticationHeaders[] = {
4616 "WWW-Authenticate",
4617 "Basic realm=\"MyRealm\""
4618 };
4619 scoped_ptr<spdy::SpdyFrame> resp_authentication(
4620 ConstructSpdySynReplyError(
4621 "401 Authentication Required",
4622 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
4623 1));
4624 scoped_ptr<spdy::SpdyFrame> body_authentication(
4625 ConstructSpdyBodyFrame(1, true));
4626 scoped_ptr<spdy::SpdyFrame> resp_data(ConstructSpdyGetSynReply(NULL, 0, 3));
4627 scoped_ptr<spdy::SpdyFrame> body_data(ConstructSpdyBodyFrame(3, true));
4628 MockRead spdy_reads[] = {
4629 CreateMockRead(*resp_authentication, 2),
4630 CreateMockRead(*body_authentication, 3),
4631 CreateMockRead(*resp_data, 5),
4632 CreateMockRead(*body_data, 6),
4633 MockRead(true, 0, 7),
4634 };
4635
4636 scoped_refptr<OrderedSocketData> data(
4637 new OrderedSocketData(spdy_reads, arraysize(spdy_reads),
4638 spdy_writes, arraysize(spdy_writes)));
4639 HttpRequestInfo request(CreateGetRequest());
4640 BoundNetLog net_log;
4641 NormalSpdyTransactionHelper helper(request, net_log, GetParam());
4642
4643 helper.RunPreTestSetup();
4644 helper.AddData(data.get());
4645 HttpNetworkTransaction* trans = helper.trans();
4646 TestCompletionCallback callback_start;
4647 const int rv_start = trans->Start(&request, &callback_start, net_log);
4648 EXPECT_EQ(ERR_IO_PENDING, rv_start);
4649 const int rv_start_complete = callback_start.WaitForResult();
4650 EXPECT_EQ(OK, rv_start_complete);
4651
4652 // Make sure the response has an auth challenge.
4653 const HttpResponseInfo* const response_start = trans->GetResponseInfo();
4654 ASSERT_TRUE(response_start != NULL);
4655 ASSERT_TRUE(response_start->headers != NULL);
4656 EXPECT_EQ(401, response_start->headers->response_code());
4657 EXPECT_TRUE(response_start->was_fetched_via_spdy);
4658 ASSERT_TRUE(response_start->auth_challenge.get() != NULL);
4659 EXPECT_FALSE(response_start->auth_challenge->is_proxy);
4660 EXPECT_EQ(L"basic", response_start->auth_challenge->scheme);
4661 EXPECT_EQ(L"MyRealm", response_start->auth_challenge->realm);
4662
4663 // Restart with a username/password.
4664 const string16 kFoo(ASCIIToUTF16("foo"));
4665 const string16 kBar(ASCIIToUTF16("bar"));
4666 TestCompletionCallback callback_restart;
4667 const int rv_restart = trans->RestartWithAuth(kFoo, kBar, &callback_restart);
4668 EXPECT_EQ(ERR_IO_PENDING, rv_restart);
4669 const int rv_restart_complete = callback_restart.WaitForResult();
4670 EXPECT_EQ(OK, rv_restart_complete);
4671 // TODO(cbentzel): This is actually the same response object as before, but
4672 // data has changed.
4673 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
4674 ASSERT_TRUE(response_restart != NULL);
4675 ASSERT_TRUE(response_restart->headers != NULL);
4676 EXPECT_EQ(200, response_restart->headers->response_code());
4677 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
4678}
4679
[email protected]aea80602009-09-18 00:55:084680} // namespace net