Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / net / spdy / spdy_session_pool_unittest.cc
blobfccfadd58742d67355012f0f2902ac4949d8c3a3
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));
56 // A delegate that opens a new session when it is closed.
57 class SessionOpeningDelegate : public SpdyStream::Delegate {
58 public:
59 SessionOpeningDelegate(SpdySessionPool* spdy_session_pool,
60 const SpdySessionKey& key)
61 : spdy_session_pool_(spdy_session_pool),
62 key_(key) {}
64 ~SessionOpeningDelegate() override {}
66 void OnRequestHeadersSent() override {}
68 SpdyResponseHeadersStatus OnResponseHeadersUpdated(
69 const SpdyHeaderBlock& response_headers) override {
70 return RESPONSE_HEADERS_ARE_COMPLETE;
73 void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) override {}
75 void OnDataSent() override {}
77 void OnTrailers(const SpdyHeaderBlock& trailers) override {}
79 void OnClose(int status) override {
80 ignore_result(CreateFakeSpdySession(spdy_session_pool_, key_));
83 private:
84 SpdySessionPool* const spdy_session_pool_;
85 const SpdySessionKey key_;
88 // Set up a SpdyStream to create a new session when it is closed.
89 // CloseCurrentSessions should not close the newly-created session.
90 TEST_P(SpdySessionPoolTest, CloseCurrentSessions) {
91 const char kTestHost[] = "www.foo.com";
92 const int kTestPort = 80;
94 session_deps_.host_resolver->set_synchronous_mode(true);
96 HostPortPair test_host_port_pair(kTestHost, kTestPort);
97 SpdySessionKey test_key =
98 SpdySessionKey(
99 test_host_port_pair, ProxyServer::Direct(),
100 PRIVACY_MODE_DISABLED);
102 MockConnect connect_data(SYNCHRONOUS, OK);
103 MockRead reads[] = {
104 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
107 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
108 data.set_connect_data(connect_data);
109 session_deps_.socket_factory->AddSocketDataProvider(&data);
111 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
112 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
114 CreateNetworkSession();
116 // Setup the first session to the first host.
117 base::WeakPtr<SpdySession> session =
118 CreateInsecureSpdySession(http_session_, test_key, BoundNetLog());
120 // Flush the SpdySession::OnReadComplete() task.
121 base::MessageLoop::current()->RunUntilIdle();
123 // Verify that we have sessions for everything.
124 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_key));
126 // Set the stream to create a new session when it is closed.
127 base::WeakPtr<SpdyStream> spdy_stream =
128 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
129 session, GURL("http://www.foo.com"),
130 MEDIUM, BoundNetLog());
131 SessionOpeningDelegate delegate(spdy_session_pool_, test_key);
132 spdy_stream->SetDelegate(&delegate);
134 // Close the current session.
135 spdy_session_pool_->CloseCurrentSessions(ERR_ABORTED);
137 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_key));
140 TEST_P(SpdySessionPoolTest, CloseCurrentIdleSessions) {
141 MockConnect connect_data(SYNCHRONOUS, OK);
142 MockRead reads[] = {
143 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
146 session_deps_.host_resolver->set_synchronous_mode(true);
148 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
149 data.set_connect_data(connect_data);
150 session_deps_.socket_factory->AddSocketDataProvider(&data);
152 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
153 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
155 CreateNetworkSession();
157 // Set up session 1
158 const std::string kTestHost1("http://www.a.com");
159 HostPortPair test_host_port_pair1(kTestHost1, 80);
160 SpdySessionKey key1(test_host_port_pair1, ProxyServer::Direct(),
161 PRIVACY_MODE_DISABLED);
162 base::WeakPtr<SpdySession> session1 =
163 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
164 GURL url1(kTestHost1);
165 base::WeakPtr<SpdyStream> spdy_stream1 =
166 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
167 session1, url1, MEDIUM, BoundNetLog());
168 ASSERT_TRUE(spdy_stream1.get() != NULL);
170 // Set up session 2
171 session_deps_.socket_factory->AddSocketDataProvider(&data);
172 const std::string kTestHost2("http://www.b.com");
173 HostPortPair test_host_port_pair2(kTestHost2, 80);
174 SpdySessionKey key2(test_host_port_pair2, ProxyServer::Direct(),
175 PRIVACY_MODE_DISABLED);
176 base::WeakPtr<SpdySession> session2 =
177 CreateInsecureSpdySession(http_session_, key2, BoundNetLog());
178 GURL url2(kTestHost2);
179 base::WeakPtr<SpdyStream> spdy_stream2 =
180 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
181 session2, url2, MEDIUM, BoundNetLog());
182 ASSERT_TRUE(spdy_stream2.get() != NULL);
184 // Set up session 3
185 session_deps_.socket_factory->AddSocketDataProvider(&data);
186 const std::string kTestHost3("http://www.c.com");
187 HostPortPair test_host_port_pair3(kTestHost3, 80);
188 SpdySessionKey key3(test_host_port_pair3, ProxyServer::Direct(),
189 PRIVACY_MODE_DISABLED);
190 base::WeakPtr<SpdySession> session3 =
191 CreateInsecureSpdySession(http_session_, key3, BoundNetLog());
192 GURL url3(kTestHost3);
193 base::WeakPtr<SpdyStream> spdy_stream3 =
194 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
195 session3, url3, MEDIUM, BoundNetLog());
196 ASSERT_TRUE(spdy_stream3.get() != NULL);
198 // All sessions are active and not closed
199 EXPECT_TRUE(session1->is_active());
200 EXPECT_TRUE(session1->IsAvailable());
201 EXPECT_TRUE(session2->is_active());
202 EXPECT_TRUE(session2->IsAvailable());
203 EXPECT_TRUE(session3->is_active());
204 EXPECT_TRUE(session3->IsAvailable());
206 // Should not do anything, all are active
207 spdy_session_pool_->CloseCurrentIdleSessions();
208 EXPECT_TRUE(session1->is_active());
209 EXPECT_TRUE(session1->IsAvailable());
210 EXPECT_TRUE(session2->is_active());
211 EXPECT_TRUE(session2->IsAvailable());
212 EXPECT_TRUE(session3->is_active());
213 EXPECT_TRUE(session3->IsAvailable());
215 // Make sessions 1 and 3 inactive, but keep them open.
216 // Session 2 still open and active
217 session1->CloseCreatedStream(spdy_stream1, OK);
218 EXPECT_EQ(NULL, spdy_stream1.get());
219 session3->CloseCreatedStream(spdy_stream3, OK);
220 EXPECT_EQ(NULL, spdy_stream3.get());
221 EXPECT_FALSE(session1->is_active());
222 EXPECT_TRUE(session1->IsAvailable());
223 EXPECT_TRUE(session2->is_active());
224 EXPECT_TRUE(session2->IsAvailable());
225 EXPECT_FALSE(session3->is_active());
226 EXPECT_TRUE(session3->IsAvailable());
228 // Should close session 1 and 3, 2 should be left open
229 spdy_session_pool_->CloseCurrentIdleSessions();
230 base::MessageLoop::current()->RunUntilIdle();
232 EXPECT_TRUE(session1 == NULL);
233 EXPECT_TRUE(session2->is_active());
234 EXPECT_TRUE(session2->IsAvailable());
235 EXPECT_TRUE(session3 == NULL);
237 // Should not do anything
238 spdy_session_pool_->CloseCurrentIdleSessions();
239 base::MessageLoop::current()->RunUntilIdle();
241 EXPECT_TRUE(session2->is_active());
242 EXPECT_TRUE(session2->IsAvailable());
244 // Make 2 not active
245 session2->CloseCreatedStream(spdy_stream2, OK);
246 base::MessageLoop::current()->RunUntilIdle();
248 EXPECT_EQ(NULL, spdy_stream2.get());
249 EXPECT_FALSE(session2->is_active());
250 EXPECT_TRUE(session2->IsAvailable());
252 // This should close session 2
253 spdy_session_pool_->CloseCurrentIdleSessions();
254 base::MessageLoop::current()->RunUntilIdle();
256 EXPECT_TRUE(session2 == NULL);
259 // Set up a SpdyStream to create a new session when it is closed.
260 // CloseAllSessions should close the newly-created session.
261 TEST_P(SpdySessionPoolTest, CloseAllSessions) {
262 const char kTestHost[] = "www.foo.com";
263 const int kTestPort = 80;
265 session_deps_.host_resolver->set_synchronous_mode(true);
267 HostPortPair test_host_port_pair(kTestHost, kTestPort);
268 SpdySessionKey test_key =
269 SpdySessionKey(
270 test_host_port_pair, ProxyServer::Direct(),
271 PRIVACY_MODE_DISABLED);
273 MockConnect connect_data(SYNCHRONOUS, OK);
274 MockRead reads[] = {
275 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
278 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
279 data.set_connect_data(connect_data);
280 session_deps_.socket_factory->AddSocketDataProvider(&data);
282 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
283 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
285 CreateNetworkSession();
287 // Setup the first session to the first host.
288 base::WeakPtr<SpdySession> session =
289 CreateInsecureSpdySession(http_session_, test_key, BoundNetLog());
291 // Flush the SpdySession::OnReadComplete() task.
292 base::MessageLoop::current()->RunUntilIdle();
294 // Verify that we have sessions for everything.
295 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_key));
297 // Set the stream to create a new session when it is closed.
298 base::WeakPtr<SpdyStream> spdy_stream =
299 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
300 session, GURL("http://www.foo.com"),
301 MEDIUM, BoundNetLog());
302 SessionOpeningDelegate delegate(spdy_session_pool_, test_key);
303 spdy_stream->SetDelegate(&delegate);
305 // Close the current session.
306 spdy_session_pool_->CloseAllSessions();
308 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_key));
311 // This test has three variants, one for each style of closing the connection.
312 // If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_SESSIONS_MANUALLY,
313 // the sessions are closed manually, calling SpdySessionPool::Remove() directly.
314 // If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_CURRENT_SESSIONS,
315 // sessions are closed with SpdySessionPool::CloseCurrentSessions().
316 // If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_IDLE_SESSIONS,
317 // sessions are closed with SpdySessionPool::CloseIdleSessions().
318 void SpdySessionPoolTest::RunIPPoolingTest(
319 SpdyPoolCloseSessionsType close_sessions_type) {
320 const int kTestPort = 80;
321 struct TestHosts {
322 std::string url;
323 std::string name;
324 std::string iplist;
325 SpdySessionKey key;
326 AddressList addresses;
327 } test_hosts[] = {
328 { "http:://www.foo.com",
329 "www.foo.com",
330 "192.0.2.33,192.168.0.1,192.168.0.5"
332 { "http://js.foo.com",
333 "js.foo.com",
334 "192.168.0.2,192.168.0.3,192.168.0.5,192.0.2.33"
336 { "http://images.foo.com",
337 "images.foo.com",
338 "192.168.0.4,192.168.0.3"
342 session_deps_.host_resolver->set_synchronous_mode(true);
343 for (size_t i = 0; i < arraysize(test_hosts); i++) {
344 session_deps_.host_resolver->rules()->AddIPLiteralRule(
345 test_hosts[i].name, test_hosts[i].iplist, std::string());
347 // This test requires that the HostResolver cache be populated. Normal
348 // code would have done this already, but we do it manually.
349 HostResolver::RequestInfo info(HostPortPair(test_hosts[i].name, kTestPort));
350 session_deps_.host_resolver->Resolve(info,
351 DEFAULT_PRIORITY,
352 &test_hosts[i].addresses,
353 CompletionCallback(),
354 NULL,
355 BoundNetLog());
357 // Setup a SpdySessionKey
358 test_hosts[i].key = SpdySessionKey(
359 HostPortPair(test_hosts[i].name, kTestPort), ProxyServer::Direct(),
360 PRIVACY_MODE_DISABLED);
363 MockConnect connect_data(SYNCHRONOUS, OK);
364 MockRead reads[] = {
365 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
368 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
369 data.set_connect_data(connect_data);
370 session_deps_.socket_factory->AddSocketDataProvider(&data);
372 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
373 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
375 CreateNetworkSession();
377 // Setup the first session to the first host.
378 base::WeakPtr<SpdySession> session =
379 CreateInsecureSpdySession(
380 http_session_, test_hosts[0].key, BoundNetLog());
382 // Flush the SpdySession::OnReadComplete() task.
383 base::MessageLoop::current()->RunUntilIdle();
385 // The third host has no overlap with the first, so it can't pool IPs.
386 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[2].key));
388 // The second host overlaps with the first, and should IP pool.
389 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[1].key));
391 // Verify that the second host, through a proxy, won't share the IP.
392 SpdySessionKey proxy_key(test_hosts[1].key.host_port_pair(),
393 ProxyServer::FromPacString("HTTP http://proxy.foo.com/"),
394 PRIVACY_MODE_DISABLED);
395 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, proxy_key));
397 // Overlap between 2 and 3 does is not transitive to 1.
398 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[2].key));
400 // Create a new session to host 2.
401 session_deps_.socket_factory->AddSocketDataProvider(&data);
402 base::WeakPtr<SpdySession> session2 =
403 CreateInsecureSpdySession(
404 http_session_, test_hosts[2].key, BoundNetLog());
406 // Verify that we have sessions for everything.
407 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[0].key));
408 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[1].key));
409 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[2].key));
411 // Grab the session to host 1 and verify that it is the same session
412 // we got with host 0, and that is a different from host 2's session.
413 base::WeakPtr<SpdySession> session1 =
414 spdy_session_pool_->FindAvailableSession(
415 test_hosts[1].key, BoundNetLog());
416 EXPECT_EQ(session.get(), session1.get());
417 EXPECT_NE(session2.get(), session1.get());
419 // Remove the aliases and observe that we still have a session for host1.
420 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
421 pool_peer.RemoveAliases(test_hosts[0].key);
422 pool_peer.RemoveAliases(test_hosts[1].key);
423 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[1].key));
425 // Expire the host cache
426 session_deps_.host_resolver->GetHostCache()->clear();
427 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[1].key));
429 // Cleanup the sessions.
430 switch (close_sessions_type) {
431 case SPDY_POOL_CLOSE_SESSIONS_MANUALLY:
432 session->CloseSessionOnError(ERR_ABORTED, std::string());
433 session2->CloseSessionOnError(ERR_ABORTED, std::string());
434 base::MessageLoop::current()->RunUntilIdle();
435 EXPECT_TRUE(session == NULL);
436 EXPECT_TRUE(session2 == NULL);
437 break;
438 case SPDY_POOL_CLOSE_CURRENT_SESSIONS:
439 spdy_session_pool_->CloseCurrentSessions(ERR_ABORTED);
440 break;
441 case SPDY_POOL_CLOSE_IDLE_SESSIONS:
442 GURL url(test_hosts[0].url);
443 base::WeakPtr<SpdyStream> spdy_stream =
444 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
445 session, url, MEDIUM, BoundNetLog());
446 GURL url1(test_hosts[1].url);
447 base::WeakPtr<SpdyStream> spdy_stream1 =
448 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
449 session1, url1, MEDIUM, BoundNetLog());
450 GURL url2(test_hosts[2].url);
451 base::WeakPtr<SpdyStream> spdy_stream2 =
452 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
453 session2, url2, MEDIUM, BoundNetLog());
455 // Close streams to make spdy_session and spdy_session1 inactive.
456 session->CloseCreatedStream(spdy_stream, OK);
457 EXPECT_EQ(NULL, spdy_stream.get());
458 session1->CloseCreatedStream(spdy_stream1, OK);
459 EXPECT_EQ(NULL, spdy_stream1.get());
461 // Check spdy_session and spdy_session1 are not closed.
462 EXPECT_FALSE(session->is_active());
463 EXPECT_TRUE(session->IsAvailable());
464 EXPECT_FALSE(session1->is_active());
465 EXPECT_TRUE(session1->IsAvailable());
466 EXPECT_TRUE(session2->is_active());
467 EXPECT_TRUE(session2->IsAvailable());
469 // Test that calling CloseIdleSessions, does not cause a crash.
470 // http://crbug.com/181400
471 spdy_session_pool_->CloseCurrentIdleSessions();
472 base::MessageLoop::current()->RunUntilIdle();
474 // Verify spdy_session and spdy_session1 are closed.
475 EXPECT_TRUE(session == NULL);
476 EXPECT_TRUE(session1 == NULL);
477 EXPECT_TRUE(session2->is_active());
478 EXPECT_TRUE(session2->IsAvailable());
480 spdy_stream2->Cancel();
481 EXPECT_EQ(NULL, spdy_stream.get());
482 EXPECT_EQ(NULL, spdy_stream1.get());
483 EXPECT_EQ(NULL, spdy_stream2.get());
485 session2->CloseSessionOnError(ERR_ABORTED, std::string());
486 base::MessageLoop::current()->RunUntilIdle();
487 EXPECT_TRUE(session2 == NULL);
488 break;
491 // Verify that the map is all cleaned up.
492 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[0].key));
493 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[1].key));
494 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[2].key));
497 TEST_P(SpdySessionPoolTest, IPPooling) {
498 RunIPPoolingTest(SPDY_POOL_CLOSE_SESSIONS_MANUALLY);
501 TEST_P(SpdySessionPoolTest, IPPoolingCloseCurrentSessions) {
502 RunIPPoolingTest(SPDY_POOL_CLOSE_CURRENT_SESSIONS);
505 TEST_P(SpdySessionPoolTest, IPPoolingCloseIdleSessions) {
506 RunIPPoolingTest(SPDY_POOL_CLOSE_IDLE_SESSIONS);
509 // Construct a Pool with SpdySessions in various availability states. Simulate
510 // an IP address change. Ensure sessions gracefully shut down. Regression test
511 // for crbug.com/379469.
512 TEST_P(SpdySessionPoolTest, IPAddressChanged) {
513 MockConnect connect_data(SYNCHRONOUS, OK);
514 session_deps_.host_resolver->set_synchronous_mode(true);
515 SpdyTestUtil spdy_util(GetParam());
517 MockRead reads[] = {
518 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
520 scoped_ptr<SpdyFrame> req(
521 spdy_util.ConstructSpdyGet("http://www.a.com", false, 1, MEDIUM));
522 MockWrite writes[] = {CreateMockWrite(*req, 1)};
524 StaticSocketDataProvider data(reads, arraysize(reads), writes,
525 arraysize(writes));
526 data.set_connect_data(connect_data);
527 session_deps_.socket_factory->AddSocketDataProvider(&data);
529 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
530 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
532 CreateNetworkSession();
534 // Set up session A: Going away, but with an active stream.
535 session_deps_.socket_factory->AddSocketDataProvider(&data);
536 const std::string kTestHostA("http://www.a.com");
537 HostPortPair test_host_port_pairA(kTestHostA, 80);
538 SpdySessionKey keyA(
539 test_host_port_pairA, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
540 base::WeakPtr<SpdySession> sessionA =
541 CreateInsecureSpdySession(http_session_, keyA, BoundNetLog());
543 GURL urlA(kTestHostA);
544 base::WeakPtr<SpdyStream> spdy_streamA = CreateStreamSynchronously(
545 SPDY_BIDIRECTIONAL_STREAM, sessionA, urlA, MEDIUM, BoundNetLog());
546 test::StreamDelegateDoNothing delegateA(spdy_streamA);
547 spdy_streamA->SetDelegate(&delegateA);
549 scoped_ptr<SpdyHeaderBlock> headers(
550 spdy_util.ConstructGetHeaderBlock(urlA.spec()));
551 spdy_streamA->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
552 EXPECT_TRUE(spdy_streamA->HasUrlFromHeaders());
554 base::MessageLoop::current()->RunUntilIdle(); // Allow headers to write.
555 EXPECT_TRUE(delegateA.send_headers_completed());
557 sessionA->MakeUnavailable();
558 EXPECT_TRUE(sessionA->IsGoingAway());
559 EXPECT_FALSE(delegateA.StreamIsClosed());
561 // Set up session B: Available, with a created stream.
562 const std::string kTestHostB("http://www.b.com");
563 HostPortPair test_host_port_pairB(kTestHostB, 80);
564 SpdySessionKey keyB(
565 test_host_port_pairB, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
566 base::WeakPtr<SpdySession> sessionB =
567 CreateInsecureSpdySession(http_session_, keyB, BoundNetLog());
568 EXPECT_TRUE(sessionB->IsAvailable());
570 GURL urlB(kTestHostB);
571 base::WeakPtr<SpdyStream> spdy_streamB = CreateStreamSynchronously(
572 SPDY_BIDIRECTIONAL_STREAM, sessionB, urlB, MEDIUM, BoundNetLog());
573 test::StreamDelegateDoNothing delegateB(spdy_streamB);
574 spdy_streamB->SetDelegate(&delegateB);
576 // Set up session C: Draining.
577 session_deps_.socket_factory->AddSocketDataProvider(&data);
578 const std::string kTestHostC("http://www.c.com");
579 HostPortPair test_host_port_pairC(kTestHostC, 80);
580 SpdySessionKey keyC(
581 test_host_port_pairC, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
582 base::WeakPtr<SpdySession> sessionC =
583 CreateInsecureSpdySession(http_session_, keyC, BoundNetLog());
585 sessionC->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Error!");
586 EXPECT_TRUE(sessionC->IsDraining());
588 spdy_session_pool_->OnIPAddressChanged();
590 #if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
591 EXPECT_TRUE(sessionA->IsGoingAway());
592 EXPECT_TRUE(sessionB->IsDraining());
593 EXPECT_TRUE(sessionC->IsDraining());
595 EXPECT_EQ(1u,
596 sessionA->num_active_streams()); // Active stream is still active.
597 EXPECT_FALSE(delegateA.StreamIsClosed());
599 EXPECT_TRUE(delegateB.StreamIsClosed()); // Created stream was closed.
600 EXPECT_EQ(ERR_NETWORK_CHANGED, delegateB.WaitForClose());
602 sessionA->CloseSessionOnError(ERR_ABORTED, "Closing");
603 sessionB->CloseSessionOnError(ERR_ABORTED, "Closing");
605 EXPECT_TRUE(delegateA.StreamIsClosed());
606 EXPECT_EQ(ERR_ABORTED, delegateA.WaitForClose());
607 #else
608 EXPECT_TRUE(sessionA->IsDraining());
609 EXPECT_TRUE(sessionB->IsDraining());
610 EXPECT_TRUE(sessionC->IsDraining());
612 // Both streams were closed with an error.
613 EXPECT_TRUE(delegateA.StreamIsClosed());
614 EXPECT_EQ(ERR_NETWORK_CHANGED, delegateA.WaitForClose());
615 EXPECT_TRUE(delegateB.StreamIsClosed());
616 EXPECT_EQ(ERR_NETWORK_CHANGED, delegateB.WaitForClose());
617 #endif // defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
620 } // namespace
622 } // namespace net