blob: 3ac38cbc7b4d9406a7bec1e7ea24c1af5e4409f0 [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]9e743cd2010-03-16 07:03:535#include "net/base/net_log_unittest.h"
[email protected]aea80602009-09-18 00:55:086#include "net/http/http_transaction_unittest.h"
[email protected]9be804c82010-06-24 17:59:467#include "net/spdy/spdy_http_stream.h"
[email protected]30c942b2010-07-21 16:59:598#include "net/spdy/spdy_network_transaction.h"
[email protected]2ff8b312010-04-26 22:20:549#include "net/spdy/spdy_test_util.h"
[email protected]aea80602009-09-18 00:55:0810#include "testing/platform_test.h"
11
12//-----------------------------------------------------------------------------
13
[email protected]d1eda932009-11-04 01:03:1014namespace net {
[email protected]9e9e842e2010-07-23 23:09:1515enum SpdyNetworkTransactionTestTypes {
16 SPDYNPN,
17 SPDYNOSSL,
18 SPDYSSL
19};
20class SpdyNetworkTransactionTest
21 : public ::testing::TestWithParam<SpdyNetworkTransactionTestTypes> {
[email protected]34437af82009-11-06 02:28:4922 protected:
[email protected]aea80602009-09-18 00:55:0823 virtual void SetUp() {
[email protected]94d78132010-01-22 00:53:0024 // By default, all tests turn off compression.
25 EnableCompression(false);
[email protected]d3cee19d2010-06-22 18:42:1826 google_get_request_initialized_ = false;
[email protected]aea80602009-09-18 00:55:0827 }
28
29 virtual void TearDown() {
30 // Empty the current queue.
31 MessageLoop::current()->RunAllPending();
[email protected]aea80602009-09-18 00:55:0832 }
33
[email protected]72552f02009-10-28 15:25:0134 struct TransactionHelperResult {
[email protected]aea80602009-09-18 00:55:0835 int rv;
36 std::string status_line;
37 std::string response_data;
[email protected]8b070372009-11-16 22:01:2538 HttpResponseInfo response_info;
[email protected]aea80602009-09-18 00:55:0839 };
40
[email protected]94d78132010-01-22 00:53:0041 void EnableCompression(bool enabled) {
[email protected]955fc2e72010-02-08 20:37:3042 spdy::SpdyFramer::set_enable_compression_default(enabled);
[email protected]94d78132010-01-22 00:53:0043 }
44
[email protected]3caf5542010-07-16 15:19:4745 class StartTransactionCallback;
46 class DeleteSessionCallback;
[email protected]74188f22010-04-09 20:18:5047
[email protected]3caf5542010-07-16 15:19:4748 // A helper class that handles all the initial npn/ssl setup.
49 class NormalSpdyTransactionHelper {
50 public:
51 NormalSpdyTransactionHelper(const HttpRequestInfo& request,
[email protected]9e9e842e2010-07-23 23:09:1552 const BoundNetLog& log,
53 SpdyNetworkTransactionTestTypes test_type)
[email protected]30c942b2010-07-21 16:59:5954 : request_(request),
55 session_(SpdySessionDependencies::SpdyCreateSession(&session_deps_)),
[email protected]9e9e842e2010-07-23 23:09:1556 log_(log),
57 test_type_(test_type) {
58 switch(test_type_) {
59 case SPDYNOSSL:
60 case SPDYSSL:
61 port_ = 80;
62 break;
63 case SPDYNPN:
64 port_ = 443;
65 break;
66 default:
67 NOTREACHED();
68 }
69 }
[email protected]74188f22010-04-09 20:18:5070
[email protected]3caf5542010-07-16 15:19:4771 void RunPreTestSetup() {
[email protected]9e9e842e2010-07-23 23:09:1572 HttpNetworkTransaction::SetUseAlternateProtocols(false);
73 HttpNetworkTransaction::SetUseSSLOverSpdyWithoutNPN(false);
74 HttpNetworkTransaction::SetUseSpdyWithoutNPN(false);
75 switch(test_type_) {
76 case SPDYNPN:
77 session_->mutable_alternate_protocols()->SetAlternateProtocolFor(
78 HostPortPair("www.google.com", 80), 443,
79 HttpAlternateProtocols::NPN_SPDY_1);
80 HttpNetworkTransaction::SetUseAlternateProtocols(true);
81 HttpNetworkTransaction::SetNextProtos(
82 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
83 break;
84 case SPDYNOSSL:
85 HttpNetworkTransaction::SetUseSSLOverSpdyWithoutNPN(false);
86 HttpNetworkTransaction::SetUseSpdyWithoutNPN(true);
87 break;
88 case SPDYSSL:
89 HttpNetworkTransaction::SetUseSSLOverSpdyWithoutNPN(true);
90 HttpNetworkTransaction::SetUseSpdyWithoutNPN(true);
91 break;
92 default:
93 NOTREACHED();
[email protected]3caf5542010-07-16 15:19:4794 }
[email protected]aea80602009-09-18 00:55:0895
[email protected]3caf5542010-07-16 15:19:4796 // We're now ready to use SSL-npn SPDY.
97 trans_.reset(new HttpNetworkTransaction(session_));
[email protected]cb54b3b22010-06-03 16:28:5598 }
[email protected]aea80602009-09-18 00:55:0899
[email protected]3caf5542010-07-16 15:19:47100 // Start the transaction, read some data, finish.
101 void RunDefaultTest() {
102 output_.rv = trans_->Start(&request_, &callback, log_);
[email protected]aea80602009-09-18 00:55:08103
[email protected]3caf5542010-07-16 15:19:47104 // We expect an IO Pending or some sort of error.
105 EXPECT_LT(output_.rv, 0);
106 if (output_.rv != ERR_IO_PENDING)
107 return;
[email protected]aea80602009-09-18 00:55:08108
[email protected]3caf5542010-07-16 15:19:47109 output_.rv = callback.WaitForResult();
110 if (output_.rv != OK) {
111 session_->spdy_session_pool()->ClearSessions();
112 return;
113 }
[email protected]ff57bb82009-11-12 06:52:14114
[email protected]3caf5542010-07-16 15:19:47115 // Verify responses.
116 const HttpResponseInfo* response = trans_->GetResponseInfo();
117 ASSERT_TRUE(response != NULL);
118 ASSERT_TRUE(response->headers != NULL);
119 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
120 EXPECT_TRUE(response->was_fetched_via_spdy);
[email protected]9e9e842e2010-07-23 23:09:15121 if(test_type_ == SPDYNPN) {
122 EXPECT_TRUE(response->was_npn_negotiated);
123 EXPECT_TRUE(response->was_alternate_protocol_available);
124 }
125 else {
126 EXPECT_TRUE(!response->was_npn_negotiated);
127 EXPECT_TRUE(!response->was_alternate_protocol_available);
128 }
[email protected]3caf5542010-07-16 15:19:47129 output_.status_line = response->headers->GetStatusLine();
130 output_.response_info = *response; // Make a copy so we can verify.
131 output_.rv = ReadTransaction(trans_.get(), &output_.response_data);
132 EXPECT_EQ(OK, output_.rv);
133 return;
134 }
135
136 // Most tests will want to call this function. In particular, the MockReads
137 // should end with an empty read, and that read needs to be processed to
138 // ensure proper deletion of the spdy_session_pool.
139 void VerifyDataConsumed() {
140 for(DataVector::iterator it = data_vector_.begin();
141 it != data_vector_.end(); ++it) {
142 EXPECT_TRUE((*it)->at_read_eof()) << "Read count: "
143 << (*it)->read_count()
144 << " Read index: "
145 << (*it)->read_index();
146 EXPECT_TRUE((*it)->at_write_eof()) << "Write count: "
147 << (*it)->write_count()
148 << " Write index: "
149 << (*it)->write_index();
150 }
151 }
152
153 // Occasionally a test will expect to error out before certain reads are
154 // processed. In that case we want to explicitly ensure that the reads were
155 // not processed.
156 void VerifyDataNotConsumed() {
157 for(DataVector::iterator it = data_vector_.begin();
158 it != data_vector_.end(); ++it) {
159 EXPECT_TRUE(!(*it)->at_read_eof()) << "Read count: "
160 << (*it)->read_count()
161 << " Read index: "
162 << (*it)->read_index();
163 EXPECT_TRUE(!(*it)->at_write_eof()) << "Write count: "
164 << (*it)->write_count()
165 << " Write index: "
166 << (*it)->write_index();
167
168 }
169 }
170
171 void RunToCompletion(StaticSocketDataProvider* data) {
172 AddData(data);
173 RunPreTestSetup();
174 RunDefaultTest();
175 VerifyDataConsumed();
176 }
[email protected]e6b06862010-07-20 16:32:58177
[email protected]3caf5542010-07-16 15:19:47178 void AddData(StaticSocketDataProvider* data) {
[email protected]3caf5542010-07-16 15:19:47179 data_vector_.push_back(data);
[email protected]9e9e842e2010-07-23 23:09:15180 linked_ptr<SSLSocketDataProvider> ssl_(
181 new SSLSocketDataProvider(true, OK));
182 if(test_type_ == SPDYNPN) {
183 ssl_->next_proto_status = SSLClientSocket::kNextProtoNegotiated;
184 ssl_->next_proto = "spdy/1";
185 ssl_->was_npn_negotiated = true;
186 }
187 ssl_vector_.push_back(ssl_);
188 if(test_type_ == SPDYNPN || test_type_ == SPDYSSL)
189 session_deps_.socket_factory.AddSSLSocketDataProvider(ssl_.get());
190 session_deps_.socket_factory.AddSocketDataProvider(data);
[email protected]3caf5542010-07-16 15:19:47191 }
192
[email protected]e6b06862010-07-20 16:32:58193 // This can only be called after RunPreTestSetup. It adds a Data Provider,
194 // but not a corresponding SSL data provider
195 void AddDataNoSSL(StaticSocketDataProvider* data) {
196 session_deps_.socket_factory.AddSocketDataProvider(data);
197 }
198
[email protected]3caf5542010-07-16 15:19:47199 void SetSession(scoped_refptr<HttpNetworkSession>& session) {
200 session_ = session;
201 }
202 HttpNetworkTransaction* trans() { return trans_.get(); }
203 void ResetTrans() { trans_.reset(); }
204 TransactionHelperResult& output() { return output_; }
205 HttpRequestInfo& request() { return request_; }
206 scoped_refptr<HttpNetworkSession>& session() { return session_; }
[email protected]9e9e842e2010-07-23 23:09:15207 int port() { return port_; }
[email protected]3caf5542010-07-16 15:19:47208
209 private:
210 typedef std::vector<StaticSocketDataProvider*> DataVector;
211 typedef std::vector<linked_ptr<SSLSocketDataProvider> > SSLVector;
212 HttpRequestInfo request_;
[email protected]30c942b2010-07-21 16:59:59213 SpdySessionDependencies session_deps_;
[email protected]3caf5542010-07-16 15:19:47214 scoped_refptr<HttpNetworkSession> session_;
215 TransactionHelperResult output_;
216 scoped_ptr<StaticSocketDataProvider> first_transaction_;
217 SSLVector ssl_vector_;
218 TestCompletionCallback callback;
219 scoped_ptr<HttpNetworkTransaction> trans_;
220 scoped_ptr<HttpNetworkTransaction> trans_http_;
221 DataVector data_vector_;
222 const BoundNetLog& log_;
[email protected]9e9e842e2010-07-23 23:09:15223 SpdyNetworkTransactionTestTypes test_type_;
224 int port_;
[email protected]3caf5542010-07-16 15:19:47225 };
[email protected]aea80602009-09-18 00:55:08226
227 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
228 int expected_status);
229
230 void ConnectStatusHelper(const MockRead& status);
[email protected]d3cee19d2010-06-22 18:42:18231
232 const HttpRequestInfo& CreateGetRequest() {
233 if (!google_get_request_initialized_) {
234 google_get_request_.method = "GET";
235 google_get_request_.url = GURL("http://www.google.com/");
236 google_get_request_.load_flags = 0;
237 google_get_request_initialized_ = true;
238 }
239 return google_get_request_;
240 }
241
242 private:
243 bool google_get_request_initialized_;
244 HttpRequestInfo google_get_request_;
[email protected]aea80602009-09-18 00:55:08245};
246
247//-----------------------------------------------------------------------------
[email protected]9e9e842e2010-07-23 23:09:15248// All tests are run with three different connection types: SPDY after NPN
249// negotiation, SPDY without SSL, and SPDY with SSL.
250INSTANTIATE_TEST_CASE_P(SpdyNetworkingTest,
251 SpdyNetworkTransactionTest,
252 ::testing::Values(SPDYNPN, SPDYNOSSL, SPDYSSL));
253
[email protected]aea80602009-09-18 00:55:08254
[email protected]3caf5542010-07-16 15:19:47255// Verify HttpNetworkTransaction constructor.
[email protected]9e9e842e2010-07-23 23:09:15256TEST_P(SpdyNetworkTransactionTest, Constructor) {
[email protected]30c942b2010-07-21 16:59:59257 SpdySessionDependencies session_deps;
[email protected]34437af82009-11-06 02:28:49258 scoped_refptr<HttpNetworkSession> session =
[email protected]30c942b2010-07-21 16:59:59259 SpdySessionDependencies::SpdyCreateSession(&session_deps);
[email protected]3caf5542010-07-16 15:19:47260 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]aea80602009-09-18 00:55:08261}
262
[email protected]9e9e842e2010-07-23 23:09:15263TEST_P(SpdyNetworkTransactionTest, Get) {
[email protected]75f30cc22010-06-28 21:41:38264 // Construct the request.
[email protected]2bd93022010-07-17 00:58:44265 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:13266 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]72552f02009-10-28 15:25:01267
[email protected]2bd93022010-07-17 00:58:44268 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
269 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]72552f02009-10-28 15:25:01270 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:13271 CreateMockRead(*resp),
272 CreateMockRead(*body),
[email protected]72552f02009-10-28 15:25:01273 MockRead(true, 0, 0) // EOF
274 };
275
[email protected]bf2491a92009-11-29 16:39:48276 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:39277 new DelayedSocketData(1, reads, arraysize(reads),
278 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:47279 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:15280 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:47281 helper.RunToCompletion(data.get());
282 TransactionHelperResult out = helper.output();
[email protected]72552f02009-10-28 15:25:01283 EXPECT_EQ(OK, out.rv);
284 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
285 EXPECT_EQ("hello!", out.response_data);
286}
287
[email protected]2bd93022010-07-17 00:58:44288// Start three gets simultaniously; making sure that multiplexed
289// streams work properly.
290
291// This can't use the TransactionHelper method, since it only
292// handles a single transaction, and finishes them as soon
293// as it launches them.
294
295// TODO(gavinp): create a working generalized TransactionHelper that
296// can allow multiple streams in flight.
297
[email protected]9e9e842e2010-07-23 23:09:15298TEST_P(SpdyNetworkTransactionTest, ThreeGets) {
[email protected]2bd93022010-07-17 00:58:44299 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
300 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
301 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
302 scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
303
304 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
305 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
306 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
307 scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
308
309 scoped_ptr<spdy::SpdyFrame> req3(ConstructSpdyGet(NULL, 0, false, 5, LOWEST));
310 scoped_ptr<spdy::SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 5));
311 scoped_ptr<spdy::SpdyFrame> body3(ConstructSpdyBodyFrame(5, false));
312 scoped_ptr<spdy::SpdyFrame> fbody3(ConstructSpdyBodyFrame(5, true));
313
314 MockWrite writes[] = { CreateMockWrite(*req),
315 CreateMockWrite(*req2),
316 CreateMockWrite(*req3),
317 };
318 MockRead reads[] = {
319 CreateMockRead(*resp, 1),
320 CreateMockRead(*body),
321 CreateMockRead(*resp2, 4),
322 CreateMockRead(*body2),
323 CreateMockRead(*resp3, 7),
324 CreateMockRead(*body3),
325
326 CreateMockRead(*fbody),
327 CreateMockRead(*fbody2),
328 CreateMockRead(*fbody3),
329
330 MockRead(true, 0, 0), // EOF
331 };
332
333 scoped_refptr<OrderedSocketData> data(
334 new OrderedSocketData(reads, arraysize(reads),
335 writes, arraysize(writes)));
336
337 BoundNetLog log;
338 TransactionHelperResult out;
339 {
[email protected]30c942b2010-07-21 16:59:59340 SpdySessionDependencies session_deps;
341 HttpNetworkSession* session =
342 SpdySessionDependencies::SpdyCreateSession(&session_deps);
[email protected]2bd93022010-07-17 00:58:44343 SpdySession::SetSSLMode(false);
344 scoped_ptr<SpdyNetworkTransaction> trans1(
345 new SpdyNetworkTransaction(session));
346 scoped_ptr<SpdyNetworkTransaction> trans2(
347 new SpdyNetworkTransaction(session));
348 scoped_ptr<SpdyNetworkTransaction> trans3(
349 new SpdyNetworkTransaction(session));
350
351 session_deps.socket_factory.AddSocketDataProvider(data);
352
353 TestCompletionCallback callback1;
354 TestCompletionCallback callback2;
355 TestCompletionCallback callback3;
356
357 HttpRequestInfo httpreq1 = CreateGetRequest();
358 HttpRequestInfo httpreq2 = CreateGetRequest();
359 HttpRequestInfo httpreq3 = CreateGetRequest();
360
361 out.rv = trans1->Start(&httpreq1, &callback1, log);
362 ASSERT_EQ(ERR_IO_PENDING, out.rv);
363 out.rv = trans2->Start(&httpreq2, &callback2, log);
364 ASSERT_EQ(ERR_IO_PENDING, out.rv);
365 out.rv = trans3->Start(&httpreq3, &callback3, log);
366 ASSERT_EQ(ERR_IO_PENDING, out.rv);
367
368 out.rv = callback1.WaitForResult();
369 ASSERT_EQ(OK, out.rv);
370 out.rv = callback3.WaitForResult();
371 ASSERT_EQ(OK, out.rv);
372
373 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
374 EXPECT_TRUE(response1->headers != NULL);
375 EXPECT_TRUE(response1->was_fetched_via_spdy);
376 out.status_line = response1->headers->GetStatusLine();
377 out.response_info = *response1;
378
379 trans2->GetResponseInfo();
380
381 out.rv = ReadTransaction(trans1.get(), &out.response_data);
382 }
383 EXPECT_EQ(OK, out.rv);
384
385 EXPECT_TRUE(data->at_read_eof());
386 EXPECT_TRUE(data->at_write_eof());
387
388 EXPECT_EQ(OK, out.rv);
389 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
390 EXPECT_EQ("hello!hello!", out.response_data);
391}
392
393
394// Similar to ThreeGets above, however this test adds a SETTINGS
395// frame. The SETTINGS frame is read during the IO loop waiting on
396// the first transaction completion, and sets a maximum concurrent
397// stream limit of 1. This means that our IO loop exists after the
398// second transaction completes, so we can assert on read_index().
[email protected]9e9e842e2010-07-23 23:09:15399TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
[email protected]2bd93022010-07-17 00:58:44400 // Construct the request.
401 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
402 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
403 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
404 scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
405
406 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
407 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
408 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
409 scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
410
411 scoped_ptr<spdy::SpdyFrame> req3(ConstructSpdyGet(NULL, 0, false, 5, LOWEST));
412 scoped_ptr<spdy::SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 5));
413 scoped_ptr<spdy::SpdyFrame> body3(ConstructSpdyBodyFrame(5, false));
414 scoped_ptr<spdy::SpdyFrame> fbody3(ConstructSpdyBodyFrame(5, true));
415
416 spdy::SpdySettings settings;
417 spdy::SettingsFlagsAndId id(0);
418 id.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS);
419 const size_t max_concurrent_streams = 1;
420
421 settings.push_back(spdy::SpdySetting(id, max_concurrent_streams));
422 scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
423
424 MockWrite writes[] = { CreateMockWrite(*req),
425 CreateMockWrite(*req2),
426 CreateMockWrite(*req3),
427 };
428 MockRead reads[] = {
429 CreateMockRead(*settings_frame, 0),
430 CreateMockRead(*resp),
431 CreateMockRead(*body),
432 CreateMockRead(*fbody),
433 CreateMockRead(*resp2, 6),
434 CreateMockRead(*body2),
435 CreateMockRead(*fbody2),
436 CreateMockRead(*resp3, 11),
437 CreateMockRead(*body3),
438 CreateMockRead(*fbody3),
439
440 MockRead(true, 0, 0), // EOF
441 };
442
443 scoped_refptr<OrderedSocketData> data(
444 new OrderedSocketData(reads, arraysize(reads),
445 writes, arraysize(writes)));
446
447 BoundNetLog log;
448 TransactionHelperResult out;
449 {
[email protected]30c942b2010-07-21 16:59:59450 SpdySessionDependencies session_deps;
451 HttpNetworkSession* session =
452 SpdySessionDependencies::SpdyCreateSession(&session_deps);
[email protected]2bd93022010-07-17 00:58:44453 SpdySession::SetSSLMode(false);
454 scoped_ptr<SpdyNetworkTransaction> trans1(
455 new SpdyNetworkTransaction(session));
456 scoped_ptr<SpdyNetworkTransaction> trans2(
457 new SpdyNetworkTransaction(session));
458 scoped_ptr<SpdyNetworkTransaction> trans3(
459 new SpdyNetworkTransaction(session));
460
461 session_deps.socket_factory.AddSocketDataProvider(data);
462
463 TestCompletionCallback callback1;
464 TestCompletionCallback callback2;
465 TestCompletionCallback callback3;
466
467 HttpRequestInfo httpreq1 = CreateGetRequest();
468 HttpRequestInfo httpreq2 = CreateGetRequest();
469 HttpRequestInfo httpreq3 = CreateGetRequest();
470
471 out.rv = trans1->Start(&httpreq1, &callback1, log);
472 ASSERT_EQ(out.rv, ERR_IO_PENDING);
473 // run transaction 1 through quickly to force a read of our SETTINGS
474 // frame
475 out.rv = callback1.WaitForResult();
476
477 out.rv = trans2->Start(&httpreq2, &callback2, log);
478 ASSERT_EQ(out.rv, ERR_IO_PENDING);
479 out.rv = trans3->Start(&httpreq3, &callback3, log);
480 ASSERT_EQ(out.rv, ERR_IO_PENDING);
481 out.rv = callback2.WaitForResult();
482 ASSERT_EQ(OK, out.rv);
483 EXPECT_EQ(7U, data->read_index()); // i.e. the third trans was queued
484
485 out.rv = callback3.WaitForResult();
486 ASSERT_EQ(OK, out.rv);
487
488 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
489 EXPECT_TRUE(response1->headers != NULL);
490 EXPECT_TRUE(response1->was_fetched_via_spdy);
491 out.status_line = response1->headers->GetStatusLine();
492 out.response_info = *response1;
493 out.rv = ReadTransaction(trans1.get(), &out.response_data);
494 EXPECT_EQ(OK, out.rv);
495 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
496 EXPECT_EQ("hello!hello!", out.response_data);
497
498 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
499 out.status_line = response2->headers->GetStatusLine();
500 out.response_info = *response2;
501 out.rv = ReadTransaction(trans2.get(), &out.response_data);
502 EXPECT_EQ(OK, out.rv);
503 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
504 EXPECT_EQ("hello!hello!", out.response_data);
505
506 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
507 out.status_line = response3->headers->GetStatusLine();
508 out.response_info = *response3;
509 out.rv = ReadTransaction(trans3.get(), &out.response_data);
510 EXPECT_EQ(OK, out.rv);
511 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
512 EXPECT_EQ("hello!hello!", out.response_data);
513 }
514 EXPECT_EQ(OK, out.rv);
515
516 EXPECT_TRUE(data->at_read_eof());
517 EXPECT_TRUE(data->at_write_eof());
518}
519
520// Similar to ThreeGetsWithMaxConcurrent above, however this test adds
521// a fourth transaction. The third and fourth transactions have
522// different data ("hello!" vs "hello!hello!") and because of the
523// user specified priority, we expect to see them inverted in
524// the response from the server.
[email protected]9e9e842e2010-07-23 23:09:15525TEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
[email protected]2bd93022010-07-17 00:58:44526 // Construct the request.
527 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
528 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
529 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
530 scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
531
532 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
533 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
534 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
535 scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
536
537 scoped_ptr<spdy::SpdyFrame> req4(
538 ConstructSpdyGet(NULL, 0, false, 5, HIGHEST));
539 scoped_ptr<spdy::SpdyFrame> resp4(ConstructSpdyGetSynReply(NULL, 0, 5));
540 scoped_ptr<spdy::SpdyFrame> fbody4(ConstructSpdyBodyFrame(5, true));
541
542 scoped_ptr<spdy::SpdyFrame> req3(ConstructSpdyGet(NULL, 0, false, 7, LOWEST));
543 scoped_ptr<spdy::SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 7));
544 scoped_ptr<spdy::SpdyFrame> body3(ConstructSpdyBodyFrame(7, false));
545 scoped_ptr<spdy::SpdyFrame> fbody3(ConstructSpdyBodyFrame(7, true));
546
547
548 spdy::SpdySettings settings;
549 spdy::SettingsFlagsAndId id(0);
550 id.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS);
551 const size_t max_concurrent_streams = 1;
552
553 settings.push_back(spdy::SpdySetting(id, max_concurrent_streams));
554 scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
555
556 MockWrite writes[] = { CreateMockWrite(*req),
557 CreateMockWrite(*req2),
558 CreateMockWrite(*req4),
559 CreateMockWrite(*req3),
560 };
561 MockRead reads[] = {
562 CreateMockRead(*settings_frame, 0),
563 CreateMockRead(*resp),
564 CreateMockRead(*body),
565 CreateMockRead(*fbody),
566 CreateMockRead(*resp2, 6),
567 CreateMockRead(*body2),
568 CreateMockRead(*fbody2),
569 CreateMockRead(*resp4, 12),
570 CreateMockRead(*fbody4),
571 CreateMockRead(*resp3, 15),
572 CreateMockRead(*body3),
573 CreateMockRead(*fbody3),
574
575 MockRead(true, 0, 0), // EOF
576 };
577
578 scoped_refptr<OrderedSocketData> data(
579 new OrderedSocketData(reads, arraysize(reads),
580 writes, arraysize(writes)));
581
582 BoundNetLog log;
583 TransactionHelperResult out;
584 {
[email protected]30c942b2010-07-21 16:59:59585 SpdySessionDependencies session_deps;
586 HttpNetworkSession* session =
587 SpdySessionDependencies::SpdyCreateSession(&session_deps);
[email protected]2bd93022010-07-17 00:58:44588 SpdySession::SetSSLMode(false);
589 scoped_ptr<SpdyNetworkTransaction> trans1(
590 new SpdyNetworkTransaction(session));
591 scoped_ptr<SpdyNetworkTransaction> trans2(
592 new SpdyNetworkTransaction(session));
593 scoped_ptr<SpdyNetworkTransaction> trans3(
594 new SpdyNetworkTransaction(session));
595 scoped_ptr<SpdyNetworkTransaction> trans4(
596 new SpdyNetworkTransaction(session));
597
598 session_deps.socket_factory.AddSocketDataProvider(data);
599
600 TestCompletionCallback callback1;
601 TestCompletionCallback callback2;
602 TestCompletionCallback callback3;
603 TestCompletionCallback callback4;
604
605 HttpRequestInfo httpreq1 = CreateGetRequest();
606 HttpRequestInfo httpreq2 = CreateGetRequest();
607 HttpRequestInfo httpreq3 = CreateGetRequest();
608 HttpRequestInfo httpreq4 = CreateGetRequest();
609 httpreq4.priority = HIGHEST;
610
611 out.rv = trans1->Start(&httpreq1, &callback1, log);
612 ASSERT_EQ(ERR_IO_PENDING, out.rv);
613 // run transaction 1 through quickly to force a read of our SETTINGS
614 // frame
615 out.rv = callback1.WaitForResult();
616 ASSERT_EQ(OK, out.rv);
617
618 out.rv = trans2->Start(&httpreq2, &callback2, log);
619 ASSERT_EQ(ERR_IO_PENDING, out.rv);
620 out.rv = trans3->Start(&httpreq3, &callback3, log);
621 ASSERT_EQ(ERR_IO_PENDING, out.rv);
622 out.rv = trans4->Start(&httpreq4, &callback4, log);
623 ASSERT_EQ(ERR_IO_PENDING, out.rv);
624
625 out.rv = callback2.WaitForResult();
626 ASSERT_EQ(OK, out.rv);
627 EXPECT_EQ(data->read_index(), 7U); // i.e. the third & fourth trans queued
628
629 out.rv = callback3.WaitForResult();
630 ASSERT_EQ(OK, out.rv);
631
632 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
633 EXPECT_TRUE(response1->headers != NULL);
634 EXPECT_TRUE(response1->was_fetched_via_spdy);
635 out.status_line = response1->headers->GetStatusLine();
636 out.response_info = *response1;
637 out.rv = ReadTransaction(trans1.get(), &out.response_data);
638 EXPECT_EQ(OK, out.rv);
639 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
640 EXPECT_EQ("hello!hello!", out.response_data);
641
642 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
643 out.status_line = response2->headers->GetStatusLine();
644 out.response_info = *response2;
645 out.rv = ReadTransaction(trans2.get(), &out.response_data);
646 EXPECT_EQ(OK, out.rv);
647 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
648 EXPECT_EQ("hello!hello!", out.response_data);
649
650 // notice: response3 gets two hellos, response4 gets one
651 // hello, so we know dequeuing priority was respected.
652 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
653 out.status_line = response3->headers->GetStatusLine();
654 out.response_info = *response3;
655 out.rv = ReadTransaction(trans3.get(), &out.response_data);
656 EXPECT_EQ(OK, out.rv);
657 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
658 EXPECT_EQ("hello!hello!", out.response_data);
659
660 out.rv = callback4.WaitForResult();
661 EXPECT_EQ(OK, out.rv);
662 const HttpResponseInfo* response4 = trans4->GetResponseInfo();
663 out.status_line = response4->headers->GetStatusLine();
664 out.response_info = *response4;
665 out.rv = ReadTransaction(trans4.get(), &out.response_data);
666 EXPECT_EQ(OK, out.rv);
667 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
668 EXPECT_EQ("hello!", out.response_data);
669 }
670 EXPECT_EQ(OK, out.rv);
671
672 EXPECT_TRUE(data->at_read_eof());
673 EXPECT_TRUE(data->at_write_eof());
674}
675
676// Similar to ThreeGetsMaxConcurrrent above, however, this test
677// deletes a session in the middle of the transaction to insure
678// that we properly remove pendingcreatestream objects from
679// the spdy_session
[email protected]9e9e842e2010-07-23 23:09:15680TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
[email protected]2bd93022010-07-17 00:58:44681 // Construct the request.
682 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
683 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
684 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
685 scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
686
687 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
688 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
689 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
690 scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
691
692 scoped_ptr<spdy::SpdyFrame> req3(ConstructSpdyGet(NULL, 0, false, 5, LOWEST));
693 scoped_ptr<spdy::SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 5));
694 scoped_ptr<spdy::SpdyFrame> body3(ConstructSpdyBodyFrame(5, false));
695 scoped_ptr<spdy::SpdyFrame> fbody3(ConstructSpdyBodyFrame(5, true));
696
697 spdy::SpdySettings settings;
698 spdy::SettingsFlagsAndId id(0);
699 id.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS);
700 const size_t max_concurrent_streams = 1;
701
702 settings.push_back(spdy::SpdySetting(id, max_concurrent_streams));
703 scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
704
705 MockWrite writes[] = { CreateMockWrite(*req),
706 CreateMockWrite(*req2),
707 };
708 MockRead reads[] = {
709 CreateMockRead(*settings_frame, 0),
710 CreateMockRead(*resp),
711 CreateMockRead(*body),
712 CreateMockRead(*fbody),
713 CreateMockRead(*resp2, 6),
714 CreateMockRead(*body2),
715 CreateMockRead(*fbody2),
716 MockRead(true, 0, 0), // EOF
717 };
718
719 scoped_refptr<OrderedSocketData> data(
720 new OrderedSocketData(reads, arraysize(reads),
721 writes, arraysize(writes)));
722
723 BoundNetLog log;
724 TransactionHelperResult out;
725 {
[email protected]30c942b2010-07-21 16:59:59726 SpdySessionDependencies session_deps;
727 HttpNetworkSession* session =
728 SpdySessionDependencies::SpdyCreateSession(&session_deps);
[email protected]2bd93022010-07-17 00:58:44729 SpdySession::SetSSLMode(false);
730 scoped_ptr<SpdyNetworkTransaction> trans1(
731 new SpdyNetworkTransaction(session));
732 scoped_ptr<SpdyNetworkTransaction> trans2(
733 new SpdyNetworkTransaction(session));
734 scoped_ptr<SpdyNetworkTransaction> trans3(
735 new SpdyNetworkTransaction(session));
736
737 session_deps.socket_factory.AddSocketDataProvider(data);
738
739 TestCompletionCallback callback1;
740 TestCompletionCallback callback2;
741 TestCompletionCallback callback3;
742
743 HttpRequestInfo httpreq1 = CreateGetRequest();
744 HttpRequestInfo httpreq2 = CreateGetRequest();
745 HttpRequestInfo httpreq3 = CreateGetRequest();
746
747 out.rv = trans1->Start(&httpreq1, &callback1, log);
748 ASSERT_EQ(out.rv, ERR_IO_PENDING);
749 // run transaction 1 through quickly to force a read of our SETTINGS
750 // frame
751 out.rv = callback1.WaitForResult();
752
753 out.rv = trans2->Start(&httpreq2, &callback2, log);
754 ASSERT_EQ(out.rv, ERR_IO_PENDING);
755 out.rv = trans3->Start(&httpreq3, &callback3, log);
756 delete trans3.release();
757 ASSERT_EQ(out.rv, ERR_IO_PENDING);
758 out.rv = callback2.WaitForResult();
759
760 EXPECT_EQ(8U, data->read_index());
761
762 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
763 EXPECT_TRUE(response1->headers != NULL);
764 EXPECT_TRUE(response1->was_fetched_via_spdy);
765 out.status_line = response1->headers->GetStatusLine();
766 out.response_info = *response1;
767 out.rv = ReadTransaction(trans1.get(), &out.response_data);
768 EXPECT_EQ(OK, out.rv);
769 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
770 EXPECT_EQ("hello!hello!", out.response_data);
771
772 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
773 out.status_line = response2->headers->GetStatusLine();
774 out.response_info = *response2;
775 out.rv = ReadTransaction(trans2.get(), &out.response_data);
776 EXPECT_EQ(OK, out.rv);
777 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
778 EXPECT_EQ("hello!hello!", out.response_data);
779 }
780 EXPECT_EQ(OK, out.rv);
781
782 EXPECT_TRUE(data->at_read_eof());
783 EXPECT_TRUE(data->at_write_eof());
784}
785
[email protected]72552f02009-10-28 15:25:01786// Test that a simple POST works.
[email protected]9e9e842e2010-07-23 23:09:15787TEST_P(SpdyNetworkTransactionTest, Post) {
[email protected]a4aeaf42010-06-30 19:57:28788 static const char upload[] = { "hello!" };
[email protected]72552f02009-10-28 15:25:01789
790 // Setup the request
791 HttpRequestInfo request;
792 request.method = "POST";
793 request.url = GURL("http://www.google.com/");
794 request.upload_data = new UploadData();
[email protected]a4aeaf42010-06-30 19:57:28795 request.upload_data->AppendBytes(upload, strlen(upload));
[email protected]72552f02009-10-28 15:25:01796
[email protected]a4aeaf42010-06-30 19:57:28797 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(NULL, 0));
[email protected]2bd93022010-07-17 00:58:44798 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]ff57bb82009-11-12 06:52:14799 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:13800 CreateMockWrite(*req),
801 CreateMockWrite(*body), // POST upload frame
[email protected]ff57bb82009-11-12 06:52:14802 };
[email protected]72552f02009-10-28 15:25:01803
[email protected]a4aeaf42010-06-30 19:57:28804 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
[email protected]ff57bb82009-11-12 06:52:14805 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:13806 CreateMockRead(*resp),
807 CreateMockRead(*body),
[email protected]72552f02009-10-28 15:25:01808 MockRead(true, 0, 0) // EOF
[email protected]aea80602009-09-18 00:55:08809 };
810
[email protected]bf2491a92009-11-29 16:39:48811 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:39812 new DelayedSocketData(2, reads, arraysize(reads),
813 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:47814 NormalSpdyTransactionHelper helper(request,
[email protected]9e9e842e2010-07-23 23:09:15815 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:47816 helper.RunToCompletion(data.get());
817 TransactionHelperResult out = helper.output();
[email protected]aea80602009-09-18 00:55:08818 EXPECT_EQ(OK, out.rv);
819 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
820 EXPECT_EQ("hello!", out.response_data);
821}
822
[email protected]edd3b0a52009-11-24 18:56:36823// Test that a simple POST works.
[email protected]9e9e842e2010-07-23 23:09:15824TEST_P(SpdyNetworkTransactionTest, EmptyPost) {
[email protected]edd3b0a52009-11-24 18:56:36825 // Setup the request
826 HttpRequestInfo request;
827 request.method = "POST";
828 request.url = GURL("http://www.google.com/");
829 // Create an empty UploadData.
830 request.upload_data = new UploadData();
831
[email protected]a4aeaf42010-06-30 19:57:28832 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(NULL, 0));
833 // Set the FIN bit since there will be no body.
834 req->set_flags(spdy::CONTROL_FLAG_FIN);
[email protected]edd3b0a52009-11-24 18:56:36835 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:13836 CreateMockWrite(*req),
[email protected]edd3b0a52009-11-24 18:56:36837 };
838
[email protected]a4aeaf42010-06-30 19:57:28839 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
[email protected]2bd93022010-07-17 00:58:44840 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]edd3b0a52009-11-24 18:56:36841 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:13842 CreateMockRead(*resp),
843 CreateMockRead(*body),
[email protected]edd3b0a52009-11-24 18:56:36844 MockRead(true, 0, 0) // EOF
845 };
846
[email protected]bf2491a92009-11-29 16:39:48847 scoped_refptr<DelayedSocketData> data(
[email protected]3f662f12010-03-25 19:56:12848 new DelayedSocketData(1, reads, arraysize(reads),
849 writes, arraysize(writes)));
[email protected]bf2491a92009-11-29 16:39:48850
[email protected]3caf5542010-07-16 15:19:47851 NormalSpdyTransactionHelper helper(request,
[email protected]9e9e842e2010-07-23 23:09:15852 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:47853 helper.RunToCompletion(data.get());
854 TransactionHelperResult out = helper.output();
[email protected]edd3b0a52009-11-24 18:56:36855 EXPECT_EQ(OK, out.rv);
856 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
857 EXPECT_EQ("hello!", out.response_data);
858}
859
[email protected]a5566f9702010-05-05 22:25:43860// While we're doing a post, the server sends back a SYN_REPLY.
[email protected]9e9e842e2010-07-23 23:09:15861TEST_P(SpdyNetworkTransactionTest, PostWithEarlySynReply) {
[email protected]a4aeaf42010-06-30 19:57:28862 static const char upload[] = { "hello!" };
[email protected]a5566f9702010-05-05 22:25:43863
864 // Setup the request
865 HttpRequestInfo request;
866 request.method = "POST";
867 request.url = GURL("http://www.google.com/");
868 request.upload_data = new UploadData();
869 request.upload_data->AppendBytes(upload, sizeof(upload));
870
[email protected]a4aeaf42010-06-30 19:57:28871 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(NULL, 0));
[email protected]2bd93022010-07-17 00:58:44872 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]a4aeaf42010-06-30 19:57:28873 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:13874 CreateMockWrite(*req.get(), 2),
875 CreateMockWrite(*body.get(), 3), // POST upload frame
[email protected]a5566f9702010-05-05 22:25:43876 };
877
[email protected]a4aeaf42010-06-30 19:57:28878 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
[email protected]a5566f9702010-05-05 22:25:43879 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:13880 CreateMockRead(*resp.get(), 2),
881 CreateMockRead(*body.get(), 3),
[email protected]a5566f9702010-05-05 22:25:43882 MockRead(false, 0, 0) // EOF
883 };
884
885 scoped_refptr<DelayedSocketData> data(
886 new DelayedSocketData(0, reads, arraysize(reads),
887 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:47888 NormalSpdyTransactionHelper helper(request,
[email protected]9e9e842e2010-07-23 23:09:15889 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:47890 helper.AddData(data.get());
891 helper.RunPreTestSetup();
892 helper.RunDefaultTest();
893 helper.VerifyDataNotConsumed();
894 TransactionHelperResult out = helper.output();
[email protected]a5566f9702010-05-05 22:25:43895 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
896}
897
[email protected]93300672009-10-24 13:22:51898// Test that the transaction doesn't crash when we don't have a reply.
[email protected]9e9e842e2010-07-23 23:09:15899TEST_P(SpdyNetworkTransactionTest, ResponseWithoutSynReply) {
[email protected]2bd93022010-07-17 00:58:44900 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]ff57bb82009-11-12 06:52:14901 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:13902 CreateMockRead(*body),
[email protected]72552f02009-10-28 15:25:01903 MockRead(true, 0, 0) // EOF
[email protected]93300672009-10-24 13:22:51904 };
905
[email protected]bf2491a92009-11-29 16:39:48906 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:39907 new DelayedSocketData(1, reads, arraysize(reads), NULL, 0));
[email protected]3caf5542010-07-16 15:19:47908 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:15909 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:47910 helper.RunToCompletion(data.get());
911 TransactionHelperResult out = helper.output();
[email protected]93300672009-10-24 13:22:51912 EXPECT_EQ(ERR_SYN_REPLY_NOT_RECEIVED, out.rv);
913}
914
[email protected]d30022352010-06-24 19:17:58915// Test that the transaction doesn't crash when we get two replies on the same
916// stream ID. See http://crbug.com/45639.
[email protected]9e9e842e2010-07-23 23:09:15917TEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
[email protected]2bd93022010-07-17 00:58:44918 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:13919 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]d30022352010-06-24 19:17:58920
[email protected]2bd93022010-07-17 00:58:44921 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
922 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]d30022352010-06-24 19:17:58923 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:13924 CreateMockRead(*resp),
925 CreateMockRead(*resp),
926 CreateMockRead(*body),
[email protected]d30022352010-06-24 19:17:58927 MockRead(true, 0, 0) // EOF
928 };
929
[email protected]d30022352010-06-24 19:17:58930 scoped_refptr<DelayedSocketData> data(
931 new DelayedSocketData(1, reads, arraysize(reads),
932 writes, arraysize(writes)));
[email protected]d30022352010-06-24 19:17:58933
[email protected]3caf5542010-07-16 15:19:47934 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:15935 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:47936 helper.AddData(data.get());
937 helper.RunPreTestSetup();
938
939 HttpNetworkTransaction* trans = helper.trans();
[email protected]d30022352010-06-24 19:17:58940
941 TestCompletionCallback callback;
[email protected]3caf5542010-07-16 15:19:47942 int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
[email protected]d30022352010-06-24 19:17:58943 EXPECT_EQ(ERR_IO_PENDING, rv);
944 rv = callback.WaitForResult();
945 EXPECT_EQ(OK, rv);
946
947 const HttpResponseInfo* response = trans->GetResponseInfo();
948 EXPECT_TRUE(response->headers != NULL);
949 EXPECT_TRUE(response->was_fetched_via_spdy);
950 std::string response_data;
[email protected]3caf5542010-07-16 15:19:47951 rv = ReadTransaction(trans, &response_data);
[email protected]d30022352010-06-24 19:17:58952 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
[email protected]3caf5542010-07-16 15:19:47953
954 helper.VerifyDataConsumed();
[email protected]d30022352010-06-24 19:17:58955}
956
[email protected]7349c6b12010-07-22 02:29:16957// Test that sent data frames and received WINDOW_UPDATE frames change
958// the send_window_size_ correctly.
[email protected]9e9e842e2010-07-23 23:09:15959TEST_P(SpdyNetworkTransactionTest, WindowUpdate) {
[email protected]30c942b2010-07-21 16:59:59960 SpdySessionDependencies session_deps;
961 scoped_refptr<HttpNetworkSession> session =
962 SpdySessionDependencies::SpdyCreateSession(&session_deps);
[email protected]5af3c572010-07-20 14:16:27963
[email protected]5af3c572010-07-20 14:16:27964 SpdySession::SetSSLMode(false);
[email protected]7349c6b12010-07-22 02:29:16965 SpdySession::SetFlowControl(true);
[email protected]5af3c572010-07-20 14:16:27966
967 // Setup the request
[email protected]7349c6b12010-07-22 02:29:16968 static const char kUploadData[] = "hello!";
969 static const int kUploadDataSize = arraysize(kUploadData)-1;
[email protected]5af3c572010-07-20 14:16:27970 HttpRequestInfo request;
971 request.method = "POST";
972 request.url = GURL("http://www.google.com/");
973 request.upload_data = new UploadData();
[email protected]7349c6b12010-07-22 02:29:16974 request.upload_data->AppendBytes(kUploadData, kUploadDataSize);
[email protected]5af3c572010-07-20 14:16:27975
976 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(NULL, 0));
977 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
978 MockWrite writes[] = {
979 CreateMockWrite(*req),
980 CreateMockWrite(*body),
981 };
982
983 // Response frames, send WINDOW_UPDATE first
984 static const int kDeltaWindowSize = 0xff;
985 scoped_ptr<spdy::SpdyFrame> window_update(
986 ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
987 scoped_ptr<spdy::SpdyFrame> reply(ConstructSpdyPostSynReply(NULL, 0));
988 MockRead reads[] = {
989 CreateMockRead(*window_update),
990 CreateMockRead(*reply),
991 CreateMockRead(*body),
992 MockRead(true, 0, 0) // EOF
993 };
994
995 scoped_refptr<DelayedSocketData> data(
996 new DelayedSocketData(2, reads, arraysize(reads),
997 writes, arraysize(writes)));
998 session_deps.socket_factory.AddSocketDataProvider(data.get());
999
1000 scoped_ptr<SpdyNetworkTransaction> trans(
1001 new SpdyNetworkTransaction(session));
1002
1003 TestCompletionCallback callback;
1004 int rv = trans->Start(&request, &callback, BoundNetLog());
1005
1006 ASSERT_TRUE(trans->stream_ != NULL);
1007 ASSERT_TRUE(trans->stream_->stream() != NULL);
[email protected]7349c6b12010-07-22 02:29:161008 EXPECT_EQ(spdy::kInitialWindowSize,
1009 trans->stream_->stream()->send_window_size());
[email protected]5af3c572010-07-20 14:16:271010
1011 EXPECT_EQ(ERR_IO_PENDING, rv);
1012 rv = callback.WaitForResult();
1013 EXPECT_EQ(OK, rv);
1014
1015 ASSERT_TRUE(trans->stream_ != NULL);
1016 ASSERT_TRUE(trans->stream_->stream() != NULL);
[email protected]7349c6b12010-07-22 02:29:161017 EXPECT_EQ(spdy::kInitialWindowSize + kDeltaWindowSize - kUploadDataSize,
1018 trans->stream_->stream()->send_window_size());
[email protected]5af3c572010-07-20 14:16:271019 EXPECT_TRUE(data->at_read_eof());
1020 EXPECT_TRUE(data->at_write_eof());
[email protected]7349c6b12010-07-22 02:29:161021
1022 SpdySession::SetFlowControl(false);
[email protected]5af3c572010-07-20 14:16:271023}
1024
1025// Test that WINDOW_UPDATE frame causing overflow is handled correctly.
[email protected]9e9e842e2010-07-23 23:09:151026TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
[email protected]30c942b2010-07-21 16:59:591027 SpdySessionDependencies session_deps;
1028 scoped_refptr<HttpNetworkSession> session =
1029 SpdySessionDependencies::SpdyCreateSession(&session_deps);
[email protected]5af3c572010-07-20 14:16:271030
[email protected]5af3c572010-07-20 14:16:271031 SpdySession::SetSSLMode(false);
[email protected]7349c6b12010-07-22 02:29:161032 SpdySession::SetFlowControl(true);
[email protected]5af3c572010-07-20 14:16:271033
1034 // Setup the request
[email protected]7349c6b12010-07-22 02:29:161035 static const char kUploadData[] = "hello!";
[email protected]5af3c572010-07-20 14:16:271036 HttpRequestInfo request;
1037 request.method = "POST";
1038 request.url = GURL("http://www.google.com/");
1039 request.upload_data = new UploadData();
[email protected]7349c6b12010-07-22 02:29:161040 request.upload_data->AppendBytes(kUploadData, arraysize(kUploadData)-1);
[email protected]5af3c572010-07-20 14:16:271041
1042 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(NULL, 0));
1043 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1044 scoped_ptr<spdy::SpdyFrame> rst(
1045 ConstructSpdyRstStream(1, spdy::FLOW_CONTROL_ERROR));
1046 MockWrite writes[] = {
1047 CreateMockWrite(*req),
1048 CreateMockWrite(*body),
1049 CreateMockWrite(*rst),
1050 };
1051
1052 // Response frames, send WINDOW_UPDATE first
1053 static const int kDeltaWindowSize = 0x7fffffff; // cause an overflow
1054 scoped_ptr<spdy::SpdyFrame> window_update(
1055 ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
1056 scoped_ptr<spdy::SpdyFrame> reply(ConstructSpdyPostSynReply(NULL, 0));
1057 MockRead reads[] = {
1058 CreateMockRead(*window_update),
1059 CreateMockRead(*reply),
1060 CreateMockRead(*body),
1061 MockRead(true, 0, 0) // EOF
1062 };
1063
1064 scoped_refptr<DelayedSocketData> data(
1065 new DelayedSocketData(2, reads, arraysize(reads),
1066 writes, arraysize(writes)));
1067 session_deps.socket_factory.AddSocketDataProvider(data.get());
1068
1069 scoped_ptr<SpdyNetworkTransaction> trans(
1070 new SpdyNetworkTransaction(session));
1071
1072 TestCompletionCallback callback;
1073 int rv = trans->Start(&request, &callback, BoundNetLog());
1074
1075 ASSERT_TRUE(trans->stream_ != NULL);
1076 ASSERT_TRUE(trans->stream_->stream() != NULL);
[email protected]7349c6b12010-07-22 02:29:161077 EXPECT_EQ(spdy::kInitialWindowSize,
1078 trans->stream_->stream()->send_window_size());
[email protected]5af3c572010-07-20 14:16:271079
1080 EXPECT_EQ(ERR_IO_PENDING, rv);
1081 rv = callback.WaitForResult();
1082 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
1083
1084 ASSERT_TRUE(session != NULL);
1085 ASSERT_TRUE(session->spdy_session_pool() != NULL);
1086 session->spdy_session_pool()->ClearSessions();
1087
1088 EXPECT_FALSE(data->at_read_eof());
1089 EXPECT_TRUE(data->at_write_eof());
[email protected]7349c6b12010-07-22 02:29:161090
1091 SpdySession::SetFlowControl(false);
[email protected]5af3c572010-07-20 14:16:271092}
1093
[email protected]9e9e842e2010-07-23 23:09:151094TEST_P(SpdyNetworkTransactionTest, CancelledTransaction) {
[email protected]75f30cc22010-06-28 21:41:381095 // Construct the request.
[email protected]2bd93022010-07-17 00:58:441096 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]34437af82009-11-06 02:28:491097 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:131098 CreateMockWrite(*req),
[email protected]34437af82009-11-06 02:28:491099 };
1100
[email protected]2bd93022010-07-17 00:58:441101 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]34437af82009-11-06 02:28:491102 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:131103 CreateMockRead(*resp),
[email protected]34437af82009-11-06 02:28:491104 // This following read isn't used by the test, except during the
[email protected]955fc2e72010-02-08 20:37:301105 // RunAllPending() call at the end since the SpdySession survives the
[email protected]3caf5542010-07-16 15:19:471106 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
[email protected]34437af82009-11-06 02:28:491107 // MockRead will do here.
1108 MockRead(true, 0, 0) // EOF
1109 };
1110
[email protected]31a2bfe2010-02-09 08:03:391111 StaticSocketDataProvider data(reads, arraysize(reads),
1112 writes, arraysize(writes));
[email protected]3caf5542010-07-16 15:19:471113
1114 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:151115 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:471116 helper.AddData(&data);
1117 helper.RunPreTestSetup();
1118 HttpNetworkTransaction* trans = helper.trans();
[email protected]34437af82009-11-06 02:28:491119
1120 TestCompletionCallback callback;
[email protected]d3cee19d2010-06-22 18:42:181121 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
[email protected]34437af82009-11-06 02:28:491122 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3caf5542010-07-16 15:19:471123 helper.ResetTrans(); // Cancel the transaction.
[email protected]34437af82009-11-06 02:28:491124
[email protected]30c942b2010-07-21 16:59:591125 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]34437af82009-11-06 02:28:491126 // MockClientSocketFactory) are still alive.
1127 MessageLoop::current()->RunAllPending();
[email protected]3caf5542010-07-16 15:19:471128 helper.VerifyDataNotConsumed();
[email protected]34437af82009-11-06 02:28:491129}
[email protected]72552f02009-10-28 15:25:011130
[email protected]6c6ea172010-07-27 20:04:031131// Verify that the client sends a Rst Frame upon cancelling the stream.
1132TEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
1133 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1134 scoped_ptr<spdy::SpdyFrame> rst(
1135 ConstructSpdyRstStream(1, spdy::CANCEL));
1136 MockWrite writes[] = {
1137 CreateMockWrite(*req, 1),
1138 CreateMockWrite(*rst, 3),
1139 };
1140
1141 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1142 MockRead reads[] = {
1143 CreateMockRead(*resp, 2),
1144 MockRead(true, 0, 0, 4) // EOF
1145 };
1146
1147 scoped_refptr<OrderedSocketData> data(
1148 new OrderedSocketData(reads, arraysize(reads),
1149 writes, arraysize(writes)));
1150
1151 NormalSpdyTransactionHelper helper(CreateGetRequest(),
1152 BoundNetLog(),
1153 GetParam());
1154 helper.AddData(data.get());
1155 helper.RunPreTestSetup();
1156 HttpNetworkTransaction* trans = helper.trans();
1157
1158 TestCompletionCallback callback;
1159
1160 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
1161 EXPECT_EQ(ERR_IO_PENDING, rv);
1162 rv = callback.WaitForResult();
1163 helper.ResetTrans(); // Cancel the transaction.
1164
1165 // Finish running rest of tasks.
1166 MessageLoop::current()->RunAllPending();
1167 data->CompleteRead();
1168 helper.VerifyDataConsumed();
1169}
1170
[email protected]3caf5542010-07-16 15:19:471171class SpdyNetworkTransactionTest::StartTransactionCallback
1172 : public CallbackRunner< Tuple1<int> > {
[email protected]b278eb72010-07-09 20:17:001173 public:
1174 explicit StartTransactionCallback(
[email protected]3caf5542010-07-16 15:19:471175 scoped_refptr<HttpNetworkSession>& session,
1176 NormalSpdyTransactionHelper& helper)
1177 : session_(session), helper_(helper) {}
[email protected]b278eb72010-07-09 20:17:001178
1179 // We try to start another transaction, which should succeed.
1180 virtual void RunWithParams(const Tuple1<int>& params) {
[email protected]3caf5542010-07-16 15:19:471181 scoped_ptr<HttpNetworkTransaction> trans(
1182 new HttpNetworkTransaction(session_));
[email protected]b278eb72010-07-09 20:17:001183 TestCompletionCallback callback;
1184 HttpRequestInfo request;
1185 request.method = "GET";
1186 request.url = GURL("http://www.google.com/");
1187 request.load_flags = 0;
1188 int rv = trans->Start(&request, &callback, BoundNetLog());
1189 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3caf5542010-07-16 15:19:471190 rv = callback.WaitForResult();
[email protected]b278eb72010-07-09 20:17:001191 }
1192
1193 private:
[email protected]3caf5542010-07-16 15:19:471194 scoped_refptr<HttpNetworkSession>& session_;
1195 NormalSpdyTransactionHelper& helper_;
[email protected]b278eb72010-07-09 20:17:001196};
1197
1198// Verify that the client can correctly deal with the user callback attempting
1199// to start another transaction on a session that is closing down. See
1200// http://crbug.com/47455
[email protected]9e9e842e2010-07-23 23:09:151201TEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
[email protected]2bd93022010-07-17 00:58:441202 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]b278eb72010-07-09 20:17:001203 MockWrite writes[] = { CreateMockWrite(*req) };
1204 MockWrite writes2[] = { CreateMockWrite(*req) };
1205
1206 // The indicated length of this packet is longer than its actual length. When
1207 // the session receives an empty packet after this one, it shuts down the
1208 // session, and calls the read callback with the incomplete data.
1209 const uint8 kGetBodyFrame2[] = {
1210 0x00, 0x00, 0x00, 0x01,
1211 0x01, 0x00, 0x00, 0x07,
1212 'h', 'e', 'l', 'l', 'o', '!',
1213 };
1214
[email protected]2bd93022010-07-17 00:58:441215 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]b278eb72010-07-09 20:17:001216 MockRead reads[] = {
1217 CreateMockRead(*resp, 2),
1218 MockRead(true, ERR_IO_PENDING, 3), // Force a pause
1219 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame2),
1220 arraysize(kGetBodyFrame2), 4),
[email protected]3caf5542010-07-16 15:19:471221 MockRead(true, ERR_IO_PENDING, 5), // Force a pause
1222 MockRead(true, 0, 0, 6), // EOF
[email protected]b278eb72010-07-09 20:17:001223 };
1224 MockRead reads2[] = {
1225 CreateMockRead(*resp, 2),
1226 MockRead(true, 0, 0, 3), // EOF
1227 };
1228
[email protected]b278eb72010-07-09 20:17:001229 scoped_refptr<OrderedSocketData> data(
1230 new OrderedSocketData(reads, arraysize(reads),
1231 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:471232 scoped_refptr<DelayedSocketData> data2(
1233 new DelayedSocketData(0, reads2, arraysize(reads2),
[email protected]b278eb72010-07-09 20:17:001234 writes2, arraysize(writes2)));
[email protected]3caf5542010-07-16 15:19:471235
1236 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:151237 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:471238 helper.AddData(data.get());
1239 helper.AddData(data2.get());
1240 helper.RunPreTestSetup();
1241 HttpNetworkTransaction* trans = helper.trans();
[email protected]b278eb72010-07-09 20:17:001242
1243 // Start the transaction with basic parameters.
1244 TestCompletionCallback callback;
[email protected]3caf5542010-07-16 15:19:471245 int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
[email protected]b278eb72010-07-09 20:17:001246 EXPECT_EQ(ERR_IO_PENDING, rv);
1247 rv = callback.WaitForResult();
1248
[email protected]3caf5542010-07-16 15:19:471249 StartTransactionCallback callback2(helper.session(), helper);
[email protected]b278eb72010-07-09 20:17:001250 const int kSize = 3000;
1251 scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(kSize);
1252 rv = trans->Read(buf, kSize, &callback2);
[email protected]3caf5542010-07-16 15:19:471253 // This forces an err_IO_pending, which sets the callback.
[email protected]b278eb72010-07-09 20:17:001254 data->CompleteRead();
[email protected]3caf5542010-07-16 15:19:471255 // This finishes the read.
1256 data->CompleteRead();
1257 helper.VerifyDataConsumed();
[email protected]b278eb72010-07-09 20:17:001258}
1259
[email protected]3caf5542010-07-16 15:19:471260class SpdyNetworkTransactionTest::DeleteSessionCallback
1261 : public CallbackRunner< Tuple1<int> > {
[email protected]9be804c82010-06-24 17:59:461262 public:
[email protected]3caf5542010-07-16 15:19:471263 explicit DeleteSessionCallback(NormalSpdyTransactionHelper& helper) :
1264 helper_(helper) {}
[email protected]9be804c82010-06-24 17:59:461265
[email protected]b278eb72010-07-09 20:17:001266 // We kill the transaction, which deletes the session and stream.
[email protected]9be804c82010-06-24 17:59:461267 virtual void RunWithParams(const Tuple1<int>& params) {
[email protected]3caf5542010-07-16 15:19:471268 helper_.ResetTrans();
[email protected]9be804c82010-06-24 17:59:461269 }
1270
1271 private:
[email protected]3caf5542010-07-16 15:19:471272 NormalSpdyTransactionHelper& helper_;
[email protected]9be804c82010-06-24 17:59:461273};
1274
1275// Verify that the client can correctly deal with the user callback deleting the
1276// transaction. Failures will usually be valgrind errors. See
1277// http://crbug.com/46925
[email protected]9e9e842e2010-07-23 23:09:151278TEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
[email protected]2bd93022010-07-17 00:58:441279 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:131280 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]9be804c82010-06-24 17:59:461281
[email protected]2bd93022010-07-17 00:58:441282 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1283 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]9be804c82010-06-24 17:59:461284 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:131285 CreateMockRead(*resp.get(), 2),
[email protected]9be804c82010-06-24 17:59:461286 MockRead(true, ERR_IO_PENDING, 3), // Force a pause
[email protected]e7f75092010-07-01 22:39:131287 CreateMockRead(*body.get(), 4),
[email protected]9be804c82010-06-24 17:59:461288 MockRead(true, 0, 0, 5), // EOF
1289 };
1290
[email protected]9be804c82010-06-24 17:59:461291 scoped_refptr<OrderedSocketData> data(
1292 new OrderedSocketData(reads, arraysize(reads),
1293 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:471294
1295 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:151296 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:471297 helper.AddData(data.get());
1298 helper.RunPreTestSetup();
1299 HttpNetworkTransaction* trans = helper.trans();
[email protected]9be804c82010-06-24 17:59:461300
1301 // Start the transaction with basic parameters.
1302 TestCompletionCallback callback;
[email protected]3caf5542010-07-16 15:19:471303 int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
[email protected]9be804c82010-06-24 17:59:461304 EXPECT_EQ(ERR_IO_PENDING, rv);
1305 rv = callback.WaitForResult();
1306
1307 // Setup a user callback which will delete the session, and clear out the
1308 // memory holding the stream object. Note that the callback deletes trans.
[email protected]3caf5542010-07-16 15:19:471309 DeleteSessionCallback callback2(helper);
[email protected]9be804c82010-06-24 17:59:461310 const int kSize = 3000;
1311 scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(kSize);
1312 rv = trans->Read(buf, kSize, &callback2);
1313 ASSERT_EQ(ERR_IO_PENDING, rv);
1314 data->CompleteRead();
1315
1316 // Finish running rest of tasks.
1317 MessageLoop::current()->RunAllPending();
[email protected]3caf5542010-07-16 15:19:471318 helper.VerifyDataConsumed();
[email protected]9be804c82010-06-24 17:59:461319}
1320
[email protected]8b070372009-11-16 22:01:251321// Verify that various SynReply headers parse correctly through the
1322// HTTP layer.
[email protected]9e9e842e2010-07-23 23:09:151323TEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) {
[email protected]e7f75092010-07-01 22:39:131324 struct SynReplyHeadersTests {
1325 int num_headers;
1326 const char* extra_headers[5];
[email protected]8b070372009-11-16 22:01:251327 const char* expected_headers;
1328 } test_cases[] = {
[email protected]e7f75092010-07-01 22:39:131329 // This uses a multi-valued cookie header.
1330 { 2,
1331 { "cookie", "val1",
1332 "cookie", "val2", // will get appended separated by NULL
1333 NULL
1334 },
[email protected]8b070372009-11-16 22:01:251335 "cookie: val1\n"
1336 "cookie: val2\n"
[email protected]e7f75092010-07-01 22:39:131337 "hello: bye\n"
[email protected]8b070372009-11-16 22:01:251338 "status: 200\n"
1339 "url: /index.php\n"
1340 "version: HTTP/1.1\n"
1341 },
[email protected]e7f75092010-07-01 22:39:131342 // This is the minimalist set of headers.
1343 { 0,
1344 { NULL },
1345 "hello: bye\n"
[email protected]8b070372009-11-16 22:01:251346 "status: 200\n"
1347 "url: /index.php\n"
1348 "version: HTTP/1.1\n"
1349 },
[email protected]e7f75092010-07-01 22:39:131350 // Headers with a comma separated list.
1351 { 1,
1352 { "cookie", "val1,val2",
1353 NULL
1354 },
[email protected]8b070372009-11-16 22:01:251355 "cookie: val1,val2\n"
[email protected]e7f75092010-07-01 22:39:131356 "hello: bye\n"
[email protected]8b070372009-11-16 22:01:251357 "status: 200\n"
1358 "url: /index.php\n"
1359 "version: HTTP/1.1\n"
1360 }
1361 };
1362
1363 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
[email protected]2bd93022010-07-17 00:58:441364 scoped_ptr<spdy::SpdyFrame> req(
1365 ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:131366 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]8b070372009-11-16 22:01:251367
[email protected]e7f75092010-07-01 22:39:131368 scoped_ptr<spdy::SpdyFrame> resp(
1369 ConstructSpdyGetSynReply(test_cases[i].extra_headers,
[email protected]2bd93022010-07-17 00:58:441370 test_cases[i].num_headers,
1371 1));
1372 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]8b070372009-11-16 22:01:251373 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:131374 CreateMockRead(*resp),
1375 CreateMockRead(*body),
[email protected]8b070372009-11-16 22:01:251376 MockRead(true, 0, 0) // EOF
1377 };
1378
[email protected]bf2491a92009-11-29 16:39:481379 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:391380 new DelayedSocketData(1, reads, arraysize(reads),
1381 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:471382 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:151383 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:471384 helper.RunToCompletion(data.get());
1385 TransactionHelperResult out = helper.output();
1386
[email protected]8b070372009-11-16 22:01:251387 EXPECT_EQ(OK, out.rv);
1388 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1389 EXPECT_EQ("hello!", out.response_data);
1390
1391 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
1392 EXPECT_TRUE(headers.get() != NULL);
1393 void* iter = NULL;
1394 std::string name, value, lines;
1395 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
1396 lines.append(name);
1397 lines.append(": ");
1398 lines.append(value);
1399 lines.append("\n");
1400 }
1401 EXPECT_EQ(std::string(test_cases[i].expected_headers), lines);
1402 }
1403}
1404
[email protected]3f662f12010-03-25 19:56:121405// Verify that various SynReply headers parse vary fields correctly
1406// through the HTTP layer, and the response matches the request.
[email protected]9e9e842e2010-07-23 23:09:151407TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) {
[email protected]3f662f12010-03-25 19:56:121408 static const SpdyHeaderInfo syn_reply_info = {
1409 spdy::SYN_REPLY, // Syn Reply
1410 1, // Stream ID
1411 0, // Associated Stream ID
[email protected]75f30cc22010-06-28 21:41:381412 SPDY_PRIORITY_LOWEST, // Priority
[email protected]3f662f12010-03-25 19:56:121413 spdy::CONTROL_FLAG_NONE, // Control Flags
1414 false, // Compressed
[email protected]75f30cc22010-06-28 21:41:381415 spdy::INVALID, // Status
[email protected]3f662f12010-03-25 19:56:121416 NULL, // Data
1417 0, // Data Length
1418 spdy::DATA_FLAG_NONE // Data Flags
1419 };
1420 // Modify the following data to change/add test cases:
1421 struct SynReplyTests {
1422 const SpdyHeaderInfo* syn_reply;
1423 bool vary_matches;
1424 int num_headers[2];
1425 const char* extra_headers[2][16];
1426 } test_cases[] = {
1427 // Test the case of a multi-valued cookie. When the value is delimited
1428 // with NUL characters, it needs to be unfolded into multiple headers.
1429 {
1430 &syn_reply_info,
1431 true,
[email protected]8c76ae22010-04-20 22:15:431432 { 1, 4 },
1433 { { "cookie", "val1,val2",
[email protected]3f662f12010-03-25 19:56:121434 NULL
1435 },
1436 { "vary", "cookie",
1437 "status", "200",
1438 "url", "/index.php",
1439 "version", "HTTP/1.1",
1440 NULL
1441 }
1442 }
1443 }, { // Multiple vary fields.
1444 &syn_reply_info,
1445 true,
1446 { 2, 5 },
1447 { { "friend", "barney",
1448 "enemy", "snaggletooth",
1449 NULL
1450 },
1451 { "vary", "friend",
1452 "vary", "enemy",
1453 "status", "200",
1454 "url", "/index.php",
1455 "version", "HTTP/1.1",
1456 NULL
1457 }
1458 }
1459 }, { // Test a '*' vary field.
1460 &syn_reply_info,
1461 false,
1462 { 1, 4 },
1463 { { "cookie", "val1,val2",
1464 NULL
1465 },
1466 { "vary", "*",
1467 "status", "200",
1468 "url", "/index.php",
1469 "version", "HTTP/1.1",
1470 NULL
1471 }
1472 }
1473 }, { // Multiple comma-separated vary fields.
1474 &syn_reply_info,
1475 true,
1476 { 2, 4 },
1477 { { "friend", "barney",
1478 "enemy", "snaggletooth",
1479 NULL
1480 },
1481 { "vary", "friend,enemy",
1482 "status", "200",
1483 "url", "/index.php",
1484 "version", "HTTP/1.1",
1485 NULL
1486 }
1487 }
1488 }
1489 };
1490
1491 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
[email protected]3f662f12010-03-25 19:56:121492 // Construct the request.
1493 scoped_ptr<spdy::SpdyFrame> frame_req(
1494 ConstructSpdyGet(test_cases[i].extra_headers[0],
[email protected]2bd93022010-07-17 00:58:441495 test_cases[i].num_headers[0],
1496 false, 1, LOWEST));
[email protected]3f662f12010-03-25 19:56:121497
1498 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:131499 CreateMockWrite(*frame_req),
[email protected]3f662f12010-03-25 19:56:121500 };
1501
1502 // Construct the reply.
1503 scoped_ptr<spdy::SpdyFrame> frame_reply(
[email protected]a4aeaf42010-06-30 19:57:281504 ConstructSpdyPacket(*test_cases[i].syn_reply,
[email protected]3f662f12010-03-25 19:56:121505 test_cases[i].extra_headers[1],
1506 test_cases[i].num_headers[1],
1507 NULL,
1508 0));
1509
[email protected]2bd93022010-07-17 00:58:441510 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]3f662f12010-03-25 19:56:121511 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:131512 CreateMockRead(*frame_reply),
1513 CreateMockRead(*body),
[email protected]3f662f12010-03-25 19:56:121514 MockRead(true, 0, 0) // EOF
1515 };
1516
[email protected]3f662f12010-03-25 19:56:121517 // Attach the headers to the request.
[email protected]8c76ae22010-04-20 22:15:431518 int header_count = test_cases[i].num_headers[0];
[email protected]3f662f12010-03-25 19:56:121519
[email protected]d3cee19d2010-06-22 18:42:181520 HttpRequestInfo request = CreateGetRequest();
[email protected]8c76ae22010-04-20 22:15:431521 for (int ct = 0; ct < header_count; ct++) {
1522 const char* header_key = test_cases[i].extra_headers[0][ct * 2];
1523 const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1];
1524 request.extra_headers.SetHeader(header_key, header_value);
[email protected]3f662f12010-03-25 19:56:121525 }
1526
1527 scoped_refptr<DelayedSocketData> data(
1528 new DelayedSocketData(1, reads, arraysize(reads),
1529 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:471530 NormalSpdyTransactionHelper helper(request,
[email protected]9e9e842e2010-07-23 23:09:151531 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:471532 helper.RunToCompletion(data.get());
1533 TransactionHelperResult out = helper.output();
1534
[email protected]3f662f12010-03-25 19:56:121535 EXPECT_EQ(OK, out.rv) << i;
1536 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line) << i;
1537 EXPECT_EQ("hello!", out.response_data) << i;
1538
1539 // Test the response information.
1540 EXPECT_TRUE(out.response_info.response_time >
1541 out.response_info.request_time) << i;
1542 base::TimeDelta test_delay = out.response_info.response_time -
1543 out.response_info.request_time;
1544 base::TimeDelta min_expected_delay;
1545 min_expected_delay.FromMilliseconds(10);
1546 EXPECT_GT(test_delay.InMillisecondsF(),
1547 min_expected_delay.InMillisecondsF()) << i;
1548 EXPECT_EQ(out.response_info.vary_data.is_valid(),
1549 test_cases[i].vary_matches) << i;
1550
1551 // Check the headers.
1552 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
1553 ASSERT_TRUE(headers.get() != NULL) << i;
1554 void* iter = NULL;
1555 std::string name, value, lines;
1556 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
1557 lines.append(name);
1558 lines.append(": ");
1559 lines.append(value);
1560 lines.append("\n");
1561 }
1562
1563 // Construct the expected header reply string.
1564 char reply_buffer[256] = "";
[email protected]75f30cc22010-06-28 21:41:381565 ConstructSpdyReplyString(test_cases[i].extra_headers[1],
1566 test_cases[i].num_headers[1],
1567 reply_buffer,
1568 256);
[email protected]3f662f12010-03-25 19:56:121569
1570 EXPECT_EQ(std::string(reply_buffer), lines) << i;
1571 }
1572}
1573
[email protected]dd11b932009-11-30 19:39:481574// Verify that we don't crash on invalid SynReply responses.
[email protected]9e9e842e2010-07-23 23:09:151575TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) {
[email protected]e7f75092010-07-01 22:39:131576 const SpdyHeaderInfo kSynStartHeader = {
1577 spdy::SYN_REPLY, // Kind = SynReply
1578 1, // Stream ID
1579 0, // Associated stream ID
1580 SPDY_PRIORITY_LOWEST, // Priority
1581 spdy::CONTROL_FLAG_NONE, // Control Flags
1582 false, // Compressed
1583 spdy::INVALID, // Status
1584 NULL, // Data
1585 0, // Length
1586 spdy::DATA_FLAG_NONE // Data Flags
[email protected]dd11b932009-11-30 19:39:481587 };
1588
[email protected]e7f75092010-07-01 22:39:131589 struct InvalidSynReplyTests {
1590 int num_headers;
1591 const char* headers[10];
[email protected]dd11b932009-11-30 19:39:481592 } test_cases[] = {
[email protected]e7f75092010-07-01 22:39:131593 // SYN_REPLY missing status header
1594 { 4,
1595 { "cookie", "val1",
1596 "cookie", "val2",
1597 "url", "/index.php",
1598 "version", "HTTP/1.1",
1599 NULL
1600 },
1601 },
1602 // SYN_REPLY missing version header
1603 { 2,
1604 { "status", "200",
1605 "url", "/index.php",
1606 NULL
1607 },
1608 },
[email protected]0d384bb2010-07-14 01:51:121609 // SYN_REPLY with no headers
1610 { 0, { NULL }, },
[email protected]dd11b932009-11-30 19:39:481611 };
1612
1613 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
[email protected]2bd93022010-07-17 00:58:441614 scoped_ptr<spdy::SpdyFrame> req(
1615 ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]dd11b932009-11-30 19:39:481616 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:131617 CreateMockWrite(*req),
[email protected]dd11b932009-11-30 19:39:481618 };
1619
[email protected]e7f75092010-07-01 22:39:131620 scoped_ptr<spdy::SpdyFrame> resp(
1621 ConstructSpdyPacket(kSynStartHeader,
1622 NULL, 0,
1623 test_cases[i].headers,
1624 test_cases[i].num_headers));
[email protected]2bd93022010-07-17 00:58:441625 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]dd11b932009-11-30 19:39:481626 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:131627 CreateMockRead(*resp),
1628 CreateMockRead(*body),
[email protected]dd11b932009-11-30 19:39:481629 MockRead(true, 0, 0) // EOF
1630 };
1631
[email protected]dd11b932009-11-30 19:39:481632 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:391633 new DelayedSocketData(1, reads, arraysize(reads),
1634 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:471635 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:151636 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:471637 helper.RunToCompletion(data.get());
1638 TransactionHelperResult out = helper.output();
[email protected]dd11b932009-11-30 19:39:481639 EXPECT_EQ(ERR_INVALID_RESPONSE, out.rv);
1640 }
1641}
1642
[email protected]94d78132010-01-22 00:53:001643// Verify that we don't crash on some corrupt frames.
[email protected]6f0a3f42010-07-08 21:44:441644// TODO(eroman): Renable this test, see http://crbug.com/48588
[email protected]9e9e842e2010-07-23 23:09:151645TEST_P(SpdyNetworkTransactionTest, DISABLED_CorruptFrameSessionError) {
[email protected]e7f75092010-07-01 22:39:131646 // This is the length field with a big number
1647 scoped_ptr<spdy::SpdyFrame> syn_reply_massive_length(
[email protected]2bd93022010-07-17 00:58:441648 ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]e7f75092010-07-01 22:39:131649 syn_reply_massive_length->set_length(0x111126);
[email protected]94d78132010-01-22 00:53:001650
1651 struct SynReplyTests {
[email protected]e7f75092010-07-01 22:39:131652 const spdy::SpdyFrame* syn_reply;
[email protected]94d78132010-01-22 00:53:001653 } test_cases[] = {
[email protected]e7f75092010-07-01 22:39:131654 { syn_reply_massive_length.get(), },
[email protected]94d78132010-01-22 00:53:001655 };
1656
1657 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
[email protected]2bd93022010-07-17 00:58:441658 scoped_ptr<spdy::SpdyFrame> req(
1659 ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]94d78132010-01-22 00:53:001660 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:131661 CreateMockWrite(*req),
[email protected]94d78132010-01-22 00:53:001662 MockWrite(true, 0, 0) // EOF
1663 };
1664
[email protected]2bd93022010-07-17 00:58:441665 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]94d78132010-01-22 00:53:001666 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:131667 CreateMockRead(*test_cases[i].syn_reply),
1668 CreateMockRead(*body),
[email protected]94d78132010-01-22 00:53:001669 MockRead(true, 0, 0) // EOF
1670 };
1671
[email protected]94d78132010-01-22 00:53:001672 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:391673 new DelayedSocketData(1, reads, arraysize(reads),
1674 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:471675 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:151676 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:471677 helper.RunToCompletion(data.get());
1678 TransactionHelperResult out = helper.output();
[email protected]955fc2e72010-02-08 20:37:301679 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]94d78132010-01-22 00:53:001680 }
1681}
1682
[email protected]bf2491a92009-11-29 16:39:481683// Test that we shutdown correctly on write errors.
[email protected]9e9e842e2010-07-23 23:09:151684TEST_P(SpdyNetworkTransactionTest, WriteError) {
[email protected]2bd93022010-07-17 00:58:441685 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]bf2491a92009-11-29 16:39:481686 MockWrite writes[] = {
1687 // We'll write 10 bytes successfully
[email protected]75f30cc22010-06-28 21:41:381688 MockWrite(true, req->data(), 10),
[email protected]bf2491a92009-11-29 16:39:481689 // Followed by ERROR!
1690 MockWrite(true, ERR_FAILED),
[email protected]bf2491a92009-11-29 16:39:481691 };
1692
[email protected]bf2491a92009-11-29 16:39:481693 scoped_refptr<DelayedSocketData> data(
[email protected]3caf5542010-07-16 15:19:471694 new DelayedSocketData(2, NULL, 0,
[email protected]31a2bfe2010-02-09 08:03:391695 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:471696 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:151697 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:471698 helper.RunToCompletion(data.get());
1699 TransactionHelperResult out = helper.output();
[email protected]bf2491a92009-11-29 16:39:481700 EXPECT_EQ(ERR_FAILED, out.rv);
[email protected]32100cb2009-11-30 18:24:461701 data->Reset();
[email protected]bf2491a92009-11-29 16:39:481702}
1703
1704// Test that partial writes work.
[email protected]9e9e842e2010-07-23 23:09:151705TEST_P(SpdyNetworkTransactionTest, PartialWrite) {
[email protected]bf2491a92009-11-29 16:39:481706 // Chop the SYN_STREAM frame into 5 chunks.
[email protected]2bd93022010-07-17 00:58:441707 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]bf2491a92009-11-29 16:39:481708 const int kChunks = 5;
[email protected]e7f75092010-07-01 22:39:131709 scoped_array<MockWrite> writes(ChopWriteFrame(*req.get(), kChunks));
[email protected]bf2491a92009-11-29 16:39:481710
[email protected]2bd93022010-07-17 00:58:441711 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1712 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]bf2491a92009-11-29 16:39:481713 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:131714 CreateMockRead(*resp),
1715 CreateMockRead(*body),
[email protected]bf2491a92009-11-29 16:39:481716 MockRead(true, 0, 0) // EOF
1717 };
1718
[email protected]bf2491a92009-11-29 16:39:481719 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:391720 new DelayedSocketData(kChunks, reads, arraysize(reads),
1721 writes.get(), kChunks));
[email protected]3caf5542010-07-16 15:19:471722 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:151723 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:471724 helper.RunToCompletion(data.get());
1725 TransactionHelperResult out = helper.output();
[email protected]bf2491a92009-11-29 16:39:481726 EXPECT_EQ(OK, out.rv);
1727 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1728 EXPECT_EQ("hello!", out.response_data);
1729}
1730
[email protected]94d78132010-01-22 00:53:001731// In this test, we enable compression, but get a uncompressed SynReply from
1732// the server. Verify that teardown is all clean.
[email protected]9e9e842e2010-07-23 23:09:151733TEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) {
[email protected]a4aeaf42010-06-30 19:57:281734 // For this test, we turn on the normal compression.
1735 EnableCompression(true);
1736
[email protected]2bd93022010-07-17 00:58:441737 scoped_ptr<spdy::SpdyFrame> compressed(
1738 ConstructSpdyGet(NULL, 0, true, 1, LOWEST));
[email protected]6c6ea172010-07-27 20:04:031739 scoped_ptr<spdy::SpdyFrame> rst(
1740 ConstructSpdyRstStream(1, spdy::PROTOCOL_ERROR));
[email protected]94d78132010-01-22 00:53:001741 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:131742 CreateMockWrite(*compressed),
[email protected]6c6ea172010-07-27 20:04:031743 CreateMockWrite(*rst),
[email protected]94d78132010-01-22 00:53:001744 };
1745
[email protected]2bd93022010-07-17 00:58:441746 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1747 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]94d78132010-01-22 00:53:001748 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:131749 CreateMockRead(*resp),
1750 CreateMockRead(*body),
[email protected]94d78132010-01-22 00:53:001751 };
1752
[email protected]94d78132010-01-22 00:53:001753 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:391754 new DelayedSocketData(1, reads, arraysize(reads),
1755 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:471756 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:151757 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:471758 helper.RunToCompletion(data.get());
1759 TransactionHelperResult out = helper.output();
[email protected]6c6ea172010-07-27 20:04:031760 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
[email protected]94d78132010-01-22 00:53:001761 data->Reset();
1762
1763 EnableCompression(false);
1764}
1765
[email protected]9e743cd2010-03-16 07:03:531766// Test that the NetLog contains good data for a simple GET request.
[email protected]9e9e842e2010-07-23 23:09:151767TEST_P(SpdyNetworkTransactionTest, NetLog) {
[email protected]2bd93022010-07-17 00:58:441768 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:131769 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]dac358042009-12-18 02:07:481770
[email protected]2bd93022010-07-17 00:58:441771 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1772 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]dac358042009-12-18 02:07:481773 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:131774 CreateMockRead(*resp),
1775 CreateMockRead(*body),
[email protected]dac358042009-12-18 02:07:481776 MockRead(true, 0, 0) // EOF
1777 };
1778
[email protected]9e743cd2010-03-16 07:03:531779 net::CapturingBoundNetLog log(net::CapturingNetLog::kUnbounded);
[email protected]dac358042009-12-18 02:07:481780
[email protected]dac358042009-12-18 02:07:481781 scoped_refptr<DelayedSocketData> data(
[email protected]31a2bfe2010-02-09 08:03:391782 new DelayedSocketData(1, reads, arraysize(reads),
1783 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:471784 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:151785 log.bound(), GetParam());
[email protected]3caf5542010-07-16 15:19:471786 helper.RunToCompletion(data.get());
1787 TransactionHelperResult out = helper.output();
[email protected]dac358042009-12-18 02:07:481788 EXPECT_EQ(OK, out.rv);
1789 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1790 EXPECT_EQ("hello!", out.response_data);
1791
[email protected]9e743cd2010-03-16 07:03:531792 // Check that the NetLog was filled reasonably.
[email protected]3caf5542010-07-16 15:19:471793 // This test is intentionally non-specific about the exact ordering of the
1794 // log; instead we just check to make sure that certain events exist, and that
1795 // they are in the right order.
[email protected]9e743cd2010-03-16 07:03:531796 EXPECT_LT(0u, log.entries().size());
[email protected]dac358042009-12-18 02:07:481797 int pos = 0;
[email protected]9e743cd2010-03-16 07:03:531798 pos = net::ExpectLogContainsSomewhere(log.entries(), 0,
[email protected]9e743cd2010-03-16 07:03:531799 net::NetLog::TYPE_SPDY_TRANSACTION_SEND_REQUEST,
1800 net::NetLog::PHASE_BEGIN);
1801 pos = net::ExpectLogContainsSomewhere(log.entries(), pos + 1,
1802 net::NetLog::TYPE_SPDY_TRANSACTION_SEND_REQUEST,
1803 net::NetLog::PHASE_END);
1804 pos = net::ExpectLogContainsSomewhere(log.entries(), pos + 1,
1805 net::NetLog::TYPE_SPDY_TRANSACTION_READ_HEADERS,
1806 net::NetLog::PHASE_BEGIN);
1807 pos = net::ExpectLogContainsSomewhere(log.entries(), pos + 1,
1808 net::NetLog::TYPE_SPDY_TRANSACTION_READ_HEADERS,
1809 net::NetLog::PHASE_END);
1810 pos = net::ExpectLogContainsSomewhere(log.entries(), pos + 1,
1811 net::NetLog::TYPE_SPDY_TRANSACTION_READ_BODY,
1812 net::NetLog::PHASE_BEGIN);
1813 pos = net::ExpectLogContainsSomewhere(log.entries(), pos + 1,
1814 net::NetLog::TYPE_SPDY_TRANSACTION_READ_BODY,
1815 net::NetLog::PHASE_END);
[email protected]dac358042009-12-18 02:07:481816}
1817
[email protected]79d84222010-02-26 00:01:441818// Since we buffer the IO from the stream to the renderer, this test verifies
1819// that when we read out the maximum amount of data (e.g. we received 50 bytes
1820// on the network, but issued a Read for only 5 of those bytes) that the data
1821// flow still works correctly.
[email protected]9e9e842e2010-07-23 23:09:151822TEST_P(SpdyNetworkTransactionTest, BufferFull) {
[email protected]20d005f2010-07-02 19:55:431823 spdy::SpdyFramer framer;
1824
[email protected]2bd93022010-07-17 00:58:441825 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:131826 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]79d84222010-02-26 00:01:441827
[email protected]20d005f2010-07-02 19:55:431828 // 2 data frames in a single read.
1829 scoped_ptr<spdy::SpdyFrame> data_frame_1(
1830 framer.CreateDataFrame(1, "goodby", 6, spdy::DATA_FLAG_NONE));
1831 scoped_ptr<spdy::SpdyFrame> data_frame_2(
1832 framer.CreateDataFrame(1, "e worl", 6, spdy::DATA_FLAG_NONE));
1833 const spdy::SpdyFrame* data_frames[2] = {
1834 data_frame_1.get(),
1835 data_frame_2.get(),
[email protected]79d84222010-02-26 00:01:441836 };
[email protected]20d005f2010-07-02 19:55:431837 char combined_data_frames[100];
1838 int combined_data_frames_len =
1839 CombineFrames(data_frames, arraysize(data_frames),
1840 combined_data_frames, arraysize(combined_data_frames));
1841 scoped_ptr<spdy::SpdyFrame> last_frame(
1842 framer.CreateDataFrame(1, "d", 1, spdy::DATA_FLAG_FIN));
[email protected]79d84222010-02-26 00:01:441843
[email protected]2bd93022010-07-17 00:58:441844 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]79d84222010-02-26 00:01:441845 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:131846 CreateMockRead(*resp),
[email protected]79d84222010-02-26 00:01:441847 MockRead(true, ERR_IO_PENDING), // Force a pause
[email protected]20d005f2010-07-02 19:55:431848 MockRead(true, combined_data_frames, combined_data_frames_len),
[email protected]79d84222010-02-26 00:01:441849 MockRead(true, ERR_IO_PENDING), // Force a pause
[email protected]20d005f2010-07-02 19:55:431850 CreateMockRead(*last_frame),
[email protected]79d84222010-02-26 00:01:441851 MockRead(true, 0, 0) // EOF
1852 };
1853
[email protected]79d84222010-02-26 00:01:441854 scoped_refptr<DelayedSocketData> data(
1855 new DelayedSocketData(1, reads, arraysize(reads),
1856 writes, arraysize(writes)));
1857
[email protected]79d84222010-02-26 00:01:441858
1859 TestCompletionCallback callback;
1860
[email protected]3caf5542010-07-16 15:19:471861 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:151862 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:471863 helper.AddData(data.get());
1864 helper.RunPreTestSetup();
1865 HttpNetworkTransaction* trans = helper.trans();
[email protected]d3cee19d2010-06-22 18:42:181866 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
[email protected]79d84222010-02-26 00:01:441867 EXPECT_EQ(ERR_IO_PENDING, rv);
1868
[email protected]3caf5542010-07-16 15:19:471869 TransactionHelperResult out = helper.output();
[email protected]79d84222010-02-26 00:01:441870 out.rv = callback.WaitForResult();
1871 EXPECT_EQ(out.rv, OK);
1872
1873 const HttpResponseInfo* response = trans->GetResponseInfo();
1874 EXPECT_TRUE(response->headers != NULL);
1875 EXPECT_TRUE(response->was_fetched_via_spdy);
1876 out.status_line = response->headers->GetStatusLine();
1877 out.response_info = *response; // Make a copy so we can verify.
1878
1879 // Read Data
1880 TestCompletionCallback read_callback;
1881
1882 std::string content;
1883 do {
1884 // Read small chunks at a time.
1885 const int kSmallReadSize = 3;
1886 scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(kSmallReadSize);
1887 rv = trans->Read(buf, kSmallReadSize, &read_callback);
1888 if (rv == net::ERR_IO_PENDING) {
1889 data->CompleteRead();
1890 rv = read_callback.WaitForResult();
1891 }
1892 if (rv > 0) {
1893 content.append(buf->data(), rv);
1894 } else if (rv < 0) {
1895 NOTREACHED();
1896 }
1897 } while (rv > 0);
1898
1899 out.response_data.swap(content);
1900
[email protected]30c942b2010-07-21 16:59:591901 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:551902 // MockClientSocketFactory) are still alive.
1903 MessageLoop::current()->RunAllPending();
1904
[email protected]79d84222010-02-26 00:01:441905 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:471906 helper.VerifyDataConsumed();
[email protected]79d84222010-02-26 00:01:441907
1908 EXPECT_EQ(OK, out.rv);
1909 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1910 EXPECT_EQ("goodbye world", out.response_data);
1911}
1912
[email protected]9e9e842e2010-07-23 23:09:151913TEST_P(SpdyNetworkTransactionTest, ConnectFailureFallbackToHttp) {
[email protected]e6b06862010-07-20 16:32:581914 MockConnect connects[] = {
1915 MockConnect(true, ERR_NAME_NOT_RESOLVED),
1916 MockConnect(false, ERR_NAME_NOT_RESOLVED),
1917 MockConnect(true, ERR_INTERNET_DISCONNECTED),
1918 MockConnect(false, ERR_INTERNET_DISCONNECTED)
1919 };
1920
1921 for (size_t index = 0; index < arraysize(connects); ++index) {
1922 scoped_ptr<spdy::SpdyFrame> req(
1923 ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1924 MockWrite writes[] = {
1925 CreateMockWrite(*req),
1926 MockWrite(true, 0, 0) // EOF
1927 };
1928
1929 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1930 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1931 MockRead reads[] = {
1932 CreateMockRead(*resp),
1933 CreateMockRead(*body),
1934 MockRead(true, 0, 0) // EOF
1935 };
1936
1937 scoped_refptr<DelayedSocketData> data(
1938 new DelayedSocketData(connects[index], 1, reads, arraysize(reads),
1939 writes, arraysize(writes)));
1940 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:151941 BoundNetLog(), GetParam());
[email protected]e6b06862010-07-20 16:32:581942 helper.AddData(data.get());
1943 helper.RunPreTestSetup();
1944
1945 // Set up http fallback data.
1946 MockRead http_fallback_data[] = {
1947 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
1948 MockRead("hello world!!!"),
1949 MockRead(true, OK),
1950 };
1951
1952 scoped_ptr<StaticSocketDataProvider> http_fallback(
1953 new StaticSocketDataProvider(http_fallback_data,
1954 arraysize(http_fallback_data),
1955 NULL, 0));
1956 helper.AddDataNoSSL(http_fallback.get());
1957 HttpNetworkTransaction* trans = helper.trans();
1958 TestCompletionCallback callback;
1959
1960 int rv = trans->Start(&helper.request(), &callback, BoundNetLog());
1961 EXPECT_EQ(rv, ERR_IO_PENDING);
1962 rv = callback.WaitForResult();
1963 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]9e9e842e2010-07-23 23:09:151964 if (GetParam() == SPDYNOSSL || GetParam() == SPDYSSL) {
1965 ASSERT_TRUE(response == NULL);
1966 return;
1967 }
1968 if (GetParam() != SPDYNPN)
1969 NOTREACHED();
[email protected]e6b06862010-07-20 16:32:581970 ASSERT_TRUE(response != NULL);
1971 ASSERT_TRUE(response->headers != NULL);
1972 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1973 std::string response_data;
1974 rv = ReadTransaction(trans, &response_data);
1975 EXPECT_EQ(OK, rv);
1976
1977 EXPECT_TRUE(!response->was_fetched_via_spdy);
1978 EXPECT_TRUE(!response->was_npn_negotiated);
1979 EXPECT_TRUE(response->was_alternate_protocol_available);
1980 EXPECT_TRUE(http_fallback->at_read_eof());
1981 EXPECT_EQ(0u, data->read_index());
1982 EXPECT_EQ(0u, data->write_index());
1983 EXPECT_EQ("hello world!!!", response_data);
1984 }
1985}
1986
[email protected]8918d282010-03-02 00:57:551987// Verify that basic buffering works; when multiple data frames arrive
1988// at the same time, ensure that we don't notify a read completion for
1989// each data frame individually.
[email protected]9e9e842e2010-07-23 23:09:151990TEST_P(SpdyNetworkTransactionTest, Buffering) {
[email protected]20d005f2010-07-02 19:55:431991 spdy::SpdyFramer framer;
1992
[email protected]2bd93022010-07-17 00:58:441993 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:131994 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]8918d282010-03-02 00:57:551995
1996 // 4 data frames in a single read.
[email protected]20d005f2010-07-02 19:55:431997 scoped_ptr<spdy::SpdyFrame> data_frame(
1998 framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE));
1999 scoped_ptr<spdy::SpdyFrame> data_frame_fin(
2000 framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_FIN));
2001 const spdy::SpdyFrame* data_frames[4] = {
2002 data_frame.get(),
2003 data_frame.get(),
2004 data_frame.get(),
2005 data_frame_fin.get()
[email protected]8918d282010-03-02 00:57:552006 };
[email protected]20d005f2010-07-02 19:55:432007 char combined_data_frames[100];
2008 int combined_data_frames_len =
2009 CombineFrames(data_frames, arraysize(data_frames),
2010 combined_data_frames, arraysize(combined_data_frames));
[email protected]8918d282010-03-02 00:57:552011
[email protected]2bd93022010-07-17 00:58:442012 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8918d282010-03-02 00:57:552013 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:132014 CreateMockRead(*resp),
[email protected]8918d282010-03-02 00:57:552015 MockRead(true, ERR_IO_PENDING), // Force a pause
[email protected]20d005f2010-07-02 19:55:432016 MockRead(true, combined_data_frames, combined_data_frames_len),
[email protected]8918d282010-03-02 00:57:552017 MockRead(true, 0, 0) // EOF
2018 };
2019
[email protected]8918d282010-03-02 00:57:552020 scoped_refptr<DelayedSocketData> data(
2021 new DelayedSocketData(1, reads, arraysize(reads),
2022 writes, arraysize(writes)));
2023
[email protected]3caf5542010-07-16 15:19:472024 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:152025 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:472026 helper.AddData(data.get());
2027 helper.RunPreTestSetup();
2028 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:552029
2030 TestCompletionCallback callback;
[email protected]d3cee19d2010-06-22 18:42:182031 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
[email protected]8918d282010-03-02 00:57:552032 EXPECT_EQ(ERR_IO_PENDING, rv);
2033
[email protected]3caf5542010-07-16 15:19:472034 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:552035 out.rv = callback.WaitForResult();
2036 EXPECT_EQ(out.rv, OK);
2037
2038 const HttpResponseInfo* response = trans->GetResponseInfo();
2039 EXPECT_TRUE(response->headers != NULL);
2040 EXPECT_TRUE(response->was_fetched_via_spdy);
2041 out.status_line = response->headers->GetStatusLine();
2042 out.response_info = *response; // Make a copy so we can verify.
2043
2044 // Read Data
2045 TestCompletionCallback read_callback;
2046
2047 std::string content;
2048 int reads_completed = 0;
2049 do {
2050 // Read small chunks at a time.
2051 const int kSmallReadSize = 14;
2052 scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(kSmallReadSize);
2053 rv = trans->Read(buf, kSmallReadSize, &read_callback);
2054 if (rv == net::ERR_IO_PENDING) {
2055 data->CompleteRead();
2056 rv = read_callback.WaitForResult();
2057 }
2058 if (rv > 0) {
2059 EXPECT_EQ(kSmallReadSize, rv);
2060 content.append(buf->data(), rv);
2061 } else if (rv < 0) {
2062 FAIL() << "Unexpected read error: " << rv;
2063 }
2064 reads_completed++;
2065 } while (rv > 0);
2066
2067 EXPECT_EQ(3, reads_completed); // Reads are: 14 bytes, 14 bytes, 0 bytes.
2068
2069 out.response_data.swap(content);
2070
[email protected]30c942b2010-07-21 16:59:592071 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:552072 // MockClientSocketFactory) are still alive.
2073 MessageLoop::current()->RunAllPending();
2074
2075 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:472076 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:552077
2078 EXPECT_EQ(OK, out.rv);
2079 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
2080 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
2081}
2082
2083// Verify the case where we buffer data but read it after it has been buffered.
[email protected]9e9e842e2010-07-23 23:09:152084TEST_P(SpdyNetworkTransactionTest, BufferedAll) {
[email protected]20d005f2010-07-02 19:55:432085 spdy::SpdyFramer framer;
2086
[email protected]2bd93022010-07-17 00:58:442087 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:132088 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]8918d282010-03-02 00:57:552089
[email protected]20d005f2010-07-02 19:55:432090 // 5 data frames in a single read.
2091 scoped_ptr<spdy::SpdyFrame> syn_reply(
[email protected]2bd93022010-07-17 00:58:442092 ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]20d005f2010-07-02 19:55:432093 syn_reply->set_flags(spdy::CONTROL_FLAG_NONE); // turn off FIN bit
2094 scoped_ptr<spdy::SpdyFrame> data_frame(
2095 framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE));
2096 scoped_ptr<spdy::SpdyFrame> data_frame_fin(
2097 framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_FIN));
2098 const spdy::SpdyFrame* frames[5] = {
2099 syn_reply.get(),
2100 data_frame.get(),
2101 data_frame.get(),
2102 data_frame.get(),
2103 data_frame_fin.get()
[email protected]8918d282010-03-02 00:57:552104 };
[email protected]20d005f2010-07-02 19:55:432105 char combined_frames[200];
2106 int combined_frames_len =
2107 CombineFrames(frames, arraysize(frames),
2108 combined_frames, arraysize(combined_frames));
[email protected]8918d282010-03-02 00:57:552109
2110 MockRead reads[] = {
[email protected]20d005f2010-07-02 19:55:432111 MockRead(true, combined_frames, combined_frames_len),
[email protected]8918d282010-03-02 00:57:552112 MockRead(true, 0, 0) // EOF
2113 };
2114
[email protected]8918d282010-03-02 00:57:552115 scoped_refptr<DelayedSocketData> data(
2116 new DelayedSocketData(1, reads, arraysize(reads),
2117 writes, arraysize(writes)));
2118
[email protected]3caf5542010-07-16 15:19:472119 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:152120 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:472121 helper.AddData(data.get());
2122 helper.RunPreTestSetup();
2123 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:552124
2125 TestCompletionCallback callback;
[email protected]d3cee19d2010-06-22 18:42:182126 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
[email protected]8918d282010-03-02 00:57:552127 EXPECT_EQ(ERR_IO_PENDING, rv);
2128
[email protected]3caf5542010-07-16 15:19:472129 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:552130 out.rv = callback.WaitForResult();
2131 EXPECT_EQ(out.rv, OK);
2132
2133 const HttpResponseInfo* response = trans->GetResponseInfo();
2134 EXPECT_TRUE(response->headers != NULL);
2135 EXPECT_TRUE(response->was_fetched_via_spdy);
2136 out.status_line = response->headers->GetStatusLine();
2137 out.response_info = *response; // Make a copy so we can verify.
2138
2139 // Read Data
2140 TestCompletionCallback read_callback;
2141
2142 std::string content;
2143 int reads_completed = 0;
2144 do {
2145 // Read small chunks at a time.
2146 const int kSmallReadSize = 14;
2147 scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(kSmallReadSize);
2148 rv = trans->Read(buf, kSmallReadSize, &read_callback);
2149 if (rv > 0) {
2150 EXPECT_EQ(kSmallReadSize, rv);
2151 content.append(buf->data(), rv);
2152 } else if (rv < 0) {
2153 FAIL() << "Unexpected read error: " << rv;
2154 }
2155 reads_completed++;
2156 } while (rv > 0);
2157
2158 EXPECT_EQ(3, reads_completed);
2159
2160 out.response_data.swap(content);
2161
[email protected]30c942b2010-07-21 16:59:592162 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:552163 // MockClientSocketFactory) are still alive.
2164 MessageLoop::current()->RunAllPending();
2165
2166 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:472167 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:552168
2169 EXPECT_EQ(OK, out.rv);
2170 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
2171 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
2172}
2173
2174// Verify the case where we buffer data and close the connection.
[email protected]9e9e842e2010-07-23 23:09:152175TEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
[email protected]20d005f2010-07-02 19:55:432176 spdy::SpdyFramer framer;
2177
[email protected]2bd93022010-07-17 00:58:442178 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:132179 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]8918d282010-03-02 00:57:552180
2181 // All data frames in a single read.
[email protected]20d005f2010-07-02 19:55:432182 // NOTE: We don't FIN the stream.
2183 scoped_ptr<spdy::SpdyFrame> data_frame(
2184 framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE));
2185 const spdy::SpdyFrame* data_frames[4] = {
2186 data_frame.get(),
2187 data_frame.get(),
2188 data_frame.get(),
2189 data_frame.get()
[email protected]8918d282010-03-02 00:57:552190 };
[email protected]20d005f2010-07-02 19:55:432191 char combined_data_frames[100];
2192 int combined_data_frames_len =
2193 CombineFrames(data_frames, arraysize(data_frames),
2194 combined_data_frames, arraysize(combined_data_frames));
[email protected]2bd93022010-07-17 00:58:442195 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]8918d282010-03-02 00:57:552196 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:132197 CreateMockRead(*resp),
[email protected]8918d282010-03-02 00:57:552198 MockRead(true, ERR_IO_PENDING), // Force a wait
[email protected]20d005f2010-07-02 19:55:432199 MockRead(true, combined_data_frames, combined_data_frames_len),
[email protected]8918d282010-03-02 00:57:552200 MockRead(true, 0, 0) // EOF
2201 };
2202
[email protected]8918d282010-03-02 00:57:552203 scoped_refptr<DelayedSocketData> data(
2204 new DelayedSocketData(1, reads, arraysize(reads),
2205 writes, arraysize(writes)));
2206
[email protected]3caf5542010-07-16 15:19:472207 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:152208 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:472209 helper.AddData(data.get());
2210 helper.RunPreTestSetup();
2211 HttpNetworkTransaction* trans = helper.trans();
[email protected]8918d282010-03-02 00:57:552212
2213 TestCompletionCallback callback;
2214
[email protected]d3cee19d2010-06-22 18:42:182215 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
[email protected]8918d282010-03-02 00:57:552216 EXPECT_EQ(ERR_IO_PENDING, rv);
2217
[email protected]3caf5542010-07-16 15:19:472218 TransactionHelperResult out = helper.output();
[email protected]8918d282010-03-02 00:57:552219 out.rv = callback.WaitForResult();
2220 EXPECT_EQ(out.rv, OK);
2221
2222 const HttpResponseInfo* response = trans->GetResponseInfo();
2223 EXPECT_TRUE(response->headers != NULL);
2224 EXPECT_TRUE(response->was_fetched_via_spdy);
2225 out.status_line = response->headers->GetStatusLine();
2226 out.response_info = *response; // Make a copy so we can verify.
2227
2228 // Read Data
2229 TestCompletionCallback read_callback;
2230
2231 std::string content;
2232 int reads_completed = 0;
2233 do {
2234 // Read small chunks at a time.
2235 const int kSmallReadSize = 14;
2236 scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(kSmallReadSize);
2237 rv = trans->Read(buf, kSmallReadSize, &read_callback);
2238 if (rv == net::ERR_IO_PENDING) {
2239 data->CompleteRead();
2240 rv = read_callback.WaitForResult();
2241 }
2242 if (rv > 0) {
2243 content.append(buf->data(), rv);
2244 } else if (rv < 0) {
2245 // This test intentionally closes the connection, and will get an error.
2246 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
2247 break;
2248 }
2249 reads_completed++;
2250 } while (rv > 0);
2251
2252 EXPECT_EQ(0, reads_completed);
2253
2254 out.response_data.swap(content);
2255
[email protected]30c942b2010-07-21 16:59:592256 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
[email protected]8918d282010-03-02 00:57:552257 // MockClientSocketFactory) are still alive.
2258 MessageLoop::current()->RunAllPending();
2259
2260 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:472261 helper.VerifyDataConsumed();
[email protected]8918d282010-03-02 00:57:552262}
2263
[email protected]1ed7b3dc2010-03-04 05:41:452264// Verify the case where we buffer data and cancel the transaction.
[email protected]9e9e842e2010-07-23 23:09:152265TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) {
[email protected]20d005f2010-07-02 19:55:432266 spdy::SpdyFramer framer;
2267
[email protected]2bd93022010-07-17 00:58:442268 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:132269 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]1ed7b3dc2010-03-04 05:41:452270
[email protected]20d005f2010-07-02 19:55:432271 // NOTE: We don't FIN the stream.
2272 scoped_ptr<spdy::SpdyFrame> data_frame(
2273 framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE));
[email protected]1ed7b3dc2010-03-04 05:41:452274
[email protected]2bd93022010-07-17 00:58:442275 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]1ed7b3dc2010-03-04 05:41:452276 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:132277 CreateMockRead(*resp),
[email protected]1ed7b3dc2010-03-04 05:41:452278 MockRead(true, ERR_IO_PENDING), // Force a wait
[email protected]20d005f2010-07-02 19:55:432279 CreateMockRead(*data_frame),
[email protected]1ed7b3dc2010-03-04 05:41:452280 MockRead(true, 0, 0) // EOF
2281 };
2282
[email protected]1ed7b3dc2010-03-04 05:41:452283 scoped_refptr<DelayedSocketData> data(
2284 new DelayedSocketData(1, reads, arraysize(reads),
2285 writes, arraysize(writes)));
2286
[email protected]3caf5542010-07-16 15:19:472287 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:152288 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:472289 helper.AddData(data.get());
2290 helper.RunPreTestSetup();
2291 HttpNetworkTransaction* trans = helper.trans();
[email protected]1ed7b3dc2010-03-04 05:41:452292 TestCompletionCallback callback;
2293
[email protected]d3cee19d2010-06-22 18:42:182294 int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog());
[email protected]1ed7b3dc2010-03-04 05:41:452295 EXPECT_EQ(ERR_IO_PENDING, rv);
2296
[email protected]3caf5542010-07-16 15:19:472297 TransactionHelperResult out = helper.output();
[email protected]1ed7b3dc2010-03-04 05:41:452298 out.rv = callback.WaitForResult();
2299 EXPECT_EQ(out.rv, OK);
2300
2301 const HttpResponseInfo* response = trans->GetResponseInfo();
2302 EXPECT_TRUE(response->headers != NULL);
2303 EXPECT_TRUE(response->was_fetched_via_spdy);
2304 out.status_line = response->headers->GetStatusLine();
2305 out.response_info = *response; // Make a copy so we can verify.
2306
2307 // Read Data
2308 TestCompletionCallback read_callback;
2309
2310 do {
2311 const int kReadSize = 256;
2312 scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(kReadSize);
2313 rv = trans->Read(buf, kReadSize, &read_callback);
2314 if (rv == net::ERR_IO_PENDING) {
2315 // Complete the read now, which causes buffering to start.
2316 data->CompleteRead();
2317 // Destroy the transaction, causing the stream to get cancelled
2318 // and orphaning the buffered IO task.
[email protected]3caf5542010-07-16 15:19:472319 helper.ResetTrans();
[email protected]1ed7b3dc2010-03-04 05:41:452320 break;
2321 }
2322 // We shouldn't get here in this test.
2323 FAIL() << "Unexpected read: " << rv;
2324 } while (rv > 0);
2325
2326 // Flush the MessageLoop; this will cause the buffered IO task
2327 // to run for the final time.
2328 MessageLoop::current()->RunAllPending();
[email protected]3caf5542010-07-16 15:19:472329
2330 // Verify that we consumed all test data.
2331 helper.VerifyDataConsumed();
[email protected]1ed7b3dc2010-03-04 05:41:452332}
2333
[email protected]74188f22010-04-09 20:18:502334// Test that if the server requests persistence of settings, that we save
2335// the settings in the SpdySettingsStorage.
[email protected]9e9e842e2010-07-23 23:09:152336TEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
[email protected]74188f22010-04-09 20:18:502337 static const SpdyHeaderInfo kSynReplyInfo = {
2338 spdy::SYN_REPLY, // Syn Reply
2339 1, // Stream ID
2340 0, // Associated Stream ID
[email protected]75f30cc22010-06-28 21:41:382341 SPDY_PRIORITY_LOWEST, // Priority
[email protected]74188f22010-04-09 20:18:502342 spdy::CONTROL_FLAG_NONE, // Control Flags
2343 false, // Compressed
[email protected]75f30cc22010-06-28 21:41:382344 spdy::INVALID, // Status
[email protected]74188f22010-04-09 20:18:502345 NULL, // Data
2346 0, // Data Length
2347 spdy::DATA_FLAG_NONE // Data Flags
2348 };
2349 static const char* const kExtraHeaders[] = {
2350 "status", "200",
2351 "version", "HTTP/1.1"
2352 };
2353
[email protected]3caf5542010-07-16 15:19:472354 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:152355 BoundNetLog(), GetParam());
[email protected]74188f22010-04-09 20:18:502356
2357 // Verify that no settings exist initially.
[email protected]9e9e842e2010-07-23 23:09:152358 HostPortPair host_port_pair("www.google.com", helper.port());
[email protected]3caf5542010-07-16 15:19:472359 EXPECT_TRUE(helper.session()->spdy_settings().Get(host_port_pair).empty());
[email protected]74188f22010-04-09 20:18:502360
2361 // Construct the request.
[email protected]2bd93022010-07-17 00:58:442362 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:132363 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]74188f22010-04-09 20:18:502364
2365 // Construct the reply.
2366 scoped_ptr<spdy::SpdyFrame> reply(
[email protected]a4aeaf42010-06-30 19:57:282367 ConstructSpdyPacket(kSynReplyInfo,
[email protected]74188f22010-04-09 20:18:502368 kExtraHeaders,
2369 arraysize(kExtraHeaders) / 2,
2370 NULL,
2371 0));
2372
2373 unsigned int kSampleId1 = 0x1;
2374 unsigned int kSampleValue1 = 0x0a0a0a0a;
2375 unsigned int kSampleId2 = 0x2;
2376 unsigned int kSampleValue2 = 0x0b0b0b0b;
2377 unsigned int kSampleId3 = 0xababab;
2378 unsigned int kSampleValue3 = 0x0c0c0c0c;
2379 scoped_ptr<spdy::SpdyFrame> settings_frame;
2380 {
2381 // Construct the SETTINGS frame.
2382 spdy::SpdySettings settings;
2383 spdy::SettingsFlagsAndId setting(0);
2384 // First add a persisted setting
2385 setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST);
2386 setting.set_id(kSampleId1);
2387 settings.push_back(std::make_pair(setting, kSampleValue1));
2388 // Next add a non-persisted setting
2389 setting.set_flags(0);
2390 setting.set_id(kSampleId2);
2391 settings.push_back(std::make_pair(setting, kSampleValue2));
2392 // Next add another persisted setting
2393 setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST);
2394 setting.set_id(kSampleId3);
2395 settings.push_back(std::make_pair(setting, kSampleValue3));
2396 settings_frame.reset(ConstructSpdySettings(settings));
2397 }
2398
[email protected]2bd93022010-07-17 00:58:442399 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]74188f22010-04-09 20:18:502400 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:132401 CreateMockRead(*reply),
2402 CreateMockRead(*body),
2403 CreateMockRead(*settings_frame),
[email protected]74188f22010-04-09 20:18:502404 MockRead(true, 0, 0) // EOF
2405 };
2406
[email protected]74188f22010-04-09 20:18:502407 scoped_refptr<DelayedSocketData> data(
2408 new DelayedSocketData(1, reads, arraysize(reads),
2409 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:472410 helper.RunToCompletion(data.get());
2411 TransactionHelperResult out = helper.output();
[email protected]74188f22010-04-09 20:18:502412 EXPECT_EQ(OK, out.rv);
2413 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
2414 EXPECT_EQ("hello!", out.response_data);
2415
2416 {
2417 // Verify we had two persisted settings.
2418 spdy::SpdySettings saved_settings =
[email protected]3caf5542010-07-16 15:19:472419 helper.session()->spdy_settings().Get(host_port_pair);
[email protected]74188f22010-04-09 20:18:502420 ASSERT_EQ(2u, saved_settings.size());
2421
2422 // Verify the first persisted setting.
2423 spdy::SpdySetting setting = saved_settings.front();
2424 saved_settings.pop_front();
2425 EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags());
2426 EXPECT_EQ(kSampleId1, setting.first.id());
2427 EXPECT_EQ(kSampleValue1, setting.second);
2428
2429 // Verify the second persisted setting.
2430 setting = saved_settings.front();
2431 saved_settings.pop_front();
2432 EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags());
2433 EXPECT_EQ(kSampleId3, setting.first.id());
2434 EXPECT_EQ(kSampleValue3, setting.second);
2435 }
2436}
2437
2438// Test that when there are settings saved that they are sent back to the
2439// server upon session establishment.
[email protected]9e9e842e2010-07-23 23:09:152440TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) {
[email protected]74188f22010-04-09 20:18:502441 static const SpdyHeaderInfo kSynReplyInfo = {
2442 spdy::SYN_REPLY, // Syn Reply
2443 1, // Stream ID
2444 0, // Associated Stream ID
[email protected]75f30cc22010-06-28 21:41:382445 SPDY_PRIORITY_LOWEST, // Priority
[email protected]74188f22010-04-09 20:18:502446 spdy::CONTROL_FLAG_NONE, // Control Flags
2447 false, // Compressed
[email protected]75f30cc22010-06-28 21:41:382448 spdy::INVALID, // Status
[email protected]74188f22010-04-09 20:18:502449 NULL, // Data
2450 0, // Data Length
2451 spdy::DATA_FLAG_NONE // Data Flags
2452 };
2453 static const char* kExtraHeaders[] = {
2454 "status", "200",
2455 "version", "HTTP/1.1"
2456 };
2457
[email protected]3caf5542010-07-16 15:19:472458 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:152459 BoundNetLog(), GetParam());
[email protected]74188f22010-04-09 20:18:502460
2461 // Verify that no settings exist initially.
[email protected]9e9e842e2010-07-23 23:09:152462 HostPortPair host_port_pair("www.google.com", helper.port());
[email protected]3caf5542010-07-16 15:19:472463 EXPECT_TRUE(helper.session()->spdy_settings().Get(host_port_pair).empty());
[email protected]74188f22010-04-09 20:18:502464
2465 unsigned int kSampleId1 = 0x1;
2466 unsigned int kSampleValue1 = 0x0a0a0a0a;
2467 unsigned int kSampleId2 = 0xababab;
2468 unsigned int kSampleValue2 = 0x0c0c0c0c;
2469 // Manually insert settings into the SpdySettingsStorage here.
2470 {
2471 spdy::SpdySettings settings;
2472 spdy::SettingsFlagsAndId setting(0);
2473 // First add a persisted setting
2474 setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST);
2475 setting.set_id(kSampleId1);
2476 settings.push_back(std::make_pair(setting, kSampleValue1));
2477 // Next add another persisted setting
2478 setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST);
2479 setting.set_id(kSampleId2);
2480 settings.push_back(std::make_pair(setting, kSampleValue2));
2481
[email protected]3caf5542010-07-16 15:19:472482 helper.session()->mutable_spdy_settings()->Set(host_port_pair, settings);
[email protected]74188f22010-04-09 20:18:502483 }
2484
[email protected]3caf5542010-07-16 15:19:472485 EXPECT_EQ(2u, helper.session()->spdy_settings().Get(host_port_pair).size());
[email protected]74188f22010-04-09 20:18:502486
2487 // Construct the SETTINGS frame.
2488 const spdy::SpdySettings& settings =
[email protected]3caf5542010-07-16 15:19:472489 helper.session()->spdy_settings().Get(host_port_pair);
[email protected]74188f22010-04-09 20:18:502490 scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
2491
2492 // Construct the request.
[email protected]2bd93022010-07-17 00:58:442493 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]74188f22010-04-09 20:18:502494
2495 MockWrite writes[] = {
[email protected]e7f75092010-07-01 22:39:132496 CreateMockWrite(*settings_frame),
2497 CreateMockWrite(*req),
[email protected]74188f22010-04-09 20:18:502498 };
2499
2500 // Construct the reply.
2501 scoped_ptr<spdy::SpdyFrame> reply(
[email protected]a4aeaf42010-06-30 19:57:282502 ConstructSpdyPacket(kSynReplyInfo,
[email protected]74188f22010-04-09 20:18:502503 kExtraHeaders,
2504 arraysize(kExtraHeaders) / 2,
2505 NULL,
2506 0));
2507
[email protected]2bd93022010-07-17 00:58:442508 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
[email protected]74188f22010-04-09 20:18:502509 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:132510 CreateMockRead(*reply),
2511 CreateMockRead(*body),
[email protected]74188f22010-04-09 20:18:502512 MockRead(true, 0, 0) // EOF
2513 };
2514
[email protected]74188f22010-04-09 20:18:502515 scoped_refptr<DelayedSocketData> data(
2516 new DelayedSocketData(2, reads, arraysize(reads),
2517 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:472518 helper.RunToCompletion(data.get());
2519 TransactionHelperResult out = helper.output();
[email protected]74188f22010-04-09 20:18:502520 EXPECT_EQ(OK, out.rv);
2521 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
2522 EXPECT_EQ("hello!", out.response_data);
2523
2524 {
2525 // Verify we had two persisted settings.
2526 spdy::SpdySettings saved_settings =
[email protected]3caf5542010-07-16 15:19:472527 helper.session()->spdy_settings().Get(host_port_pair);
[email protected]74188f22010-04-09 20:18:502528 ASSERT_EQ(2u, saved_settings.size());
2529
2530 // Verify the first persisted setting.
2531 spdy::SpdySetting setting = saved_settings.front();
2532 saved_settings.pop_front();
2533 EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags());
2534 EXPECT_EQ(kSampleId1, setting.first.id());
2535 EXPECT_EQ(kSampleValue1, setting.second);
2536
2537 // Verify the second persisted setting.
2538 setting = saved_settings.front();
2539 saved_settings.pop_front();
2540 EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags());
2541 EXPECT_EQ(kSampleId2, setting.first.id());
2542 EXPECT_EQ(kSampleValue2, setting.second);
2543 }
2544}
2545
[email protected]9e9e842e2010-07-23 23:09:152546TEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
[email protected]2bd93022010-07-17 00:58:442547 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:132548 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]69d717bd2010-04-21 18:43:212549
[email protected]a4aeaf42010-06-30 19:57:282550 scoped_ptr<spdy::SpdyFrame> go_away(ConstructSpdyGoAway());
[email protected]69d717bd2010-04-21 18:43:212551 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:132552 CreateMockRead(*go_away),
[email protected]69d717bd2010-04-21 18:43:212553 MockRead(true, 0, 0) // EOF
2554 };
2555
[email protected]69d717bd2010-04-21 18:43:212556 scoped_refptr<DelayedSocketData> data(
2557 new DelayedSocketData(1, reads, arraysize(reads),
2558 writes, arraysize(writes)));
[email protected]3caf5542010-07-16 15:19:472559 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:152560 BoundNetLog(), GetParam());
[email protected]3caf5542010-07-16 15:19:472561 helper.RunToCompletion(data.get());
2562 TransactionHelperResult out = helper.output();
[email protected]69d717bd2010-04-21 18:43:212563 EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv);
2564}
2565
[email protected]9e9e842e2010-07-23 23:09:152566TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) {
[email protected]2bd93022010-07-17 00:58:442567 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:132568 MockWrite writes[] = { CreateMockWrite(*req) };
[email protected]f5ed21552010-05-04 18:39:542569
[email protected]2bd93022010-07-17 00:58:442570 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
[email protected]f5ed21552010-05-04 18:39:542571 MockRead reads[] = {
[email protected]e7f75092010-07-01 22:39:132572 CreateMockRead(*resp),
[email protected]f5ed21552010-05-04 18:39:542573 MockRead(false, 0, 0) // EOF
2574 };
2575
[email protected]f5ed21552010-05-04 18:39:542576 scoped_refptr<DelayedSocketData> data(
2577 new DelayedSocketData(1, reads, arraysize(reads),
2578 writes, arraysize(writes)));
[email protected]f5ed21552010-05-04 18:39:542579 BoundNetLog log;
[email protected]3caf5542010-07-16 15:19:472580 NormalSpdyTransactionHelper helper(CreateGetRequest(),
[email protected]9e9e842e2010-07-23 23:09:152581 log, GetParam());
[email protected]3caf5542010-07-16 15:19:472582 helper.AddData(data.get());
2583 helper.RunPreTestSetup();
2584 HttpNetworkTransaction* trans = helper.trans();
[email protected]f5ed21552010-05-04 18:39:542585
2586 TestCompletionCallback callback;
[email protected]3caf5542010-07-16 15:19:472587 TransactionHelperResult out;
[email protected]d3cee19d2010-06-22 18:42:182588 out.rv = trans->Start(&CreateGetRequest(), &callback, log);
[email protected]3caf5542010-07-16 15:19:472589
[email protected]f5ed21552010-05-04 18:39:542590 EXPECT_EQ(out.rv, ERR_IO_PENDING);
2591 out.rv = callback.WaitForResult();
2592 EXPECT_EQ(out.rv, OK);
2593
2594 const HttpResponseInfo* response = trans->GetResponseInfo();
2595 EXPECT_TRUE(response->headers != NULL);
2596 EXPECT_TRUE(response->was_fetched_via_spdy);
[email protected]3caf5542010-07-16 15:19:472597 out.rv = ReadTransaction(trans, &out.response_data);
[email protected]f5ed21552010-05-04 18:39:542598 EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv);
2599
2600 // Verify that we consumed all test data.
[email protected]3caf5542010-07-16 15:19:472601 helper.VerifyDataConsumed();
[email protected]f5ed21552010-05-04 18:39:542602}
[email protected]aea80602009-09-18 00:55:082603} // namespace net