Fix mouse warp with 2x displays
[chromium-blink-merge.git] / net / spdy / spdy_session_pool_unittest.cc
blob3f12e61bab0ae349c4f3fcec0de18533a43edfac
1 // Copyright (c) 2013 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_pool.h"
7 #include <cstddef>
8 #include <string>
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "net/dns/host_cache.h"
13 #include "net/http/http_network_session.h"
14 #include "net/socket/client_socket_handle.h"
15 #include "net/socket/transport_client_socket_pool.h"
16 #include "net/spdy/spdy_session.h"
17 #include "net/spdy/spdy_stream_test_util.h"
18 #include "net/spdy/spdy_test_util_common.h"
19 #include "testing/gtest/include/gtest/gtest.h"
21 namespace net {
23 namespace {
25 class SpdySessionPoolTest : public ::testing::Test,
26 public ::testing::WithParamInterface<NextProto> {
27 protected:
28 // Used by RunIPPoolingTest().
29 enum SpdyPoolCloseSessionsType {
30 SPDY_POOL_CLOSE_SESSIONS_MANUALLY,
31 SPDY_POOL_CLOSE_CURRENT_SESSIONS,
32 SPDY_POOL_CLOSE_IDLE_SESSIONS,
35 SpdySessionPoolTest()
36 : session_deps_(GetParam()),
37 spdy_session_pool_(NULL) {}
39 void CreateNetworkSession() {
40 http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
41 spdy_session_pool_ = http_session_->spdy_session_pool();
44 void RunIPPoolingTest(SpdyPoolCloseSessionsType close_sessions_type);
46 SpdySessionDependencies session_deps_;
47 scoped_refptr<HttpNetworkSession> http_session_;
48 SpdySessionPool* spdy_session_pool_;
51 INSTANTIATE_TEST_CASE_P(NextProto,
52 SpdySessionPoolTest,
53 testing::Values(kProtoSPDY31,
54 kProtoHTTP2_14,
55 kProtoHTTP2));
57 // A delegate that opens a new session when it is closed.
58 class SessionOpeningDelegate : public SpdyStream::Delegate {
59 public:
60 SessionOpeningDelegate(SpdySessionPool* spdy_session_pool,
61 const SpdySessionKey& key)
62 : spdy_session_pool_(spdy_session_pool),
63 key_(key) {}
65 ~SessionOpeningDelegate() override {}
67 void OnRequestHeadersSent() override {}
69 SpdyResponseHeadersStatus OnResponseHeadersUpdated(
70 const SpdyHeaderBlock& response_headers) override {
71 return RESPONSE_HEADERS_ARE_COMPLETE;
74 void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) override {}
76 void OnDataSent() override {}
78 void OnClose(int status) override {
79 ignore_result(CreateFakeSpdySession(spdy_session_pool_, key_));
82 private:
83 SpdySessionPool* const spdy_session_pool_;
84 const SpdySessionKey key_;
87 // Set up a SpdyStream to create a new session when it is closed.
88 // CloseCurrentSessions should not close the newly-created session.
89 TEST_P(SpdySessionPoolTest, CloseCurrentSessions) {
90 const char kTestHost[] = "www.foo.com";
91 const int kTestPort = 80;
93 session_deps_.host_resolver->set_synchronous_mode(true);
95 HostPortPair test_host_port_pair(kTestHost, kTestPort);
96 SpdySessionKey test_key =
97 SpdySessionKey(
98 test_host_port_pair, ProxyServer::Direct(),
99 PRIVACY_MODE_DISABLED);
101 MockConnect connect_data(SYNCHRONOUS, OK);
102 MockRead reads[] = {
103 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
106 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
107 data.set_connect_data(connect_data);
108 session_deps_.socket_factory->AddSocketDataProvider(&data);
110 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
111 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
113 CreateNetworkSession();
115 // Setup the first session to the first host.
116 base::WeakPtr<SpdySession> session =
117 CreateInsecureSpdySession(http_session_, test_key, BoundNetLog());
119 // Flush the SpdySession::OnReadComplete() task.
120 base::MessageLoop::current()->RunUntilIdle();
122 // Verify that we have sessions for everything.
123 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_key));
125 // Set the stream to create a new session when it is closed.
126 base::WeakPtr<SpdyStream> spdy_stream =
127 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
128 session, GURL("http://www.foo.com"),
129 MEDIUM, BoundNetLog());
130 SessionOpeningDelegate delegate(spdy_session_pool_, test_key);
131 spdy_stream->SetDelegate(&delegate);
133 // Close the current session.
134 spdy_session_pool_->CloseCurrentSessions(ERR_ABORTED);
136 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_key));
139 TEST_P(SpdySessionPoolTest, CloseCurrentIdleSessions) {
140 MockConnect connect_data(SYNCHRONOUS, OK);
141 MockRead reads[] = {
142 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
145 session_deps_.host_resolver->set_synchronous_mode(true);
147 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
148 data.set_connect_data(connect_data);
149 session_deps_.socket_factory->AddSocketDataProvider(&data);
151 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
152 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
154 CreateNetworkSession();
156 // Set up session 1
157 const std::string kTestHost1("http://www.a.com");
158 HostPortPair test_host_port_pair1(kTestHost1, 80);
159 SpdySessionKey key1(test_host_port_pair1, ProxyServer::Direct(),
160 PRIVACY_MODE_DISABLED);
161 base::WeakPtr<SpdySession> session1 =
162 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
163 GURL url1(kTestHost1);
164 base::WeakPtr<SpdyStream> spdy_stream1 =
165 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
166 session1, url1, MEDIUM, BoundNetLog());
167 ASSERT_TRUE(spdy_stream1.get() != NULL);
169 // Set up session 2
170 session_deps_.socket_factory->AddSocketDataProvider(&data);
171 const std::string kTestHost2("http://www.b.com");
172 HostPortPair test_host_port_pair2(kTestHost2, 80);
173 SpdySessionKey key2(test_host_port_pair2, ProxyServer::Direct(),
174 PRIVACY_MODE_DISABLED);
175 base::WeakPtr<SpdySession> session2 =
176 CreateInsecureSpdySession(http_session_, key2, BoundNetLog());
177 GURL url2(kTestHost2);
178 base::WeakPtr<SpdyStream> spdy_stream2 =
179 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
180 session2, url2, MEDIUM, BoundNetLog());
181 ASSERT_TRUE(spdy_stream2.get() != NULL);
183 // Set up session 3
184 session_deps_.socket_factory->AddSocketDataProvider(&data);
185 const std::string kTestHost3("http://www.c.com");
186 HostPortPair test_host_port_pair3(kTestHost3, 80);
187 SpdySessionKey key3(test_host_port_pair3, ProxyServer::Direct(),
188 PRIVACY_MODE_DISABLED);
189 base::WeakPtr<SpdySession> session3 =
190 CreateInsecureSpdySession(http_session_, key3, BoundNetLog());
191 GURL url3(kTestHost3);
192 base::WeakPtr<SpdyStream> spdy_stream3 =
193 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
194 session3, url3, MEDIUM, BoundNetLog());
195 ASSERT_TRUE(spdy_stream3.get() != NULL);
197 // All sessions are active and not closed
198 EXPECT_TRUE(session1->is_active());
199 EXPECT_TRUE(session1->IsAvailable());
200 EXPECT_TRUE(session2->is_active());
201 EXPECT_TRUE(session2->IsAvailable());
202 EXPECT_TRUE(session3->is_active());
203 EXPECT_TRUE(session3->IsAvailable());
205 // Should not do anything, all are active
206 spdy_session_pool_->CloseCurrentIdleSessions();
207 EXPECT_TRUE(session1->is_active());
208 EXPECT_TRUE(session1->IsAvailable());
209 EXPECT_TRUE(session2->is_active());
210 EXPECT_TRUE(session2->IsAvailable());
211 EXPECT_TRUE(session3->is_active());
212 EXPECT_TRUE(session3->IsAvailable());
214 // Make sessions 1 and 3 inactive, but keep them open.
215 // Session 2 still open and active
216 session1->CloseCreatedStream(spdy_stream1, OK);
217 EXPECT_EQ(NULL, spdy_stream1.get());
218 session3->CloseCreatedStream(spdy_stream3, OK);
219 EXPECT_EQ(NULL, spdy_stream3.get());
220 EXPECT_FALSE(session1->is_active());
221 EXPECT_TRUE(session1->IsAvailable());
222 EXPECT_TRUE(session2->is_active());
223 EXPECT_TRUE(session2->IsAvailable());
224 EXPECT_FALSE(session3->is_active());
225 EXPECT_TRUE(session3->IsAvailable());
227 // Should close session 1 and 3, 2 should be left open
228 spdy_session_pool_->CloseCurrentIdleSessions();
229 base::MessageLoop::current()->RunUntilIdle();
231 EXPECT_TRUE(session1 == NULL);
232 EXPECT_TRUE(session2->is_active());
233 EXPECT_TRUE(session2->IsAvailable());
234 EXPECT_TRUE(session3 == NULL);
236 // Should not do anything
237 spdy_session_pool_->CloseCurrentIdleSessions();
238 base::MessageLoop::current()->RunUntilIdle();
240 EXPECT_TRUE(session2->is_active());
241 EXPECT_TRUE(session2->IsAvailable());
243 // Make 2 not active
244 session2->CloseCreatedStream(spdy_stream2, OK);
245 base::MessageLoop::current()->RunUntilIdle();
247 EXPECT_EQ(NULL, spdy_stream2.get());
248 EXPECT_FALSE(session2->is_active());
249 EXPECT_TRUE(session2->IsAvailable());
251 // This should close session 2
252 spdy_session_pool_->CloseCurrentIdleSessions();
253 base::MessageLoop::current()->RunUntilIdle();
255 EXPECT_TRUE(session2 == NULL);
258 // Set up a SpdyStream to create a new session when it is closed.
259 // CloseAllSessions should close the newly-created session.
260 TEST_P(SpdySessionPoolTest, CloseAllSessions) {
261 const char kTestHost[] = "www.foo.com";
262 const int kTestPort = 80;
264 session_deps_.host_resolver->set_synchronous_mode(true);
266 HostPortPair test_host_port_pair(kTestHost, kTestPort);
267 SpdySessionKey test_key =
268 SpdySessionKey(
269 test_host_port_pair, ProxyServer::Direct(),
270 PRIVACY_MODE_DISABLED);
272 MockConnect connect_data(SYNCHRONOUS, OK);
273 MockRead reads[] = {
274 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
277 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
278 data.set_connect_data(connect_data);
279 session_deps_.socket_factory->AddSocketDataProvider(&data);
281 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
282 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
284 CreateNetworkSession();
286 // Setup the first session to the first host.
287 base::WeakPtr<SpdySession> session =
288 CreateInsecureSpdySession(http_session_, test_key, BoundNetLog());
290 // Flush the SpdySession::OnReadComplete() task.
291 base::MessageLoop::current()->RunUntilIdle();
293 // Verify that we have sessions for everything.
294 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_key));
296 // Set the stream to create a new session when it is closed.
297 base::WeakPtr<SpdyStream> spdy_stream =
298 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
299 session, GURL("http://www.foo.com"),
300 MEDIUM, BoundNetLog());
301 SessionOpeningDelegate delegate(spdy_session_pool_, test_key);
302 spdy_stream->SetDelegate(&delegate);
304 // Close the current session.
305 spdy_session_pool_->CloseAllSessions();
307 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_key));
310 // This test has three variants, one for each style of closing the connection.
311 // If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_SESSIONS_MANUALLY,
312 // the sessions are closed manually, calling SpdySessionPool::Remove() directly.
313 // If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_CURRENT_SESSIONS,
314 // sessions are closed with SpdySessionPool::CloseCurrentSessions().
315 // If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_IDLE_SESSIONS,
316 // sessions are closed with SpdySessionPool::CloseIdleSessions().
317 void SpdySessionPoolTest::RunIPPoolingTest(
318 SpdyPoolCloseSessionsType close_sessions_type) {
319 const int kTestPort = 80;
320 struct TestHosts {
321 std::string url;
322 std::string name;
323 std::string iplist;
324 SpdySessionKey key;
325 AddressList addresses;
326 } test_hosts[] = {
327 { "http:://www.foo.com",
328 "www.foo.com",
329 "192.0.2.33,192.168.0.1,192.168.0.5"
331 { "http://js.foo.com",
332 "js.foo.com",
333 "192.168.0.2,192.168.0.3,192.168.0.5,192.0.2.33"
335 { "http://images.foo.com",
336 "images.foo.com",
337 "192.168.0.4,192.168.0.3"
341 session_deps_.host_resolver->set_synchronous_mode(true);
342 for (size_t i = 0; i < arraysize(test_hosts); i++) {
343 session_deps_.host_resolver->rules()->AddIPLiteralRule(
344 test_hosts[i].name, test_hosts[i].iplist, std::string());
346 // This test requires that the HostResolver cache be populated. Normal
347 // code would have done this already, but we do it manually.
348 HostResolver::RequestInfo info(HostPortPair(test_hosts[i].name, kTestPort));
349 session_deps_.host_resolver->Resolve(info,
350 DEFAULT_PRIORITY,
351 &test_hosts[i].addresses,
352 CompletionCallback(),
353 NULL,
354 BoundNetLog());
356 // Setup a SpdySessionKey
357 test_hosts[i].key = SpdySessionKey(
358 HostPortPair(test_hosts[i].name, kTestPort), ProxyServer::Direct(),
359 PRIVACY_MODE_DISABLED);
362 MockConnect connect_data(SYNCHRONOUS, OK);
363 MockRead reads[] = {
364 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
367 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
368 data.set_connect_data(connect_data);
369 session_deps_.socket_factory->AddSocketDataProvider(&data);
371 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
372 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
374 CreateNetworkSession();
376 // Setup the first session to the first host.
377 base::WeakPtr<SpdySession> session =
378 CreateInsecureSpdySession(
379 http_session_, test_hosts[0].key, BoundNetLog());
381 // Flush the SpdySession::OnReadComplete() task.
382 base::MessageLoop::current()->RunUntilIdle();
384 // The third host has no overlap with the first, so it can't pool IPs.
385 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[2].key));
387 // The second host overlaps with the first, and should IP pool.
388 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[1].key));
390 // Verify that the second host, through a proxy, won't share the IP.
391 SpdySessionKey proxy_key(test_hosts[1].key.host_port_pair(),
392 ProxyServer::FromPacString("HTTP http://proxy.foo.com/"),
393 PRIVACY_MODE_DISABLED);
394 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, proxy_key));
396 // Overlap between 2 and 3 does is not transitive to 1.
397 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[2].key));
399 // Create a new session to host 2.
400 session_deps_.socket_factory->AddSocketDataProvider(&data);
401 base::WeakPtr<SpdySession> session2 =
402 CreateInsecureSpdySession(
403 http_session_, test_hosts[2].key, BoundNetLog());
405 // Verify that we have sessions for everything.
406 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[0].key));
407 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[1].key));
408 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[2].key));
410 // Grab the session to host 1 and verify that it is the same session
411 // we got with host 0, and that is a different from host 2's session.
412 base::WeakPtr<SpdySession> session1 =
413 spdy_session_pool_->FindAvailableSession(
414 test_hosts[1].key, BoundNetLog());
415 EXPECT_EQ(session.get(), session1.get());
416 EXPECT_NE(session2.get(), session1.get());
418 // Remove the aliases and observe that we still have a session for host1.
419 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
420 pool_peer.RemoveAliases(test_hosts[0].key);
421 pool_peer.RemoveAliases(test_hosts[1].key);
422 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[1].key));
424 // Expire the host cache
425 session_deps_.host_resolver->GetHostCache()->clear();
426 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[1].key));
428 // Cleanup the sessions.
429 switch (close_sessions_type) {
430 case SPDY_POOL_CLOSE_SESSIONS_MANUALLY:
431 session->CloseSessionOnError(ERR_ABORTED, std::string());
432 session2->CloseSessionOnError(ERR_ABORTED, std::string());
433 base::MessageLoop::current()->RunUntilIdle();
434 EXPECT_TRUE(session == NULL);
435 EXPECT_TRUE(session2 == NULL);
436 break;
437 case SPDY_POOL_CLOSE_CURRENT_SESSIONS:
438 spdy_session_pool_->CloseCurrentSessions(ERR_ABORTED);
439 break;
440 case SPDY_POOL_CLOSE_IDLE_SESSIONS:
441 GURL url(test_hosts[0].url);
442 base::WeakPtr<SpdyStream> spdy_stream =
443 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
444 session, url, MEDIUM, BoundNetLog());
445 GURL url1(test_hosts[1].url);
446 base::WeakPtr<SpdyStream> spdy_stream1 =
447 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
448 session1, url1, MEDIUM, BoundNetLog());
449 GURL url2(test_hosts[2].url);
450 base::WeakPtr<SpdyStream> spdy_stream2 =
451 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
452 session2, url2, MEDIUM, BoundNetLog());
454 // Close streams to make spdy_session and spdy_session1 inactive.
455 session->CloseCreatedStream(spdy_stream, OK);
456 EXPECT_EQ(NULL, spdy_stream.get());
457 session1->CloseCreatedStream(spdy_stream1, OK);
458 EXPECT_EQ(NULL, spdy_stream1.get());
460 // Check spdy_session and spdy_session1 are not closed.
461 EXPECT_FALSE(session->is_active());
462 EXPECT_TRUE(session->IsAvailable());
463 EXPECT_FALSE(session1->is_active());
464 EXPECT_TRUE(session1->IsAvailable());
465 EXPECT_TRUE(session2->is_active());
466 EXPECT_TRUE(session2->IsAvailable());
468 // Test that calling CloseIdleSessions, does not cause a crash.
469 // http://crbug.com/181400
470 spdy_session_pool_->CloseCurrentIdleSessions();
471 base::MessageLoop::current()->RunUntilIdle();
473 // Verify spdy_session and spdy_session1 are closed.
474 EXPECT_TRUE(session == NULL);
475 EXPECT_TRUE(session1 == NULL);
476 EXPECT_TRUE(session2->is_active());
477 EXPECT_TRUE(session2->IsAvailable());
479 spdy_stream2->Cancel();
480 EXPECT_EQ(NULL, spdy_stream.get());
481 EXPECT_EQ(NULL, spdy_stream1.get());
482 EXPECT_EQ(NULL, spdy_stream2.get());
484 session2->CloseSessionOnError(ERR_ABORTED, std::string());
485 base::MessageLoop::current()->RunUntilIdle();
486 EXPECT_TRUE(session2 == NULL);
487 break;
490 // Verify that the map is all cleaned up.
491 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[0].key));
492 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[1].key));
493 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[2].key));
496 TEST_P(SpdySessionPoolTest, IPPooling) {
497 RunIPPoolingTest(SPDY_POOL_CLOSE_SESSIONS_MANUALLY);
500 TEST_P(SpdySessionPoolTest, IPPoolingCloseCurrentSessions) {
501 RunIPPoolingTest(SPDY_POOL_CLOSE_CURRENT_SESSIONS);
504 TEST_P(SpdySessionPoolTest, IPPoolingCloseIdleSessions) {
505 RunIPPoolingTest(SPDY_POOL_CLOSE_IDLE_SESSIONS);
508 // Construct a Pool with SpdySessions in various availability states. Simulate
509 // an IP address change. Ensure sessions gracefully shut down. Regression test
510 // for crbug.com/379469.
511 TEST_P(SpdySessionPoolTest, IPAddressChanged) {
512 MockConnect connect_data(SYNCHRONOUS, OK);
513 session_deps_.host_resolver->set_synchronous_mode(true);
514 SpdyTestUtil spdy_util(GetParam());
516 MockRead reads[] = {
517 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
519 scoped_ptr<SpdyFrame> req(
520 spdy_util.ConstructSpdyGet("http://www.a.com", false, 1, MEDIUM));
521 MockWrite writes[] = {CreateMockWrite(*req, 1)};
523 StaticSocketDataProvider data(reads, arraysize(reads), writes,
524 arraysize(writes));
525 data.set_connect_data(connect_data);
526 session_deps_.socket_factory->AddSocketDataProvider(&data);
528 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
529 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
531 CreateNetworkSession();
533 // Set up session A: Going away, but with an active stream.
534 session_deps_.socket_factory->AddSocketDataProvider(&data);
535 const std::string kTestHostA("http://www.a.com");
536 HostPortPair test_host_port_pairA(kTestHostA, 80);
537 SpdySessionKey keyA(
538 test_host_port_pairA, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
539 base::WeakPtr<SpdySession> sessionA =
540 CreateInsecureSpdySession(http_session_, keyA, BoundNetLog());
542 GURL urlA(kTestHostA);
543 base::WeakPtr<SpdyStream> spdy_streamA = CreateStreamSynchronously(
544 SPDY_BIDIRECTIONAL_STREAM, sessionA, urlA, MEDIUM, BoundNetLog());
545 test::StreamDelegateDoNothing delegateA(spdy_streamA);
546 spdy_streamA->SetDelegate(&delegateA);
548 scoped_ptr<SpdyHeaderBlock> headers(
549 spdy_util.ConstructGetHeaderBlock(urlA.spec()));
550 spdy_streamA->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
551 EXPECT_TRUE(spdy_streamA->HasUrlFromHeaders());
553 base::MessageLoop::current()->RunUntilIdle(); // Allow headers to write.
554 EXPECT_TRUE(delegateA.send_headers_completed());
556 sessionA->MakeUnavailable();
557 EXPECT_TRUE(sessionA->IsGoingAway());
558 EXPECT_FALSE(delegateA.StreamIsClosed());
560 // Set up session B: Available, with a created stream.
561 const std::string kTestHostB("http://www.b.com");
562 HostPortPair test_host_port_pairB(kTestHostB, 80);
563 SpdySessionKey keyB(
564 test_host_port_pairB, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
565 base::WeakPtr<SpdySession> sessionB =
566 CreateInsecureSpdySession(http_session_, keyB, BoundNetLog());
567 EXPECT_TRUE(sessionB->IsAvailable());
569 GURL urlB(kTestHostB);
570 base::WeakPtr<SpdyStream> spdy_streamB = CreateStreamSynchronously(
571 SPDY_BIDIRECTIONAL_STREAM, sessionB, urlB, MEDIUM, BoundNetLog());
572 test::StreamDelegateDoNothing delegateB(spdy_streamB);
573 spdy_streamB->SetDelegate(&delegateB);
575 // Set up session C: Draining.
576 session_deps_.socket_factory->AddSocketDataProvider(&data);
577 const std::string kTestHostC("http://www.c.com");
578 HostPortPair test_host_port_pairC(kTestHostC, 80);
579 SpdySessionKey keyC(
580 test_host_port_pairC, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
581 base::WeakPtr<SpdySession> sessionC =
582 CreateInsecureSpdySession(http_session_, keyC, BoundNetLog());
584 sessionC->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Error!");
585 EXPECT_TRUE(sessionC->IsDraining());
587 spdy_session_pool_->OnIPAddressChanged();
589 #if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
590 EXPECT_TRUE(sessionA->IsGoingAway());
591 EXPECT_TRUE(sessionB->IsDraining());
592 EXPECT_TRUE(sessionC->IsDraining());
594 EXPECT_EQ(1u,
595 sessionA->num_active_streams()); // Active stream is still active.
596 EXPECT_FALSE(delegateA.StreamIsClosed());
598 EXPECT_TRUE(delegateB.StreamIsClosed()); // Created stream was closed.
599 EXPECT_EQ(ERR_NETWORK_CHANGED, delegateB.WaitForClose());
601 sessionA->CloseSessionOnError(ERR_ABORTED, "Closing");
602 sessionB->CloseSessionOnError(ERR_ABORTED, "Closing");
604 EXPECT_TRUE(delegateA.StreamIsClosed());
605 EXPECT_EQ(ERR_ABORTED, delegateA.WaitForClose());
606 #else
607 EXPECT_TRUE(sessionA->IsDraining());
608 EXPECT_TRUE(sessionB->IsDraining());
609 EXPECT_TRUE(sessionC->IsDraining());
611 // Both streams were closed with an error.
612 EXPECT_TRUE(delegateA.StreamIsClosed());
613 EXPECT_EQ(ERR_NETWORK_CHANGED, delegateA.WaitForClose());
614 EXPECT_TRUE(delegateB.StreamIsClosed());
615 EXPECT_EQ(ERR_NETWORK_CHANGED, delegateB.WaitForClose());
616 #endif // defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
619 } // namespace
621 } // namespace net