1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/spdy/spdy_session.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "net/base/io_buffer.h"
9 #include "net/base/ip_endpoint.h"
10 #include "net/base/net_log_unittest.h"
11 #include "net/base/request_priority.h"
12 #include "net/base/test_data_directory.h"
13 #include "net/base/test_data_stream.h"
14 #include "net/dns/host_cache.h"
15 #include "net/spdy/spdy_session_pool.h"
16 #include "net/spdy/spdy_session_test_util.h"
17 #include "net/spdy/spdy_stream.h"
18 #include "net/spdy/spdy_stream_test_util.h"
19 #include "net/spdy/spdy_test_util_common.h"
20 #include "net/spdy/spdy_test_util_spdy2.h"
21 #include "net/test/cert_test_util.h"
22 #include "testing/platform_test.h"
24 using namespace net::test_spdy2
;
30 static const char kTestUrl
[] = "http://www.example.org/";
31 static const char kTestHost
[] = "www.example.org";
32 static const int kTestPort
= 80;
34 static int g_delta_seconds
= 0;
35 base::TimeTicks
TheNearFuture() {
36 return base::TimeTicks::Now() + base::TimeDelta::FromSeconds(g_delta_seconds
);
41 class SpdySessionSpdy2Test
: public PlatformTest
{
43 SpdySessionSpdy2Test()
44 : spdy_session_pool_(NULL
),
46 test_host_port_pair_(kTestHost
, kTestPort
),
47 pair_(test_host_port_pair_
, ProxyServer::Direct()) {
50 virtual void SetUp() {
54 void CreateDeterministicNetworkSession() {
56 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
);
57 spdy_session_pool_
= http_session_
->spdy_session_pool();
60 void CreateNetworkSession() {
62 SpdySessionDependencies::SpdyCreateSession(&session_deps_
);
63 spdy_session_pool_
= http_session_
->spdy_session_pool();
66 scoped_refptr
<SpdySession
> GetSession(const HostPortProxyPair
& pair
) {
67 EXPECT_FALSE(spdy_session_pool_
->HasSession(pair
));
68 scoped_refptr
<SpdySession
> session
=
69 spdy_session_pool_
->Get(pair
, BoundNetLog());
70 EXPECT_TRUE(spdy_session_pool_
->HasSession(pair
));
74 // Creates an initialized session to |pair_|.
75 scoped_refptr
<SpdySession
> CreateInitializedSession() {
76 scoped_refptr
<SpdySession
> session
= GetSession(pair_
);
80 http_session_
.get(), session
.get(), test_host_port_pair_
));
84 net::Error
InitializeSession(HttpNetworkSession
* http_session
,
86 const HostPortPair
& host_port_pair
) {
87 transport_params_
= new TransportSocketParams(
88 host_port_pair
, MEDIUM
, false, false, OnHostResolutionCallback());
90 scoped_ptr
<ClientSocketHandle
> connection(new ClientSocketHandle
);
91 EXPECT_EQ(OK
, connection
->Init(host_port_pair
.ToString(),
92 transport_params_
, MEDIUM
,
94 http_session
->GetTransportSocketPool(
95 HttpNetworkSession::NORMAL_SOCKET_POOL
),
97 return session
->InitializeWithSocket(connection
.release(), false, OK
);
100 scoped_refptr
<TransportSocketParams
> transport_params_
;
101 SpdySessionDependencies session_deps_
;
102 scoped_refptr
<HttpNetworkSession
> http_session_
;
103 SpdySessionPool
* spdy_session_pool_
;
105 HostPortPair test_host_port_pair_
;
106 HostPortProxyPair pair_
;
109 TEST_F(SpdySessionSpdy2Test
, GoAway
) {
110 session_deps_
.host_resolver
->set_synchronous_mode(true);
112 MockConnect
connect_data(SYNCHRONOUS
, OK
);
113 scoped_ptr
<SpdyFrame
> goaway(ConstructSpdyGoAway(1));
115 CreateMockRead(*goaway
, 2),
116 MockRead(ASYNC
, 0, 3) // EOF
118 scoped_ptr
<SpdyFrame
> req1(ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
));
119 scoped_ptr
<SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, MEDIUM
));
120 MockWrite writes
[] = {
121 CreateMockWrite(*req1
, 0),
122 CreateMockWrite(*req2
, 1),
124 DeterministicSocketData
data(reads
, arraysize(reads
),
125 writes
, arraysize(writes
));
126 data
.set_connect_data(connect_data
);
127 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
129 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
130 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
132 CreateDeterministicNetworkSession();
134 scoped_refptr
<SpdySession
> session
= CreateInitializedSession();
136 EXPECT_EQ(2, session
->GetProtocolVersion());
138 GURL
url("http://www.google.com");
139 scoped_refptr
<SpdyStream
> spdy_stream1
=
140 CreateStreamSynchronously(session
, url
, MEDIUM
, BoundNetLog());
142 scoped_refptr
<SpdyStream
> spdy_stream2
=
143 CreateStreamSynchronously(session
, url
, MEDIUM
, BoundNetLog());
145 scoped_ptr
<SpdyHeaderBlock
> headers(new SpdyHeaderBlock
);
146 (*headers
)["method"] = "GET";
147 (*headers
)["scheme"] = url
.scheme();
148 (*headers
)["host"] = url
.host();
149 (*headers
)["url"] = url
.path();
150 (*headers
)["version"] = "HTTP/1.1";
151 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock
);
152 *headers2
= *headers
;
154 spdy_stream1
->set_spdy_headers(headers
.Pass());
155 EXPECT_TRUE(spdy_stream1
->HasUrl());
157 spdy_stream2
->set_spdy_headers(headers2
.Pass());
158 EXPECT_TRUE(spdy_stream2
->HasUrl());
160 spdy_stream1
->SendRequest(false);
161 spdy_stream2
->SendRequest(false);
164 EXPECT_EQ(1u, spdy_stream1
->stream_id());
165 EXPECT_EQ(3u, spdy_stream2
->stream_id());
167 EXPECT_TRUE(spdy_session_pool_
->HasSession(pair_
));
169 // Read and process the GOAWAY frame.
172 EXPECT_FALSE(spdy_session_pool_
->HasSession(pair_
));
174 EXPECT_TRUE(session
->IsStreamActive(1));
175 EXPECT_FALSE(session
->IsStreamActive(3));
177 scoped_refptr
<SpdySession
> session2
= GetSession(pair_
);
179 spdy_stream1
->Close();
183 // Delete the first session.
186 // Delete the second session.
187 spdy_session_pool_
->Remove(session2
);
191 TEST_F(SpdySessionSpdy2Test
, ClientPing
) {
192 session_deps_
.enable_ping
= true;
193 session_deps_
.host_resolver
->set_synchronous_mode(true);
195 MockConnect
connect_data(SYNCHRONOUS
, OK
);
196 scoped_ptr
<SpdyFrame
> read_ping(ConstructSpdyPing(1));
198 CreateMockRead(*read_ping
),
199 MockRead(SYNCHRONOUS
, 0, 0) // EOF
201 scoped_ptr
<SpdyFrame
> write_ping(ConstructSpdyPing(1));
202 MockWrite writes
[] = {
203 CreateMockWrite(*write_ping
),
205 StaticSocketDataProvider
data(
206 reads
, arraysize(reads
), writes
, arraysize(writes
));
207 data
.set_connect_data(connect_data
);
208 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
210 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
211 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
213 CreateNetworkSession();
215 scoped_refptr
<SpdySession
> session
= CreateInitializedSession();
217 scoped_refptr
<SpdyStream
> spdy_stream1
=
218 CreateStreamSynchronously(session
, test_url_
, MEDIUM
, BoundNetLog());
219 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
220 test::StreamDelegateSendImmediate
delegate(
221 spdy_stream1
, scoped_ptr
<SpdyHeaderBlock
>(), NULL
);
222 spdy_stream1
->SetDelegate(&delegate
);
224 base::TimeTicks before_ping_time
= base::TimeTicks::Now();
226 session
->set_connection_at_risk_of_loss_time(
227 base::TimeDelta::FromSeconds(-1));
228 session
->set_hung_interval(base::TimeDelta::FromMilliseconds(50));
230 session
->SendPrefacePingIfNoneInFlight();
232 EXPECT_EQ(ERR_CONNECTION_CLOSED
, delegate
.WaitForClose());
234 session
->CheckPingStatus(before_ping_time
);
236 EXPECT_EQ(0, session
->pings_in_flight());
237 EXPECT_GE(session
->next_ping_id(), static_cast<uint32
>(1));
238 EXPECT_FALSE(session
->check_ping_status_pending());
239 EXPECT_GE(session
->last_activity_time(), before_ping_time
);
241 EXPECT_FALSE(spdy_session_pool_
->HasSession(pair_
));
243 // Delete the first session.
247 TEST_F(SpdySessionSpdy2Test
, ServerPing
) {
248 session_deps_
.host_resolver
->set_synchronous_mode(true);
250 MockConnect
connect_data(SYNCHRONOUS
, OK
);
251 scoped_ptr
<SpdyFrame
> read_ping(ConstructSpdyPing(2));
253 CreateMockRead(*read_ping
),
254 MockRead(SYNCHRONOUS
, 0, 0) // EOF
256 scoped_ptr
<SpdyFrame
> write_ping(ConstructSpdyPing(2));
257 MockWrite writes
[] = {
258 CreateMockWrite(*write_ping
),
260 StaticSocketDataProvider
data(
261 reads
, arraysize(reads
), writes
, arraysize(writes
));
262 data
.set_connect_data(connect_data
);
263 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
265 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
266 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
268 CreateNetworkSession();
270 scoped_refptr
<SpdySession
> session
= CreateInitializedSession();
272 scoped_refptr
<SpdyStream
> spdy_stream1
=
273 CreateStreamSynchronously(session
, test_url_
, MEDIUM
, BoundNetLog());
274 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
275 test::StreamDelegateSendImmediate
delegate(
276 spdy_stream1
, scoped_ptr
<SpdyHeaderBlock
>(), NULL
);
277 spdy_stream1
->SetDelegate(&delegate
);
279 // Flush the SpdySession::OnReadComplete() task.
280 MessageLoop::current()->RunUntilIdle();
282 EXPECT_FALSE(spdy_session_pool_
->HasSession(pair_
));
284 // Delete the session.
288 TEST_F(SpdySessionSpdy2Test
, DeleteExpiredPushStreams
) {
289 session_deps_
.host_resolver
->set_synchronous_mode(true);
291 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
292 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
293 session_deps_
.time_func
= TheNearFuture
;
295 CreateNetworkSession();
297 scoped_refptr
<SpdySession
> session
= GetSession(pair_
);
299 // Give the session a SPDY2 framer.
300 session
->buffered_spdy_framer_
.reset(new BufferedSpdyFramer(2, false));
302 // Create the associated stream and add to active streams.
303 scoped_ptr
<SpdyHeaderBlock
> request_headers(new SpdyHeaderBlock
);
304 (*request_headers
)["scheme"] = "http";
305 (*request_headers
)["host"] = "www.google.com";
306 (*request_headers
)["url"] = "/";
308 scoped_refptr
<SpdyStream
> stream(
309 new SpdyStream(session
, std::string(), DEFAULT_PRIORITY
,
310 kSpdyStreamInitialWindowSize
,
311 kSpdyStreamInitialWindowSize
,
312 false, session
->net_log_
));
313 stream
->set_spdy_headers(request_headers
.Pass());
314 session
->ActivateStream(stream
);
316 SpdyHeaderBlock headers
;
317 headers
["url"] = "http://www.google.com/a.dat";
318 session
->OnSynStream(2, 1, 0, 0, true, false, headers
);
320 // Verify that there is one unclaimed push stream.
321 EXPECT_EQ(1u, session
->num_unclaimed_pushed_streams());
322 SpdySession::PushedStreamMap::iterator iter
=
323 session
->unclaimed_pushed_streams_
.find("http://www.google.com/a.dat");
324 EXPECT_TRUE(session
->unclaimed_pushed_streams_
.end() != iter
);
327 g_delta_seconds
= 301;
329 headers
["url"] = "http://www.google.com/b.dat";
330 session
->OnSynStream(4, 1, 0, 0, true, false, headers
);
332 // Verify that the second pushed stream evicted the first pushed stream.
333 EXPECT_EQ(1u, session
->num_unclaimed_pushed_streams());
334 iter
= session
->unclaimed_pushed_streams_
.find("http://www.google.com/b.dat");
335 EXPECT_TRUE(session
->unclaimed_pushed_streams_
.end() != iter
);
337 // Delete the session.
341 TEST_F(SpdySessionSpdy2Test
, FailedPing
) {
342 session_deps_
.host_resolver
->set_synchronous_mode(true);
344 MockConnect
connect_data(SYNCHRONOUS
, OK
);
345 scoped_ptr
<SpdyFrame
> read_ping(ConstructSpdyPing(1));
347 CreateMockRead(*read_ping
),
348 MockRead(SYNCHRONOUS
, 0, 0) // EOF
350 scoped_ptr
<SpdyFrame
> write_ping(ConstructSpdyPing(1));
351 MockWrite writes
[] = {
352 CreateMockWrite(*write_ping
),
354 StaticSocketDataProvider
data(
355 reads
, arraysize(reads
), writes
, arraysize(writes
));
356 data
.set_connect_data(connect_data
);
357 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
359 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
360 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
362 CreateNetworkSession();
364 scoped_refptr
<SpdySession
> session
= CreateInitializedSession();
366 scoped_refptr
<SpdyStream
> spdy_stream1
=
367 CreateStreamSynchronously(session
, test_url_
, MEDIUM
, BoundNetLog());
368 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
369 test::StreamDelegateSendImmediate
delegate(
370 spdy_stream1
, scoped_ptr
<SpdyHeaderBlock
>(), NULL
);
371 spdy_stream1
->SetDelegate(&delegate
);
373 session
->set_connection_at_risk_of_loss_time(base::TimeDelta::FromSeconds(0));
374 session
->set_hung_interval(base::TimeDelta::FromSeconds(0));
376 // Send a PING frame.
377 session
->WritePingFrame(1);
378 EXPECT_LT(0, session
->pings_in_flight());
379 EXPECT_GE(session
->next_ping_id(), static_cast<uint32
>(1));
380 EXPECT_TRUE(session
->check_ping_status_pending());
382 // Assert session is not closed.
383 EXPECT_FALSE(session
->IsClosed());
384 EXPECT_LT(0u, session
->num_active_streams() + session
->num_created_streams());
385 EXPECT_TRUE(spdy_session_pool_
->HasSession(pair_
));
387 // We set last time we have received any data in 1 sec less than now.
388 // CheckPingStatus will trigger timeout because hung interval is zero.
389 base::TimeTicks now
= base::TimeTicks::Now();
390 session
->last_activity_time_
= now
- base::TimeDelta::FromSeconds(1);
391 session
->CheckPingStatus(now
);
393 EXPECT_TRUE(session
->IsClosed());
394 EXPECT_EQ(0u, session
->num_active_streams());
395 EXPECT_EQ(0u, session
->num_unclaimed_pushed_streams());
396 EXPECT_FALSE(spdy_session_pool_
->HasSession(pair_
));
398 // Delete the first session.
402 TEST_F(SpdySessionSpdy2Test
, CloseIdleSessions
) {
403 CreateNetworkSession();
406 const std::string
kTestHost1("http://www.a.com");
407 HostPortPair
test_host_port_pair1(kTestHost1
, 80);
408 HostPortProxyPair
pair1(test_host_port_pair1
, ProxyServer::Direct());
409 scoped_refptr
<SpdySession
> session1
= GetSession(pair1
);
410 GURL
url1(kTestHost1
);
411 scoped_refptr
<SpdyStream
> spdy_stream1
=
412 CreateStreamSynchronously(session1
, url1
, MEDIUM
, BoundNetLog());
413 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
416 const std::string
kTestHost2("http://www.b.com");
417 HostPortPair
test_host_port_pair2(kTestHost2
, 80);
418 HostPortProxyPair
pair2(test_host_port_pair2
, ProxyServer::Direct());
419 scoped_refptr
<SpdySession
> session2
= GetSession(pair2
);
420 GURL
url2(kTestHost2
);
421 scoped_refptr
<SpdyStream
> spdy_stream2
=
422 CreateStreamSynchronously(session2
, url2
, MEDIUM
, BoundNetLog());
423 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
426 const std::string
kTestHost3("http://www.c.com");
427 HostPortPair
test_host_port_pair3(kTestHost3
, 80);
428 HostPortProxyPair
pair3(test_host_port_pair3
, ProxyServer::Direct());
429 scoped_refptr
<SpdySession
> session3
= GetSession(pair3
);
430 GURL
url3(kTestHost3
);
431 scoped_refptr
<SpdyStream
> spdy_stream3
=
432 CreateStreamSynchronously(session3
, url3
, MEDIUM
, BoundNetLog());
433 ASSERT_TRUE(spdy_stream3
.get() != NULL
);
435 // All sessions are active and not closed
436 EXPECT_TRUE(session1
->is_active());
437 EXPECT_FALSE(session1
->IsClosed());
438 EXPECT_TRUE(session2
->is_active());
439 EXPECT_FALSE(session2
->IsClosed());
440 EXPECT_TRUE(session3
->is_active());
441 EXPECT_FALSE(session3
->IsClosed());
443 // Should not do anything, all are active
444 spdy_session_pool_
->CloseIdleSessions();
445 EXPECT_TRUE(session1
->is_active());
446 EXPECT_FALSE(session1
->IsClosed());
447 EXPECT_TRUE(session2
->is_active());
448 EXPECT_FALSE(session2
->IsClosed());
449 EXPECT_TRUE(session3
->is_active());
450 EXPECT_FALSE(session3
->IsClosed());
452 // Make sessions 1 and 3 inactive, but keep them open.
453 // Session 2 still open and active
454 session1
->CloseCreatedStream(spdy_stream1
, OK
);
455 session3
->CloseCreatedStream(spdy_stream3
, OK
);
456 EXPECT_FALSE(session1
->is_active());
457 EXPECT_FALSE(session1
->IsClosed());
458 EXPECT_TRUE(session2
->is_active());
459 EXPECT_FALSE(session2
->IsClosed());
460 EXPECT_FALSE(session3
->is_active());
461 EXPECT_FALSE(session3
->IsClosed());
463 // Should close session 1 and 3, 2 should be left open
464 spdy_session_pool_
->CloseIdleSessions();
465 EXPECT_FALSE(session1
->is_active());
466 EXPECT_TRUE(session1
->IsClosed());
467 EXPECT_TRUE(session2
->is_active());
468 EXPECT_FALSE(session2
->IsClosed());
469 EXPECT_FALSE(session3
->is_active());
470 EXPECT_TRUE(session3
->IsClosed());
472 // Should not do anything
473 spdy_session_pool_
->CloseIdleSessions();
474 EXPECT_TRUE(session2
->is_active());
475 EXPECT_FALSE(session2
->IsClosed());
478 session2
->CloseCreatedStream(spdy_stream2
, OK
);
479 EXPECT_FALSE(session2
->is_active());
480 EXPECT_FALSE(session2
->IsClosed());
482 // This should close session 2
483 spdy_session_pool_
->CloseIdleSessions();
484 EXPECT_FALSE(session2
->is_active());
485 EXPECT_TRUE(session2
->IsClosed());
488 // Start with max concurrent streams set to 1. Request two streams. Receive a
489 // settings frame setting max concurrent streams to 2. Have the callback
490 // release the stream, which releases its reference (the last) to the session.
491 // Make sure nothing blows up.
492 // http://crbug.com/57331
493 TEST_F(SpdySessionSpdy2Test
, OnSettings
) {
494 session_deps_
.host_resolver
->set_synchronous_mode(true);
496 SettingsMap new_settings
;
497 const SpdySettingsIds kSpdySettingsIds1
= SETTINGS_MAX_CONCURRENT_STREAMS
;
498 const uint32 max_concurrent_streams
= 2;
499 new_settings
[kSpdySettingsIds1
] =
500 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
502 // Set up the socket so we read a SETTINGS frame that raises max concurrent
504 MockConnect
connect_data(SYNCHRONOUS
, OK
);
505 scoped_ptr
<SpdyFrame
> settings_frame(ConstructSpdySettings(new_settings
));
507 CreateMockRead(*settings_frame
),
508 MockRead(SYNCHRONOUS
, 0, 0) // EOF
511 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
512 data
.set_connect_data(connect_data
);
513 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
515 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
516 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
518 CreateNetworkSession();
520 // Initialize the SpdySetting with 1 max concurrent streams.
521 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
522 test_host_port_pair_
,
524 SETTINGS_FLAG_PLEASE_PERSIST
,
527 scoped_refptr
<SpdySession
> session
= CreateInitializedSession();
529 // Create 2 streams. First will succeed. Second will be pending.
530 scoped_refptr
<SpdyStream
> spdy_stream1
=
531 CreateStreamSynchronously(session
, test_url_
, MEDIUM
, BoundNetLog());
532 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
534 StreamReleaserCallback
stream_releaser(session
, spdy_stream1
);
536 SpdyStreamRequest request
;
537 ASSERT_EQ(ERR_IO_PENDING
,
538 request
.StartRequest(session
, test_url_
, MEDIUM
,
540 stream_releaser
.MakeCallback(&request
)));
542 // Make sure |stream_releaser| holds the last refs.
546 EXPECT_EQ(OK
, stream_releaser
.WaitForResult());
549 // Start with max concurrent streams set to 1. Request two streams. When the
550 // first completes, have the callback close itself, which should trigger the
551 // second stream creation. Then cancel that one immediately. Don't crash.
552 // http://crbug.com/63532
553 TEST_F(SpdySessionSpdy2Test
, CancelPendingCreateStream
) {
554 session_deps_
.host_resolver
->set_synchronous_mode(true);
557 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
560 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
561 MockConnect
connect_data(SYNCHRONOUS
, OK
);
563 data
.set_connect_data(connect_data
);
564 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
566 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
567 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
569 CreateNetworkSession();
571 // Initialize the SpdySetting with 1 max concurrent streams.
572 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
573 test_host_port_pair_
,
574 SETTINGS_MAX_CONCURRENT_STREAMS
,
575 SETTINGS_FLAG_PLEASE_PERSIST
,
578 scoped_refptr
<SpdySession
> session
= CreateInitializedSession();
580 // Create 2 streams. First will succeed. Second will be pending.
581 scoped_refptr
<SpdyStream
> spdy_stream1
=
582 CreateStreamSynchronously(session
, test_url_
, MEDIUM
, BoundNetLog());
583 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
585 // Use scoped_ptr to let us invalidate the memory when we want to, to trigger
586 // a valgrind error if the callback is invoked when it's not supposed to be.
587 scoped_ptr
<TestCompletionCallback
> callback(new TestCompletionCallback
);
589 SpdyStreamRequest request
;
590 ASSERT_EQ(ERR_IO_PENDING
,
591 request
.StartRequest(session
, test_url_
, MEDIUM
,
593 callback
->callback()));
595 // Release the first one, this will allow the second to be created.
596 spdy_stream1
->Cancel();
599 request
.CancelRequest();
602 // Should not crash when running the pending callback.
603 MessageLoop::current()->RunUntilIdle();
606 TEST_F(SpdySessionSpdy2Test
, SendInitialSettingsOnNewSession
) {
607 session_deps_
.host_resolver
->set_synchronous_mode(true);
610 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
613 SettingsMap settings
;
614 const SpdySettingsIds kSpdySettingsIds1
= SETTINGS_MAX_CONCURRENT_STREAMS
;
615 settings
[kSpdySettingsIds1
] =
616 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, kMaxConcurrentPushedStreams
);
617 MockConnect
connect_data(SYNCHRONOUS
, OK
);
618 scoped_ptr
<SpdyFrame
> settings_frame(ConstructSpdySettings(settings
));
619 MockWrite writes
[] = {
620 CreateMockWrite(*settings_frame
),
623 StaticSocketDataProvider
data(
624 reads
, arraysize(reads
), writes
, arraysize(writes
));
625 data
.set_connect_data(connect_data
);
626 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
628 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
629 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
631 CreateNetworkSession();
633 SpdySessionPoolPeer
pool_peer(spdy_session_pool_
);
634 pool_peer
.EnableSendingInitialSettings(true);
636 scoped_refptr
<SpdySession
> session
= CreateInitializedSession();
638 MessageLoop::current()->RunUntilIdle();
639 EXPECT_TRUE(data
.at_write_eof());
642 TEST_F(SpdySessionSpdy2Test
, SendSettingsOnNewSession
) {
643 session_deps_
.host_resolver
->set_synchronous_mode(true);
646 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
649 // Create the bogus setting that we want to verify is sent out.
650 // Note that it will be marked as SETTINGS_FLAG_PERSISTED when sent out. But
651 // to persist it into the HttpServerProperties, we need to mark as
652 // SETTINGS_FLAG_PLEASE_PERSIST.
653 SettingsMap settings
;
654 const SpdySettingsIds kSpdySettingsIds1
= SETTINGS_UPLOAD_BANDWIDTH
;
655 const uint32 kBogusSettingValue
= 0xCDCD;
656 settings
[kSpdySettingsIds1
] =
657 SettingsFlagsAndValue(SETTINGS_FLAG_PERSISTED
, kBogusSettingValue
);
658 MockConnect
connect_data(SYNCHRONOUS
, OK
);
659 scoped_ptr
<SpdyFrame
> settings_frame(ConstructSpdySettings(settings
));
660 MockWrite writes
[] = {
661 CreateMockWrite(*settings_frame
),
664 StaticSocketDataProvider
data(
665 reads
, arraysize(reads
), writes
, arraysize(writes
));
666 data
.set_connect_data(connect_data
);
667 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
669 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
670 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
672 CreateNetworkSession();
674 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
675 test_host_port_pair_
,
677 SETTINGS_FLAG_PLEASE_PERSIST
,
680 scoped_refptr
<SpdySession
> session
= CreateInitializedSession();
682 MessageLoop::current()->RunUntilIdle();
683 EXPECT_TRUE(data
.at_write_eof());
688 // Specifies the style for closing the connection.
689 enum SpdyPoolCloseSessionsType
{
690 SPDY_POOL_CLOSE_SESSIONS_MANUALLY
,
691 SPDY_POOL_CLOSE_CURRENT_SESSIONS
,
692 SPDY_POOL_CLOSE_IDLE_SESSIONS
,
695 // This test has three variants, one for each style of closing the connection.
696 // If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_SESSIONS_MANUALLY,
697 // the sessions are closed manually, calling SpdySessionPool::Remove() directly.
698 // If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_CURRENT_SESSIONS,
699 // sessions are closed with SpdySessionPool::CloseCurrentSessions().
700 // If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_IDLE_SESSIONS,
701 // sessions are closed with SpdySessionPool::CloseIdleSessions().
702 void IPPoolingTest(SpdyPoolCloseSessionsType close_sessions_type
) {
703 const int kTestPort
= 80;
708 HostPortProxyPair pair
;
709 AddressList addresses
;
711 { "http:://www.foo.com",
713 "192.0.2.33,192.168.0.1,192.168.0.5"
715 { "http://js.foo.com",
717 "192.168.0.2,192.168.0.3,192.168.0.5,192.0.2.33"
719 { "http://images.foo.com",
721 "192.168.0.4,192.168.0.3"
725 SpdySessionDependencies session_deps
;
726 session_deps
.host_resolver
->set_synchronous_mode(true);
727 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_hosts
); i
++) {
728 session_deps
.host_resolver
->rules()->AddIPLiteralRule(
729 test_hosts
[i
].name
, test_hosts
[i
].iplist
, std::string());
731 // This test requires that the HostResolver cache be populated. Normal
732 // code would have done this already, but we do it manually.
733 HostResolver::RequestInfo
info(HostPortPair(test_hosts
[i
].name
, kTestPort
));
734 session_deps
.host_resolver
->Resolve(
735 info
, &test_hosts
[i
].addresses
, CompletionCallback(), NULL
,
738 // Setup a HostPortProxyPair
739 test_hosts
[i
].pair
= HostPortProxyPair(
740 HostPortPair(test_hosts
[i
].name
, kTestPort
), ProxyServer::Direct());
743 MockConnect
connect_data(SYNCHRONOUS
, OK
);
745 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
748 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
749 data
.set_connect_data(connect_data
);
750 session_deps
.socket_factory
->AddSocketDataProvider(&data
);
752 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
753 session_deps
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
755 scoped_refptr
<HttpNetworkSession
> http_session(
756 SpdySessionDependencies::SpdyCreateSession(&session_deps
));
758 // Setup the first session to the first host.
759 SpdySessionPool
* spdy_session_pool(http_session
->spdy_session_pool());
760 EXPECT_FALSE(spdy_session_pool
->HasSession(test_hosts
[0].pair
));
761 scoped_refptr
<SpdySession
> session
=
762 spdy_session_pool
->Get(test_hosts
[0].pair
, BoundNetLog());
763 EXPECT_TRUE(spdy_session_pool
->HasSession(test_hosts
[0].pair
));
765 HostPortPair
test_host_port_pair(test_hosts
[0].name
, kTestPort
);
767 scoped_refptr
<TransportSocketParams
> transport_params(
768 new TransportSocketParams(test_host_port_pair
,
772 OnHostResolutionCallback()));
773 scoped_ptr
<ClientSocketHandle
> connection(new ClientSocketHandle
);
774 EXPECT_EQ(OK
, connection
->Init(test_host_port_pair
.ToString(),
775 transport_params
, MEDIUM
, CompletionCallback(),
776 http_session
->GetTransportSocketPool(
777 HttpNetworkSession::NORMAL_SOCKET_POOL
),
779 EXPECT_EQ(OK
, session
->InitializeWithSocket(connection
.release(), false, OK
));
781 // TODO(rtenneti): MockClientSocket::GetPeerAddress return's 0 as the port
782 // number. Fix it to return port 80 and then use GetPeerAddress to AddAlias.
783 SpdySessionPoolPeer
pool_peer(spdy_session_pool
);
784 pool_peer
.AddAlias(test_hosts
[0].addresses
.front(), test_hosts
[0].pair
);
786 // Flush the SpdySession::OnReadComplete() task.
787 MessageLoop::current()->RunUntilIdle();
789 // The third host has no overlap with the first, so it can't pool IPs.
790 EXPECT_FALSE(spdy_session_pool
->HasSession(test_hosts
[2].pair
));
792 // The second host overlaps with the first, and should IP pool.
793 EXPECT_TRUE(spdy_session_pool
->HasSession(test_hosts
[1].pair
));
795 // Verify that the second host, through a proxy, won't share the IP.
796 HostPortProxyPair
proxy_pair(test_hosts
[1].pair
.first
,
797 ProxyServer::FromPacString("HTTP http://proxy.foo.com/"));
798 EXPECT_FALSE(spdy_session_pool
->HasSession(proxy_pair
));
800 // Overlap between 2 and 3 does is not transitive to 1.
801 EXPECT_FALSE(spdy_session_pool
->HasSession(test_hosts
[2].pair
));
803 // Create a new session to host 2.
804 scoped_refptr
<SpdySession
> session2
=
805 spdy_session_pool
->Get(test_hosts
[2].pair
, BoundNetLog());
807 // Verify that we have sessions for everything.
808 EXPECT_TRUE(spdy_session_pool
->HasSession(test_hosts
[0].pair
));
809 EXPECT_TRUE(spdy_session_pool
->HasSession(test_hosts
[1].pair
));
810 EXPECT_TRUE(spdy_session_pool
->HasSession(test_hosts
[2].pair
));
812 // Grab the session to host 1 and verify that it is the same session
813 // we got with host 0, and that is a different than host 2's session.
814 scoped_refptr
<SpdySession
> session1
=
815 spdy_session_pool
->Get(test_hosts
[1].pair
, BoundNetLog());
816 EXPECT_EQ(session
.get(), session1
.get());
817 EXPECT_NE(session2
.get(), session1
.get());
819 // Remove the aliases and observe that we still have a session for host1.
820 pool_peer
.RemoveAliases(test_hosts
[0].pair
);
821 pool_peer
.RemoveAliases(test_hosts
[1].pair
);
822 EXPECT_TRUE(spdy_session_pool
->HasSession(test_hosts
[1].pair
));
824 // Expire the host cache
825 session_deps
.host_resolver
->GetHostCache()->clear();
826 EXPECT_TRUE(spdy_session_pool
->HasSession(test_hosts
[1].pair
));
828 // Cleanup the sessions.
829 switch (close_sessions_type
) {
830 case SPDY_POOL_CLOSE_SESSIONS_MANUALLY
:
831 spdy_session_pool
->Remove(session
);
833 spdy_session_pool
->Remove(session2
);
836 case SPDY_POOL_CLOSE_CURRENT_SESSIONS
:
837 spdy_session_pool
->CloseCurrentSessions(net::ERR_ABORTED
);
839 case SPDY_POOL_CLOSE_IDLE_SESSIONS
:
840 GURL
url(test_hosts
[0].url
);
841 scoped_refptr
<SpdyStream
> spdy_stream
=
842 CreateStreamSynchronously(session
, url
, MEDIUM
, BoundNetLog());
843 GURL
url1(test_hosts
[1].url
);
844 scoped_refptr
<SpdyStream
> spdy_stream1
=
845 CreateStreamSynchronously(session1
, url1
, MEDIUM
, BoundNetLog());
846 GURL
url2(test_hosts
[2].url
);
847 scoped_refptr
<SpdyStream
> spdy_stream2
=
848 CreateStreamSynchronously(session2
, url2
, MEDIUM
, BoundNetLog());
850 // Close streams to make spdy_session and spdy_session1 inactive.
851 session
->CloseCreatedStream(spdy_stream
, OK
);
852 session1
->CloseCreatedStream(spdy_stream1
, OK
);
854 // Check spdy_session and spdy_session1 are not closed.
855 EXPECT_FALSE(session
->is_active());
856 EXPECT_FALSE(session
->IsClosed());
857 EXPECT_FALSE(session1
->is_active());
858 EXPECT_FALSE(session1
->IsClosed());
859 EXPECT_TRUE(session2
->is_active());
860 EXPECT_FALSE(session2
->IsClosed());
862 // Test that calling CloseIdleSessions, does not cause a crash.
863 // http://crbug.com/181400
864 spdy_session_pool
->CloseIdleSessions();
866 // Verify spdy_session and spdy_session1 are closed.
867 EXPECT_FALSE(session
->is_active());
868 EXPECT_TRUE(session
->IsClosed());
869 EXPECT_FALSE(session1
->is_active());
870 EXPECT_TRUE(session1
->IsClosed());
871 EXPECT_TRUE(session2
->is_active());
872 EXPECT_FALSE(session2
->IsClosed());
876 spdy_stream2
->Cancel();
878 spdy_session_pool
->Remove(session2
);
883 // Verify that the map is all cleaned up.
884 EXPECT_FALSE(spdy_session_pool
->HasSession(test_hosts
[0].pair
));
885 EXPECT_FALSE(spdy_session_pool
->HasSession(test_hosts
[1].pair
));
886 EXPECT_FALSE(spdy_session_pool
->HasSession(test_hosts
[2].pair
));
891 TEST_F(SpdySessionSpdy2Test
, IPPooling
) {
892 IPPoolingTest(SPDY_POOL_CLOSE_SESSIONS_MANUALLY
);
895 TEST_F(SpdySessionSpdy2Test
, IPPoolingCloseCurrentSessions
) {
896 IPPoolingTest(SPDY_POOL_CLOSE_CURRENT_SESSIONS
);
899 TEST_F(SpdySessionSpdy2Test
, IPPoolingCloseIdleSessions
) {
900 IPPoolingTest(SPDY_POOL_CLOSE_IDLE_SESSIONS
);
903 TEST_F(SpdySessionSpdy2Test
, ClearSettingsStorageOnIPAddressChanged
) {
904 CreateNetworkSession();
906 HttpServerProperties
* test_http_server_properties
=
907 spdy_session_pool_
->http_server_properties();
908 SettingsFlagsAndValue
flags_and_value1(SETTINGS_FLAG_PLEASE_PERSIST
, 2);
909 test_http_server_properties
->SetSpdySetting(
910 test_host_port_pair_
,
911 SETTINGS_MAX_CONCURRENT_STREAMS
,
912 SETTINGS_FLAG_PLEASE_PERSIST
,
914 EXPECT_NE(0u, test_http_server_properties
->GetSpdySettings(
915 test_host_port_pair_
).size());
916 spdy_session_pool_
->OnIPAddressChanged();
917 EXPECT_EQ(0u, test_http_server_properties
->GetSpdySettings(
918 test_host_port_pair_
).size());
921 TEST_F(SpdySessionSpdy2Test
, CloseSessionOnError
) {
922 session_deps_
.host_resolver
->set_synchronous_mode(true);
924 MockConnect
connect_data(SYNCHRONOUS
, OK
);
925 scoped_ptr
<SpdyFrame
> goaway(ConstructSpdyGoAway());
927 CreateMockRead(*goaway
),
928 MockRead(SYNCHRONOUS
, 0, 0) // EOF
931 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
932 data
.set_connect_data(connect_data
);
933 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
935 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
936 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
938 CreateNetworkSession();
940 CapturingBoundNetLog log
;
941 scoped_refptr
<SpdySession
> session
=
942 spdy_session_pool_
->Get(pair_
, log
.bound());
943 EXPECT_TRUE(spdy_session_pool_
->HasSession(pair_
));
945 InitializeSession(http_session_
.get(), session
.get(), test_host_port_pair_
);
947 // Flush the SpdySession::OnReadComplete() task.
948 MessageLoop::current()->RunUntilIdle();
950 EXPECT_FALSE(spdy_session_pool_
->HasSession(pair_
));
952 // Check that the NetLog was filled reasonably.
953 net::CapturingNetLog::CapturedEntryList entries
;
954 log
.GetEntries(&entries
);
955 EXPECT_LT(0u, entries
.size());
957 // Check that we logged SPDY_SESSION_CLOSE correctly.
958 int pos
= net::ExpectLogContainsSomewhere(
960 net::NetLog::TYPE_SPDY_SESSION_CLOSE
,
961 net::NetLog::PHASE_NONE
);
963 CapturingNetLog::CapturedEntry entry
= entries
[pos
];
965 ASSERT_TRUE(entry
.GetNetErrorCode(&error_code
));
966 EXPECT_EQ(ERR_CONNECTION_CLOSED
, error_code
);
969 TEST_F(SpdySessionSpdy2Test
, OutOfOrderSynStreams
) {
970 // Construct the request.
971 MockConnect
connect_data(SYNCHRONOUS
, OK
);
972 scoped_ptr
<SpdyFrame
> req1(ConstructSpdyGet(NULL
, 0, false, 1, HIGHEST
));
973 scoped_ptr
<SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
));
974 MockWrite writes
[] = {
975 CreateMockWrite(*req1
, 2),
976 CreateMockWrite(*req2
, 1),
979 scoped_ptr
<SpdyFrame
> resp1(ConstructSpdyGetSynReply(NULL
, 0, 1));
980 scoped_ptr
<SpdyFrame
> body1(ConstructSpdyBodyFrame(1, true));
981 scoped_ptr
<SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 3));
982 scoped_ptr
<SpdyFrame
> body2(ConstructSpdyBodyFrame(3, true));
984 CreateMockRead(*resp1
, 3),
985 CreateMockRead(*body1
, 4),
986 CreateMockRead(*resp2
, 5),
987 CreateMockRead(*body2
, 6),
988 MockRead(ASYNC
, 0, 7) // EOF
991 session_deps_
.host_resolver
->set_synchronous_mode(true);
993 StaticSocketDataProvider
data(reads
, arraysize(reads
),
994 writes
, arraysize(writes
));
995 data
.set_connect_data(connect_data
);
996 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
998 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
999 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
1001 CreateNetworkSession();
1003 scoped_refptr
<SpdySession
> session
= CreateInitializedSession();
1005 GURL
url("http://www.google.com");
1007 scoped_refptr
<SpdyStream
> spdy_stream1
=
1008 CreateStreamSynchronously(session
, url
, LOWEST
, BoundNetLog());
1009 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1010 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1012 scoped_refptr
<SpdyStream
> spdy_stream2
=
1013 CreateStreamSynchronously(session
, url
, HIGHEST
, BoundNetLog());
1014 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
1015 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1017 scoped_ptr
<SpdyHeaderBlock
> headers(new SpdyHeaderBlock
);
1018 (*headers
)["method"] = "GET";
1019 (*headers
)["scheme"] = url
.scheme();
1020 (*headers
)["host"] = url
.host();
1021 (*headers
)["url"] = url
.path();
1022 (*headers
)["version"] = "HTTP/1.1";
1023 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock
);
1024 *headers2
= *headers
;
1026 spdy_stream1
->set_spdy_headers(headers
.Pass());
1027 EXPECT_TRUE(spdy_stream1
->HasUrl());
1029 spdy_stream2
->set_spdy_headers(headers2
.Pass());
1030 EXPECT_TRUE(spdy_stream2
->HasUrl());
1032 spdy_stream1
->SendRequest(false);
1033 spdy_stream2
->SendRequest(false);
1034 MessageLoop::current()->RunUntilIdle();
1036 EXPECT_EQ(3u, spdy_stream1
->stream_id());
1037 EXPECT_EQ(1u, spdy_stream2
->stream_id());
1039 spdy_stream1
->Cancel();
1040 spdy_stream1
= NULL
;
1042 spdy_stream2
->Cancel();
1043 spdy_stream2
= NULL
;
1046 TEST_F(SpdySessionSpdy2Test
, CancelStream
) {
1047 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1048 // Request 1, at HIGHEST priority, will be cancelled before it writes data.
1049 // Request 2, at LOWEST priority, will be a full request and will be id 1.
1050 scoped_ptr
<SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
1051 MockWrite writes
[] = {
1052 CreateMockWrite(*req2
, 0),
1055 scoped_ptr
<SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 1));
1056 scoped_ptr
<SpdyFrame
> body2(ConstructSpdyBodyFrame(1, true));
1057 MockRead reads
[] = {
1058 CreateMockRead(*resp2
, 1),
1059 CreateMockRead(*body2
, 2),
1060 MockRead(ASYNC
, 0, 3) // EOF
1063 session_deps_
.host_resolver
->set_synchronous_mode(true);
1065 DeterministicSocketData
data(reads
, arraysize(reads
),
1066 writes
, arraysize(writes
));
1067 data
.set_connect_data(connect_data
);
1068 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1070 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
1071 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
1073 CreateDeterministicNetworkSession();
1075 scoped_refptr
<SpdySession
> session
= CreateInitializedSession();
1077 GURL
url1("http://www.google.com");
1078 scoped_refptr
<SpdyStream
> spdy_stream1
=
1079 CreateStreamSynchronously(session
, url1
, HIGHEST
, BoundNetLog());
1080 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1081 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1083 GURL
url2("http://www.google.com");
1084 scoped_refptr
<SpdyStream
> spdy_stream2
=
1085 CreateStreamSynchronously(session
, url2
, LOWEST
, BoundNetLog());
1086 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
1087 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1089 scoped_ptr
<SpdyHeaderBlock
> headers(new SpdyHeaderBlock
);
1090 (*headers
)["method"] = "GET";
1091 (*headers
)["scheme"] = url1
.scheme();
1092 (*headers
)["host"] = url1
.host();
1093 (*headers
)["url"] = url1
.path();
1094 (*headers
)["version"] = "HTTP/1.1";
1095 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock
);
1096 *headers2
= *headers
;
1098 spdy_stream1
->set_spdy_headers(headers
.Pass());
1099 EXPECT_TRUE(spdy_stream1
->HasUrl());
1101 spdy_stream2
->set_spdy_headers(headers2
.Pass());
1102 EXPECT_TRUE(spdy_stream2
->HasUrl());
1104 spdy_stream1
->SendRequest(false);
1105 spdy_stream2
->SendRequest(false);
1107 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1109 spdy_stream1
->Cancel();
1111 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1115 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1116 EXPECT_EQ(1u, spdy_stream2
->stream_id());
1118 spdy_stream1
= NULL
;
1119 spdy_stream2
->Cancel();
1120 spdy_stream2
= NULL
;
1123 TEST_F(SpdySessionSpdy2Test
, CloseSessionWithTwoCreatedStreams
) {
1124 session_deps_
.host_resolver
->set_synchronous_mode(true);
1126 // Test that if a sesion is closed with two created streams pending,
1127 // it does not crash. http://crbug.com/139518
1128 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1130 // No actual data will be sent.
1131 MockWrite writes
[] = {
1132 MockWrite(ASYNC
, 0, 1) // EOF
1135 MockRead reads
[] = {
1136 MockRead(ASYNC
, 0, 0) // EOF
1138 DeterministicSocketData
data(reads
, arraysize(reads
),
1139 writes
, arraysize(writes
));
1140 data
.set_connect_data(connect_data
);
1141 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1143 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
1144 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
1146 CreateDeterministicNetworkSession();
1148 scoped_refptr
<SpdySession
> session
= CreateInitializedSession();
1150 GURL
url1("http://www.google.com");
1151 scoped_refptr
<SpdyStream
> spdy_stream1
=
1152 CreateStreamSynchronously(session
, url1
, HIGHEST
, BoundNetLog());
1153 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1154 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1156 GURL
url2("http://www.google.com");
1157 scoped_refptr
<SpdyStream
> spdy_stream2
=
1158 CreateStreamSynchronously(session
, url2
, LOWEST
, BoundNetLog());
1159 ASSERT_TRUE(spdy_stream2
.get() != NULL
);
1160 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1162 scoped_ptr
<SpdyHeaderBlock
> headers(new SpdyHeaderBlock
);
1163 (*headers
)["method"] = "GET";
1164 (*headers
)["scheme"] = url1
.scheme();
1165 (*headers
)["host"] = url1
.host();
1166 (*headers
)["url"] = url1
.path();
1167 (*headers
)["version"] = "HTTP/1.1";
1168 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock
);
1169 *headers2
= *headers
;
1171 spdy_stream1
->set_spdy_headers(headers
.Pass());
1172 EXPECT_TRUE(spdy_stream1
->HasUrl());
1173 test::ClosingDelegate
delegate1(spdy_stream1
.get());
1174 spdy_stream1
->SetDelegate(&delegate1
);
1176 spdy_stream2
->set_spdy_headers(headers2
.Pass());
1177 EXPECT_TRUE(spdy_stream2
->HasUrl());
1178 test::ClosingDelegate
delegate2(spdy_stream2
.get());
1179 spdy_stream2
->SetDelegate(&delegate2
);
1181 spdy_stream1
->SendRequest(false);
1182 spdy_stream2
->SendRequest(false);
1184 // Ensure that the streams have not yet been activated and assigned an id.
1185 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1186 EXPECT_EQ(0u, spdy_stream2
->stream_id());
1188 // Ensure we don't crash while closing the session.
1189 session
->CloseSessionOnError(ERR_ABORTED
, true, std::string());
1191 EXPECT_TRUE(spdy_stream1
->closed());
1192 EXPECT_TRUE(spdy_stream2
->closed());
1194 spdy_stream1
= NULL
;
1195 spdy_stream2
= NULL
;
1198 TEST_F(SpdySessionSpdy2Test
, VerifyDomainAuthentication
) {
1199 session_deps_
.host_resolver
->set_synchronous_mode(true);
1201 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1203 // No actual data will be sent.
1204 MockWrite writes
[] = {
1205 MockWrite(ASYNC
, 0, 1) // EOF
1208 MockRead reads
[] = {
1209 MockRead(ASYNC
, 0, 0) // EOF
1211 DeterministicSocketData
data(reads
, arraysize(reads
),
1212 writes
, arraysize(writes
));
1213 data
.set_connect_data(connect_data
);
1214 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1216 // Load a cert that is valid for:
1220 base::FilePath certs_dir
= GetTestCertsDirectory();
1221 scoped_refptr
<X509Certificate
> test_cert(
1222 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
1223 ASSERT_NE(static_cast<X509Certificate
*>(NULL
), test_cert
);
1225 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
1226 ssl
.cert
= test_cert
;
1227 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
1229 CreateDeterministicNetworkSession();
1231 scoped_refptr
<SpdySession
> session
= GetSession(pair_
);
1233 SSLConfig ssl_config
;
1234 scoped_refptr
<TransportSocketParams
> transport_params(
1235 new TransportSocketParams(test_host_port_pair_
,
1239 OnHostResolutionCallback()));
1240 scoped_refptr
<SOCKSSocketParams
> socks_params
;
1241 scoped_refptr
<HttpProxySocketParams
> http_proxy_params
;
1242 scoped_refptr
<SSLSocketParams
> ssl_params(
1243 new SSLSocketParams(transport_params
,
1246 ProxyServer::SCHEME_DIRECT
,
1247 test_host_port_pair_
,
1252 scoped_ptr
<ClientSocketHandle
> connection(new ClientSocketHandle
);
1253 EXPECT_EQ(OK
, connection
->Init(test_host_port_pair_
.ToString(),
1254 ssl_params
, MEDIUM
, CompletionCallback(),
1255 http_session_
->GetSSLSocketPool(
1256 HttpNetworkSession::NORMAL_SOCKET_POOL
),
1259 EXPECT_EQ(OK
, session
->InitializeWithSocket(connection
.release(), false, OK
));
1260 EXPECT_TRUE(session
->VerifyDomainAuthentication("www.example.org"));
1261 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.org"));
1262 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.com"));
1263 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.google.com"));
1266 TEST_F(SpdySessionSpdy2Test
, ConnectionPooledWithTlsChannelId
) {
1267 session_deps_
.host_resolver
->set_synchronous_mode(true);
1269 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1271 // No actual data will be sent.
1272 MockWrite writes
[] = {
1273 MockWrite(ASYNC
, 0, 1) // EOF
1276 MockRead reads
[] = {
1277 MockRead(ASYNC
, 0, 0) // EOF
1279 DeterministicSocketData
data(reads
, arraysize(reads
),
1280 writes
, arraysize(writes
));
1281 data
.set_connect_data(connect_data
);
1282 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1284 // Load a cert that is valid for:
1288 base::FilePath certs_dir
= GetTestCertsDirectory();
1289 scoped_refptr
<X509Certificate
> test_cert(
1290 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
1291 ASSERT_NE(static_cast<X509Certificate
*>(NULL
), test_cert
);
1293 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
1294 ssl
.channel_id_sent
= true;
1295 ssl
.cert
= test_cert
;
1296 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
1298 CreateDeterministicNetworkSession();
1300 scoped_refptr
<SpdySession
> session
= GetSession(pair_
);
1302 SSLConfig ssl_config
;
1303 scoped_refptr
<TransportSocketParams
> transport_params(
1304 new TransportSocketParams(test_host_port_pair_
,
1308 OnHostResolutionCallback()));
1309 scoped_refptr
<SOCKSSocketParams
> socks_params
;
1310 scoped_refptr
<HttpProxySocketParams
> http_proxy_params
;
1311 scoped_refptr
<SSLSocketParams
> ssl_params(
1312 new SSLSocketParams(transport_params
,
1315 ProxyServer::SCHEME_DIRECT
,
1316 test_host_port_pair_
,
1321 scoped_ptr
<ClientSocketHandle
> connection(new ClientSocketHandle
);
1322 EXPECT_EQ(OK
, connection
->Init(test_host_port_pair_
.ToString(),
1323 ssl_params
, MEDIUM
, CompletionCallback(),
1324 http_session_
->GetSSLSocketPool(
1325 HttpNetworkSession::NORMAL_SOCKET_POOL
),
1328 EXPECT_EQ(OK
, session
->InitializeWithSocket(connection
.release(), false, OK
));
1329 EXPECT_TRUE(session
->VerifyDomainAuthentication("www.example.org"));
1330 EXPECT_TRUE(session
->VerifyDomainAuthentication("mail.example.org"));
1331 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.example.com"));
1332 EXPECT_FALSE(session
->VerifyDomainAuthentication("mail.google.com"));
1335 TEST_F(SpdySessionSpdy2Test
, CloseTwoStalledCreateStream
) {
1336 // TODO(rtenneti): Define a helper class/methods and move the common code in
1338 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1340 SettingsMap new_settings
;
1341 const SpdySettingsIds kSpdySettingsIds1
= SETTINGS_MAX_CONCURRENT_STREAMS
;
1342 const uint32 max_concurrent_streams
= 1;
1343 new_settings
[kSpdySettingsIds1
] =
1344 SettingsFlagsAndValue(SETTINGS_FLAG_NONE
, max_concurrent_streams
);
1346 scoped_ptr
<SpdyFrame
> req1(ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
));
1347 scoped_ptr
<SpdyFrame
> req2(ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
));
1348 scoped_ptr
<SpdyFrame
> req3(ConstructSpdyGet(NULL
, 0, false, 5, LOWEST
));
1349 MockWrite writes
[] = {
1350 CreateMockWrite(*req1
, 1),
1351 CreateMockWrite(*req2
, 4),
1352 CreateMockWrite(*req3
, 7),
1355 // Set up the socket so we read a SETTINGS frame that sets max concurrent
1357 scoped_ptr
<SpdyFrame
> settings_frame(ConstructSpdySettings(new_settings
));
1359 scoped_ptr
<SpdyFrame
> resp1(ConstructSpdyGetSynReply(NULL
, 0, 1));
1360 scoped_ptr
<SpdyFrame
> body1(ConstructSpdyBodyFrame(1, true));
1362 scoped_ptr
<SpdyFrame
> resp2(ConstructSpdyGetSynReply(NULL
, 0, 3));
1363 scoped_ptr
<SpdyFrame
> body2(ConstructSpdyBodyFrame(3, true));
1365 scoped_ptr
<SpdyFrame
> resp3(ConstructSpdyGetSynReply(NULL
, 0, 5));
1366 scoped_ptr
<SpdyFrame
> body3(ConstructSpdyBodyFrame(5, true));
1368 MockRead reads
[] = {
1369 CreateMockRead(*settings_frame
),
1370 CreateMockRead(*resp1
, 2),
1371 CreateMockRead(*body1
, 3),
1372 CreateMockRead(*resp2
, 5),
1373 CreateMockRead(*body2
, 6),
1374 CreateMockRead(*resp3
, 8),
1375 CreateMockRead(*body3
, 9),
1376 MockRead(ASYNC
, 0, 10) // EOF
1379 DeterministicSocketData
data(reads
, arraysize(reads
),
1380 writes
, arraysize(writes
));
1381 data
.set_connect_data(connect_data
);
1382 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1384 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
1385 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
1387 CreateDeterministicNetworkSession();
1389 scoped_refptr
<SpdySession
> session
= CreateInitializedSession();
1391 // Read the settings frame.
1394 GURL
url1("http://www.google.com");
1395 scoped_refptr
<SpdyStream
> spdy_stream1
=
1396 CreateStreamSynchronously(session
, url1
, LOWEST
, BoundNetLog());
1397 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1398 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1400 TestCompletionCallback callback2
;
1401 GURL
url2("http://www.google.com");
1402 SpdyStreamRequest request2
;
1403 ASSERT_EQ(ERR_IO_PENDING
,
1404 request2
.StartRequest(session
, url2
, LOWEST
,
1406 callback2
.callback()));
1408 TestCompletionCallback callback3
;
1409 GURL
url3("http://www.google.com");
1410 SpdyStreamRequest request3
;
1411 ASSERT_EQ(ERR_IO_PENDING
,
1412 request3
.StartRequest(session
, url3
, LOWEST
,
1414 callback3
.callback()));
1416 EXPECT_EQ(1u, session
->num_active_streams() + session
->num_created_streams());
1417 EXPECT_EQ(2u, session
->pending_create_stream_queues(LOWEST
));
1419 scoped_ptr
<SpdyHeaderBlock
> headers(new SpdyHeaderBlock
);
1420 (*headers
)["method"] = "GET";
1421 (*headers
)["scheme"] = url1
.scheme();
1422 (*headers
)["host"] = url1
.host();
1423 (*headers
)["url"] = url1
.path();
1424 (*headers
)["version"] = "HTTP/1.1";
1425 scoped_ptr
<SpdyHeaderBlock
> headers2(new SpdyHeaderBlock
);
1426 *headers2
= *headers
;
1427 scoped_ptr
<SpdyHeaderBlock
> headers3(new SpdyHeaderBlock
);
1428 *headers3
= *headers
;
1430 spdy_stream1
->set_spdy_headers(headers
.Pass());
1431 EXPECT_TRUE(spdy_stream1
->HasUrl());
1432 spdy_stream1
->SendRequest(false);
1434 // Run until 1st stream is closed and 2nd one is opened.
1435 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1437 EXPECT_EQ(1u, spdy_stream1
->stream_id());
1438 EXPECT_EQ(2u, session
->num_active_streams() + session
->num_created_streams());
1439 EXPECT_EQ(0u, session
->pending_create_stream_queues(LOWEST
));
1441 scoped_refptr
<SpdyStream
> stream2
= request2
.ReleaseStream();
1442 stream2
->set_spdy_headers(headers2
.Pass());
1443 EXPECT_TRUE(stream2
->HasUrl());
1444 stream2
->SendRequest(false);
1446 // Run until 2nd stream is closed.
1447 EXPECT_EQ(0u, stream2
->stream_id());
1449 EXPECT_EQ(3u, stream2
->stream_id());
1450 EXPECT_EQ(1u, session
->num_active_streams() + session
->num_created_streams());
1451 EXPECT_EQ(0u, session
->pending_create_stream_queues(LOWEST
));
1453 scoped_refptr
<SpdyStream
> stream3
= request3
.ReleaseStream();
1454 ASSERT_TRUE(stream3
.get() != NULL
);
1455 stream3
->set_spdy_headers(headers3
.Pass());
1456 EXPECT_TRUE(stream3
->HasUrl());
1457 stream3
->SendRequest(false);
1459 EXPECT_EQ(0u, stream3
->stream_id());
1461 EXPECT_EQ(5u, stream3
->stream_id());
1462 EXPECT_EQ(0u, session
->num_active_streams() + session
->num_created_streams());
1463 EXPECT_EQ(0u, session
->pending_create_stream_queues(LOWEST
));
1466 TEST_F(SpdySessionSpdy2Test
, CancelTwoStalledCreateStream
) {
1467 session_deps_
.host_resolver
->set_synchronous_mode(true);
1469 MockRead reads
[] = {
1470 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1473 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1474 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1476 data
.set_connect_data(connect_data
);
1477 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1479 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
1480 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
1482 CreateNetworkSession();
1484 // Initialize the SpdySetting with 1 max concurrent streams.
1485 spdy_session_pool_
->http_server_properties()->SetSpdySetting(
1486 test_host_port_pair_
,
1487 SETTINGS_MAX_CONCURRENT_STREAMS
,
1488 SETTINGS_FLAG_PLEASE_PERSIST
,
1491 scoped_refptr
<SpdySession
> session
= CreateInitializedSession();
1493 GURL
url1("http://www.google.com");
1494 scoped_refptr
<SpdyStream
> spdy_stream1
=
1495 CreateStreamSynchronously(session
, url1
, LOWEST
, BoundNetLog());
1496 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1497 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1499 TestCompletionCallback callback2
;
1500 GURL
url2("http://www.google.com");
1501 SpdyStreamRequest request2
;
1502 ASSERT_EQ(ERR_IO_PENDING
,
1503 request2
.StartRequest(session
, url2
, LOWEST
,
1505 callback2
.callback()));
1507 TestCompletionCallback callback3
;
1508 GURL
url3("http://www.google.com");
1509 SpdyStreamRequest request3
;
1510 ASSERT_EQ(ERR_IO_PENDING
,
1511 request3
.StartRequest(session
, url3
, LOWEST
,
1513 callback3
.callback()));
1515 EXPECT_EQ(1u, session
->num_active_streams() + session
->num_created_streams());
1516 EXPECT_EQ(2u, session
->pending_create_stream_queues(LOWEST
));
1518 // Cancel the first stream, this will allow the second stream to be created.
1519 EXPECT_TRUE(spdy_stream1
.get() != NULL
);
1520 spdy_stream1
->Cancel();
1521 spdy_stream1
= NULL
;
1523 callback2
.WaitForResult();
1524 EXPECT_EQ(2u, session
->num_active_streams() + session
->num_created_streams());
1525 EXPECT_EQ(0u, session
->pending_create_stream_queues(LOWEST
));
1527 // Cancel the second stream, this will allow the third stream to be created.
1528 request2
.ReleaseStream()->Cancel();
1529 EXPECT_EQ(1u, session
->num_active_streams() + session
->num_created_streams());
1530 EXPECT_EQ(0u, session
->pending_create_stream_queues(LOWEST
));
1532 // Cancel the third stream.
1533 request3
.ReleaseStream()->Cancel();
1534 EXPECT_EQ(0u, session
->num_active_streams() + session
->num_created_streams());
1535 EXPECT_EQ(0u, session
->pending_create_stream_queues(LOWEST
));
1538 TEST_F(SpdySessionSpdy2Test
, NeedsCredentials
) {
1539 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1540 MockRead reads
[] = {
1541 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
) // Stall forever.
1543 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1544 data
.set_connect_data(connect_data
);
1545 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1547 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
1548 ssl
.channel_id_sent
= true;
1549 ssl
.protocol_negotiated
= kProtoSPDY2
;
1550 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
1552 CreateNetworkSession();
1554 const std::string
kTestHost("www.foo.com");
1555 const int kTestPort
= 80;
1556 HostPortPair
test_host_port_pair(kTestHost
, kTestPort
);
1557 HostPortProxyPair
pair(test_host_port_pair
, ProxyServer::Direct());
1559 scoped_refptr
<SpdySession
> session
= GetSession(pair
);
1561 SSLConfig ssl_config
;
1562 scoped_refptr
<TransportSocketParams
> transport_params(
1563 new TransportSocketParams(test_host_port_pair
,
1567 OnHostResolutionCallback()));
1568 scoped_refptr
<SOCKSSocketParams
> socks_params
;
1569 scoped_refptr
<HttpProxySocketParams
> http_proxy_params
;
1570 scoped_refptr
<SSLSocketParams
> ssl_params(
1571 new SSLSocketParams(transport_params
,
1574 ProxyServer::SCHEME_DIRECT
,
1575 test_host_port_pair
,
1580 scoped_ptr
<ClientSocketHandle
> connection(new ClientSocketHandle
);
1581 EXPECT_EQ(OK
, connection
->Init(test_host_port_pair
.ToString(),
1582 ssl_params
, MEDIUM
, CompletionCallback(),
1583 http_session_
->GetSSLSocketPool(
1584 HttpNetworkSession::NORMAL_SOCKET_POOL
),
1587 EXPECT_EQ(OK
, session
->InitializeWithSocket(connection
.release(), true, OK
));
1589 EXPECT_FALSE(session
->NeedsCredentials());
1591 // Flush the SpdySession::OnReadComplete() task.
1592 MessageLoop::current()->RunUntilIdle();
1594 spdy_session_pool_
->Remove(session
);
1597 // Test that SpdySession::DoRead reads data from the socket without yielding.
1598 // This test makes 32k - 1 bytes of data available on the socket for reading. It
1599 // then verifies that it has read all the available data without yielding.
1600 TEST_F(SpdySessionSpdy2Test
, ReadDataWithoutYielding
) {
1601 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1602 BufferedSpdyFramer
framer(2, false);
1604 scoped_ptr
<SpdyFrame
> req1(ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
));
1605 MockWrite writes
[] = {
1606 CreateMockWrite(*req1
, 0),
1609 // Build buffer of size kMaxReadBytes / 4 (-spdy_data_frame_size).
1610 ASSERT_EQ(32 * 1024, kMaxReadBytes
);
1611 const int kPayloadSize
=
1612 kMaxReadBytes
/ 4 - framer
.GetControlFrameHeaderSize();
1613 TestDataStream test_stream
;
1614 scoped_refptr
<net::IOBuffer
> payload(new net::IOBuffer(kPayloadSize
));
1615 char* payload_data
= payload
->data();
1616 test_stream
.GetBytes(payload_data
, kPayloadSize
);
1618 scoped_ptr
<SpdyFrame
> partial_data_frame(
1619 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
, DATA_FLAG_NONE
));
1620 scoped_ptr
<SpdyFrame
> finish_data_frame(
1621 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
- 1, DATA_FLAG_FIN
));
1623 scoped_ptr
<SpdyFrame
> resp1(ConstructSpdyGetSynReply(NULL
, 0, 1));
1625 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
1627 MockRead reads
[] = {
1628 CreateMockRead(*resp1
, 1),
1629 CreateMockRead(*partial_data_frame
, 2),
1630 CreateMockRead(*partial_data_frame
, 3, SYNCHRONOUS
),
1631 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
1632 CreateMockRead(*finish_data_frame
, 5, SYNCHRONOUS
),
1633 MockRead(ASYNC
, 0, 6) // EOF
1636 // Create SpdySession and SpdyStream and send the request.
1637 DeterministicSocketData
data(reads
, arraysize(reads
),
1638 writes
, arraysize(writes
));
1639 data
.set_connect_data(connect_data
);
1640 session_deps_
.host_resolver
->set_synchronous_mode(true);
1641 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1643 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
1644 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
1646 CreateDeterministicNetworkSession();
1648 scoped_refptr
<SpdySession
> session
= CreateInitializedSession();
1650 GURL
url1("http://www.google.com");
1651 scoped_refptr
<SpdyStream
> spdy_stream1
=
1652 CreateStreamSynchronously(session
, url1
, MEDIUM
, BoundNetLog());
1653 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1654 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1656 scoped_ptr
<SpdyHeaderBlock
> headers(new SpdyHeaderBlock
);
1657 (*headers
)["method"] = "GET";
1658 (*headers
)["scheme"] = url1
.scheme();
1659 (*headers
)["host"] = url1
.host();
1660 (*headers
)["url"] = url1
.path();
1661 (*headers
)["version"] = "HTTP/1.1";
1663 spdy_stream1
->set_spdy_headers(headers
.Pass());
1664 EXPECT_TRUE(spdy_stream1
->HasUrl());
1665 spdy_stream1
->SendRequest(false);
1667 // Set up the TaskObserver to verify SpdySession::DoRead doesn't post a task.
1668 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoRead");
1670 // Run until 1st read.
1671 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1673 EXPECT_EQ(1u, spdy_stream1
->stream_id());
1674 EXPECT_EQ(0u, observer
.executed_count());
1676 // Read all the data and verify SpdySession::DoRead has not posted a task.
1679 // Verify task observer's executed_count is zero, which indicates DoRead read
1680 // all the available data.
1681 EXPECT_EQ(0u, observer
.executed_count());
1682 EXPECT_TRUE(data
.at_write_eof());
1683 EXPECT_TRUE(data
.at_read_eof());
1686 // Test that SpdySession::DoRead yields while reading the data. This test makes
1687 // 32k + 1 bytes of data available on the socket for reading. It then verifies
1688 // that DoRead has yielded even though there is data available for it to read
1689 // (i.e, socket()->Read didn't return ERR_IO_PENDING during socket reads).
1690 TEST_F(SpdySessionSpdy2Test
, TestYieldingDuringReadData
) {
1691 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1692 BufferedSpdyFramer
framer(2, false);
1694 scoped_ptr
<SpdyFrame
> req1(ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
));
1695 MockWrite writes
[] = {
1696 CreateMockWrite(*req1
, 0),
1699 // Build buffer of size kMaxReadBytes / 4 (-spdy_data_frame_size).
1700 ASSERT_EQ(32 * 1024, kMaxReadBytes
);
1701 const int kPayloadSize
=
1702 kMaxReadBytes
/ 4 - framer
.GetControlFrameHeaderSize();
1703 TestDataStream test_stream
;
1704 scoped_refptr
<net::IOBuffer
> payload(new net::IOBuffer(kPayloadSize
));
1705 char* payload_data
= payload
->data();
1706 test_stream
.GetBytes(payload_data
, kPayloadSize
);
1708 scoped_ptr
<SpdyFrame
> partial_data_frame(
1709 framer
.CreateDataFrame(1, payload_data
, kPayloadSize
, DATA_FLAG_NONE
));
1710 scoped_ptr
<SpdyFrame
> finish_data_frame(
1711 framer
.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN
));
1713 scoped_ptr
<SpdyFrame
> resp1(ConstructSpdyGetSynReply(NULL
, 0, 1));
1715 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
1716 MockRead reads
[] = {
1717 CreateMockRead(*resp1
, 1),
1718 CreateMockRead(*partial_data_frame
, 2),
1719 CreateMockRead(*partial_data_frame
, 3, SYNCHRONOUS
),
1720 CreateMockRead(*partial_data_frame
, 4, SYNCHRONOUS
),
1721 CreateMockRead(*partial_data_frame
, 5, SYNCHRONOUS
),
1722 CreateMockRead(*finish_data_frame
, 6, SYNCHRONOUS
),
1723 MockRead(ASYNC
, 0, 7) // EOF
1726 // Create SpdySession and SpdyStream and send the request.
1727 DeterministicSocketData
data(reads
, arraysize(reads
),
1728 writes
, arraysize(writes
));
1729 data
.set_connect_data(connect_data
);
1730 session_deps_
.host_resolver
->set_synchronous_mode(true);
1731 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1733 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
1734 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
1736 CreateDeterministicNetworkSession();
1738 scoped_refptr
<SpdySession
> session
= CreateInitializedSession();
1740 GURL
url1("http://www.google.com");
1741 scoped_refptr
<SpdyStream
> spdy_stream1
=
1742 CreateStreamSynchronously(session
, url1
, MEDIUM
, BoundNetLog());
1743 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1744 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1746 scoped_ptr
<SpdyHeaderBlock
> headers(new SpdyHeaderBlock
);
1747 (*headers
)["method"] = "GET";
1748 (*headers
)["scheme"] = url1
.scheme();
1749 (*headers
)["host"] = url1
.host();
1750 (*headers
)["url"] = url1
.path();
1751 (*headers
)["version"] = "HTTP/1.1";
1753 spdy_stream1
->set_spdy_headers(headers
.Pass());
1754 EXPECT_TRUE(spdy_stream1
->HasUrl());
1755 spdy_stream1
->SendRequest(false);
1757 // Set up the TaskObserver to verify SpdySession::DoRead posts a task.
1758 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoRead");
1760 // Run until 1st read.
1761 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1763 EXPECT_EQ(1u, spdy_stream1
->stream_id());
1764 EXPECT_EQ(0u, observer
.executed_count());
1766 // Read all the data and verify SpdySession::DoRead has posted a task.
1769 // Verify task observer's executed_count is 1, which indicates DoRead has
1770 // posted only one task and thus yielded though there is data available for it
1772 EXPECT_EQ(1u, observer
.executed_count());
1773 EXPECT_TRUE(data
.at_write_eof());
1774 EXPECT_TRUE(data
.at_read_eof());
1777 // Test that SpdySession::DoRead() tests interactions of yielding + async,
1778 // by doing the following MockReads.
1780 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
1781 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
1783 // The above reads 26K synchronously. Since that is less that 32K, we will
1784 // attempt to read again. However, that DoRead() will return ERR_IO_PENDING
1785 // (because of async read), so DoRead() will yield. When we come back, DoRead()
1786 // will read the results from the async read, and rest of the data
1788 TEST_F(SpdySessionSpdy2Test
, TestYieldingDuringAsyncReadData
) {
1789 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1790 BufferedSpdyFramer
framer(2, false);
1792 scoped_ptr
<SpdyFrame
> req1(ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
));
1793 MockWrite writes
[] = {
1794 CreateMockWrite(*req1
, 0),
1797 // Build buffer of size kMaxReadBytes / 4 (-spdy_data_frame_size).
1798 ASSERT_EQ(32 * 1024, kMaxReadBytes
);
1799 TestDataStream test_stream
;
1800 const int kEightKPayloadSize
=
1801 kMaxReadBytes
/ 4 - framer
.GetControlFrameHeaderSize();
1802 scoped_refptr
<net::IOBuffer
> eightk_payload(
1803 new net::IOBuffer(kEightKPayloadSize
));
1804 char* eightk_payload_data
= eightk_payload
->data();
1805 test_stream
.GetBytes(eightk_payload_data
, kEightKPayloadSize
);
1807 // Build buffer of 2k size.
1808 TestDataStream test_stream2
;
1809 const int kTwoKPayloadSize
= kEightKPayloadSize
- 6 * 1024;
1810 scoped_refptr
<net::IOBuffer
> twok_payload(
1811 new net::IOBuffer(kTwoKPayloadSize
));
1812 char* twok_payload_data
= twok_payload
->data();
1813 test_stream2
.GetBytes(twok_payload_data
, kTwoKPayloadSize
);
1815 scoped_ptr
<SpdyFrame
> eightk_data_frame(framer
.CreateDataFrame(
1816 1, eightk_payload_data
, kEightKPayloadSize
, DATA_FLAG_NONE
));
1817 scoped_ptr
<SpdyFrame
> twok_data_frame(framer
.CreateDataFrame(
1818 1, twok_payload_data
, kTwoKPayloadSize
, DATA_FLAG_NONE
));
1819 scoped_ptr
<SpdyFrame
> finish_data_frame(framer
.CreateDataFrame(
1820 1, "h", 1, DATA_FLAG_FIN
));
1822 scoped_ptr
<SpdyFrame
> resp1(ConstructSpdyGetSynReply(NULL
, 0, 1));
1824 MockRead reads
[] = {
1825 CreateMockRead(*resp1
, 1),
1826 CreateMockRead(*eightk_data_frame
, 2),
1827 CreateMockRead(*eightk_data_frame
, 3, SYNCHRONOUS
),
1828 CreateMockRead(*eightk_data_frame
, 4, SYNCHRONOUS
),
1829 CreateMockRead(*twok_data_frame
, 5, SYNCHRONOUS
),
1830 CreateMockRead(*eightk_data_frame
, 6, ASYNC
),
1831 CreateMockRead(*eightk_data_frame
, 7, SYNCHRONOUS
),
1832 CreateMockRead(*eightk_data_frame
, 8, SYNCHRONOUS
),
1833 CreateMockRead(*eightk_data_frame
, 9, SYNCHRONOUS
),
1834 CreateMockRead(*twok_data_frame
, 10, SYNCHRONOUS
),
1835 CreateMockRead(*finish_data_frame
, 11, SYNCHRONOUS
),
1836 MockRead(ASYNC
, 0, 12) // EOF
1839 // Create SpdySession and SpdyStream and send the request.
1840 DeterministicSocketData
data(reads
, arraysize(reads
),
1841 writes
, arraysize(writes
));
1842 data
.set_connect_data(connect_data
);
1843 session_deps_
.host_resolver
->set_synchronous_mode(true);
1844 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1846 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
1847 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
1849 CreateDeterministicNetworkSession();
1851 scoped_refptr
<SpdySession
> session
= CreateInitializedSession();
1853 GURL
url1("http://www.google.com");
1854 scoped_refptr
<SpdyStream
> spdy_stream1
=
1855 CreateStreamSynchronously(session
, url1
, MEDIUM
, BoundNetLog());
1856 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1857 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1859 scoped_ptr
<SpdyHeaderBlock
> headers(new SpdyHeaderBlock
);
1860 (*headers
)["method"] = "GET";
1861 (*headers
)["scheme"] = url1
.scheme();
1862 (*headers
)["host"] = url1
.host();
1863 (*headers
)["url"] = url1
.path();
1864 (*headers
)["version"] = "HTTP/1.1";
1866 spdy_stream1
->set_spdy_headers(headers
.Pass());
1867 EXPECT_TRUE(spdy_stream1
->HasUrl());
1868 spdy_stream1
->SendRequest(false);
1870 // Set up the TaskObserver to monitor SpdySession::DoRead posting of tasks.
1871 SpdySessionTestTaskObserver
observer("spdy_session.cc", "DoRead");
1873 // Run until 1st read.
1874 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1876 EXPECT_EQ(1u, spdy_stream1
->stream_id());
1877 EXPECT_EQ(0u, observer
.executed_count());
1879 // Read all the data and verify SpdySession::DoRead has posted a task.
1882 // Verify task observer's executed_count is 1, which indicates DoRead has
1883 // posted only one task and thus yielded though there is data available for
1885 EXPECT_EQ(1u, observer
.executed_count());
1886 EXPECT_TRUE(data
.at_write_eof());
1887 EXPECT_TRUE(data
.at_read_eof());
1890 // Send a GoAway frame when SpdySession is in DoLoop. If scoped_refptr to
1891 // <SpdySession> is deleted from SpdySession::DoLoop(), we get a crash because
1892 // GoAway could delete the SpdySession from the SpdySessionPool and the last
1893 // reference to SpdySession.
1894 TEST_F(SpdySessionSpdy2Test
, GoAwayWhileInDoLoop
) {
1895 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1896 BufferedSpdyFramer
framer(2, false);
1898 scoped_ptr
<SpdyFrame
> req1(ConstructSpdyGet(NULL
, 0, false, 1, MEDIUM
));
1899 MockWrite writes
[] = {
1900 CreateMockWrite(*req1
, 0),
1903 scoped_ptr
<SpdyFrame
> resp1(ConstructSpdyGetSynReply(NULL
, 0, 1));
1904 scoped_ptr
<SpdyFrame
> body1(ConstructSpdyBodyFrame(1, true));
1905 scoped_ptr
<SpdyFrame
> goaway(ConstructSpdyGoAway());
1907 MockRead reads
[] = {
1908 CreateMockRead(*resp1
, 1),
1909 CreateMockRead(*body1
, 2),
1910 CreateMockRead(*goaway
, 3),
1911 MockRead(ASYNC
, 0, 4) // EOF
1914 // Create SpdySession and SpdyStream and send the request.
1915 DeterministicSocketData
data(reads
, arraysize(reads
),
1916 writes
, arraysize(writes
));
1917 data
.set_connect_data(connect_data
);
1918 session_deps_
.host_resolver
->set_synchronous_mode(true);
1919 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data
);
1921 SSLSocketDataProvider
ssl(SYNCHRONOUS
, OK
);
1922 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
1924 CreateDeterministicNetworkSession();
1926 scoped_refptr
<SpdySession
> session
= CreateInitializedSession();
1928 GURL
url1("http://www.google.com");
1929 scoped_refptr
<SpdyStream
> spdy_stream1
=
1930 CreateStreamSynchronously(session
, url1
, MEDIUM
, BoundNetLog());
1931 ASSERT_TRUE(spdy_stream1
.get() != NULL
);
1932 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1934 scoped_ptr
<SpdyHeaderBlock
> headers(new SpdyHeaderBlock
);
1935 (*headers
)["method"] = "GET";
1936 (*headers
)["scheme"] = url1
.scheme();
1937 (*headers
)["host"] = url1
.host();
1938 (*headers
)["url"] = url1
.path();
1939 (*headers
)["version"] = "HTTP/1.1";
1941 spdy_stream1
->set_spdy_headers(headers
.Pass());
1942 EXPECT_TRUE(spdy_stream1
->HasUrl());
1943 spdy_stream1
->SendRequest(false);
1945 // Run until 1st read.
1946 EXPECT_EQ(0u, spdy_stream1
->stream_id());
1948 EXPECT_EQ(1u, spdy_stream1
->stream_id());
1950 // Drop the reference to the session.
1953 // Run until GoAway.
1956 // Drop the reference to the stream which deletes its reference to the
1957 // SpdySession. Only references to SpdySession are held by DoLoop and
1958 // SpdySessionPool. If DoLoop doesn't hold the reference, we get a crash if
1959 // SpdySession is deleted from the SpdySessionPool.
1960 spdy_stream1
= NULL
;
1963 EXPECT_TRUE(data
.at_write_eof());
1964 EXPECT_TRUE(data
.at_read_eof());
1967 // Within this framework, a SpdySession should be initialized with
1968 // flow control disabled and with protocol version 2.
1969 TEST_F(SpdySessionSpdy2Test
, ProtocolNegotiation
) {
1970 session_deps_
.host_resolver
->set_synchronous_mode(true);
1972 MockConnect
connect_data(SYNCHRONOUS
, OK
);
1973 MockRead reads
[] = {
1974 MockRead(SYNCHRONOUS
, 0, 0) // EOF
1976 StaticSocketDataProvider
data(reads
, arraysize(reads
), NULL
, 0);
1977 data
.set_connect_data(connect_data
);
1978 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1980 CreateNetworkSession();
1981 scoped_refptr
<SpdySession
> session
= GetSession(pair_
);
1983 EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE
, session
->flow_control_state());
1984 EXPECT_TRUE(session
->buffered_spdy_framer_
== NULL
);
1985 EXPECT_EQ(0, session
->session_send_window_size_
);
1986 EXPECT_EQ(0, session
->session_recv_window_size_
);
1987 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);
1990 http_session_
.get(), session
.get(), test_host_port_pair_
);
1992 EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE
, session
->flow_control_state());
1993 EXPECT_EQ(kSpdyVersion2
, session
->buffered_spdy_framer_
->protocol_version());
1994 EXPECT_EQ(0, session
->session_send_window_size_
);
1995 EXPECT_EQ(0, session
->session_recv_window_size_
);
1996 EXPECT_EQ(0, session
->session_unacked_recv_window_bytes_
);