ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / net / spdy / spdy_session_pool_unittest.cc
blob9d5e48c7449ee755efa51b1ede55f6169f0e82ab
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(
52 NextProto,
53 SpdySessionPoolTest,
54 testing::Values(kProtoSPDY31, kProtoSPDY4_14, kProtoSPDY4_15));
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 OnClose(int status) override {
78 ignore_result(CreateFakeSpdySession(spdy_session_pool_, key_));
81 private:
82 SpdySessionPool* const spdy_session_pool_;
83 const SpdySessionKey key_;
86 // Set up a SpdyStream to create a new session when it is closed.
87 // CloseCurrentSessions should not close the newly-created session.
88 TEST_P(SpdySessionPoolTest, CloseCurrentSessions) {
89 const char kTestHost[] = "www.foo.com";
90 const int kTestPort = 80;
92 session_deps_.host_resolver->set_synchronous_mode(true);
94 HostPortPair test_host_port_pair(kTestHost, kTestPort);
95 SpdySessionKey test_key =
96 SpdySessionKey(
97 test_host_port_pair, ProxyServer::Direct(),
98 PRIVACY_MODE_DISABLED);
100 MockConnect connect_data(SYNCHRONOUS, OK);
101 MockRead reads[] = {
102 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
105 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
106 data.set_connect_data(connect_data);
107 session_deps_.socket_factory->AddSocketDataProvider(&data);
109 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
110 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
112 CreateNetworkSession();
114 // Setup the first session to the first host.
115 base::WeakPtr<SpdySession> session =
116 CreateInsecureSpdySession(http_session_, test_key, BoundNetLog());
118 // Flush the SpdySession::OnReadComplete() task.
119 base::MessageLoop::current()->RunUntilIdle();
121 // Verify that we have sessions for everything.
122 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_key));
124 // Set the stream to create a new session when it is closed.
125 base::WeakPtr<SpdyStream> spdy_stream =
126 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
127 session, GURL("http://www.foo.com"),
128 MEDIUM, BoundNetLog());
129 SessionOpeningDelegate delegate(spdy_session_pool_, test_key);
130 spdy_stream->SetDelegate(&delegate);
132 // Close the current session.
133 spdy_session_pool_->CloseCurrentSessions(net::ERR_ABORTED);
135 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_key));
138 TEST_P(SpdySessionPoolTest, CloseCurrentIdleSessions) {
139 MockConnect connect_data(SYNCHRONOUS, OK);
140 MockRead reads[] = {
141 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
144 session_deps_.host_resolver->set_synchronous_mode(true);
146 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
147 data.set_connect_data(connect_data);
148 session_deps_.socket_factory->AddSocketDataProvider(&data);
150 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
151 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
153 CreateNetworkSession();
155 // Set up session 1
156 const std::string kTestHost1("http://www.a.com");
157 HostPortPair test_host_port_pair1(kTestHost1, 80);
158 SpdySessionKey key1(test_host_port_pair1, ProxyServer::Direct(),
159 PRIVACY_MODE_DISABLED);
160 base::WeakPtr<SpdySession> session1 =
161 CreateInsecureSpdySession(http_session_, key1, BoundNetLog());
162 GURL url1(kTestHost1);
163 base::WeakPtr<SpdyStream> spdy_stream1 =
164 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
165 session1, url1, MEDIUM, BoundNetLog());
166 ASSERT_TRUE(spdy_stream1.get() != NULL);
168 // Set up session 2
169 session_deps_.socket_factory->AddSocketDataProvider(&data);
170 const std::string kTestHost2("http://www.b.com");
171 HostPortPair test_host_port_pair2(kTestHost2, 80);
172 SpdySessionKey key2(test_host_port_pair2, ProxyServer::Direct(),
173 PRIVACY_MODE_DISABLED);
174 base::WeakPtr<SpdySession> session2 =
175 CreateInsecureSpdySession(http_session_, key2, BoundNetLog());
176 GURL url2(kTestHost2);
177 base::WeakPtr<SpdyStream> spdy_stream2 =
178 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
179 session2, url2, MEDIUM, BoundNetLog());
180 ASSERT_TRUE(spdy_stream2.get() != NULL);
182 // Set up session 3
183 session_deps_.socket_factory->AddSocketDataProvider(&data);
184 const std::string kTestHost3("http://www.c.com");
185 HostPortPair test_host_port_pair3(kTestHost3, 80);
186 SpdySessionKey key3(test_host_port_pair3, ProxyServer::Direct(),
187 PRIVACY_MODE_DISABLED);
188 base::WeakPtr<SpdySession> session3 =
189 CreateInsecureSpdySession(http_session_, key3, BoundNetLog());
190 GURL url3(kTestHost3);
191 base::WeakPtr<SpdyStream> spdy_stream3 =
192 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
193 session3, url3, MEDIUM, BoundNetLog());
194 ASSERT_TRUE(spdy_stream3.get() != NULL);
196 // All sessions are active and not closed
197 EXPECT_TRUE(session1->is_active());
198 EXPECT_TRUE(session1->IsAvailable());
199 EXPECT_TRUE(session2->is_active());
200 EXPECT_TRUE(session2->IsAvailable());
201 EXPECT_TRUE(session3->is_active());
202 EXPECT_TRUE(session3->IsAvailable());
204 // Should not do anything, all are active
205 spdy_session_pool_->CloseCurrentIdleSessions();
206 EXPECT_TRUE(session1->is_active());
207 EXPECT_TRUE(session1->IsAvailable());
208 EXPECT_TRUE(session2->is_active());
209 EXPECT_TRUE(session2->IsAvailable());
210 EXPECT_TRUE(session3->is_active());
211 EXPECT_TRUE(session3->IsAvailable());
213 // Make sessions 1 and 3 inactive, but keep them open.
214 // Session 2 still open and active
215 session1->CloseCreatedStream(spdy_stream1, OK);
216 EXPECT_EQ(NULL, spdy_stream1.get());
217 session3->CloseCreatedStream(spdy_stream3, OK);
218 EXPECT_EQ(NULL, spdy_stream3.get());
219 EXPECT_FALSE(session1->is_active());
220 EXPECT_TRUE(session1->IsAvailable());
221 EXPECT_TRUE(session2->is_active());
222 EXPECT_TRUE(session2->IsAvailable());
223 EXPECT_FALSE(session3->is_active());
224 EXPECT_TRUE(session3->IsAvailable());
226 // Should close session 1 and 3, 2 should be left open
227 spdy_session_pool_->CloseCurrentIdleSessions();
228 base::MessageLoop::current()->RunUntilIdle();
230 EXPECT_TRUE(session1 == NULL);
231 EXPECT_TRUE(session2->is_active());
232 EXPECT_TRUE(session2->IsAvailable());
233 EXPECT_TRUE(session3 == NULL);
235 // Should not do anything
236 spdy_session_pool_->CloseCurrentIdleSessions();
237 base::MessageLoop::current()->RunUntilIdle();
239 EXPECT_TRUE(session2->is_active());
240 EXPECT_TRUE(session2->IsAvailable());
242 // Make 2 not active
243 session2->CloseCreatedStream(spdy_stream2, OK);
244 base::MessageLoop::current()->RunUntilIdle();
246 EXPECT_EQ(NULL, spdy_stream2.get());
247 EXPECT_FALSE(session2->is_active());
248 EXPECT_TRUE(session2->IsAvailable());
250 // This should close session 2
251 spdy_session_pool_->CloseCurrentIdleSessions();
252 base::MessageLoop::current()->RunUntilIdle();
254 EXPECT_TRUE(session2 == NULL);
257 // Set up a SpdyStream to create a new session when it is closed.
258 // CloseAllSessions should close the newly-created session.
259 TEST_P(SpdySessionPoolTest, CloseAllSessions) {
260 const char kTestHost[] = "www.foo.com";
261 const int kTestPort = 80;
263 session_deps_.host_resolver->set_synchronous_mode(true);
265 HostPortPair test_host_port_pair(kTestHost, kTestPort);
266 SpdySessionKey test_key =
267 SpdySessionKey(
268 test_host_port_pair, ProxyServer::Direct(),
269 PRIVACY_MODE_DISABLED);
271 MockConnect connect_data(SYNCHRONOUS, OK);
272 MockRead reads[] = {
273 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
276 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
277 data.set_connect_data(connect_data);
278 session_deps_.socket_factory->AddSocketDataProvider(&data);
280 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
281 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
283 CreateNetworkSession();
285 // Setup the first session to the first host.
286 base::WeakPtr<SpdySession> session =
287 CreateInsecureSpdySession(http_session_, test_key, BoundNetLog());
289 // Flush the SpdySession::OnReadComplete() task.
290 base::MessageLoop::current()->RunUntilIdle();
292 // Verify that we have sessions for everything.
293 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_key));
295 // Set the stream to create a new session when it is closed.
296 base::WeakPtr<SpdyStream> spdy_stream =
297 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
298 session, GURL("http://www.foo.com"),
299 MEDIUM, BoundNetLog());
300 SessionOpeningDelegate delegate(spdy_session_pool_, test_key);
301 spdy_stream->SetDelegate(&delegate);
303 // Close the current session.
304 spdy_session_pool_->CloseAllSessions();
306 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_key));
309 // This test has three variants, one for each style of closing the connection.
310 // If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_SESSIONS_MANUALLY,
311 // the sessions are closed manually, calling SpdySessionPool::Remove() directly.
312 // If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_CURRENT_SESSIONS,
313 // sessions are closed with SpdySessionPool::CloseCurrentSessions().
314 // If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_IDLE_SESSIONS,
315 // sessions are closed with SpdySessionPool::CloseIdleSessions().
316 void SpdySessionPoolTest::RunIPPoolingTest(
317 SpdyPoolCloseSessionsType close_sessions_type) {
318 const int kTestPort = 80;
319 struct TestHosts {
320 std::string url;
321 std::string name;
322 std::string iplist;
323 SpdySessionKey key;
324 AddressList addresses;
325 } test_hosts[] = {
326 { "http:://www.foo.com",
327 "www.foo.com",
328 "192.0.2.33,192.168.0.1,192.168.0.5"
330 { "http://js.foo.com",
331 "js.foo.com",
332 "192.168.0.2,192.168.0.3,192.168.0.5,192.0.2.33"
334 { "http://images.foo.com",
335 "images.foo.com",
336 "192.168.0.4,192.168.0.3"
340 session_deps_.host_resolver->set_synchronous_mode(true);
341 for (size_t i = 0; i < arraysize(test_hosts); i++) {
342 session_deps_.host_resolver->rules()->AddIPLiteralRule(
343 test_hosts[i].name, test_hosts[i].iplist, std::string());
345 // This test requires that the HostResolver cache be populated. Normal
346 // code would have done this already, but we do it manually.
347 HostResolver::RequestInfo info(HostPortPair(test_hosts[i].name, kTestPort));
348 session_deps_.host_resolver->Resolve(info,
349 DEFAULT_PRIORITY,
350 &test_hosts[i].addresses,
351 CompletionCallback(),
352 NULL,
353 BoundNetLog());
355 // Setup a SpdySessionKey
356 test_hosts[i].key = SpdySessionKey(
357 HostPortPair(test_hosts[i].name, kTestPort), ProxyServer::Direct(),
358 PRIVACY_MODE_DISABLED);
361 MockConnect connect_data(SYNCHRONOUS, OK);
362 MockRead reads[] = {
363 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
366 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
367 data.set_connect_data(connect_data);
368 session_deps_.socket_factory->AddSocketDataProvider(&data);
370 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
371 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
373 CreateNetworkSession();
375 // Setup the first session to the first host.
376 base::WeakPtr<SpdySession> session =
377 CreateInsecureSpdySession(
378 http_session_, test_hosts[0].key, BoundNetLog());
380 // Flush the SpdySession::OnReadComplete() task.
381 base::MessageLoop::current()->RunUntilIdle();
383 // The third host has no overlap with the first, so it can't pool IPs.
384 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[2].key));
386 // The second host overlaps with the first, and should IP pool.
387 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[1].key));
389 // Verify that the second host, through a proxy, won't share the IP.
390 SpdySessionKey proxy_key(test_hosts[1].key.host_port_pair(),
391 ProxyServer::FromPacString("HTTP http://proxy.foo.com/"),
392 PRIVACY_MODE_DISABLED);
393 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, proxy_key));
395 // Overlap between 2 and 3 does is not transitive to 1.
396 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[2].key));
398 // Create a new session to host 2.
399 session_deps_.socket_factory->AddSocketDataProvider(&data);
400 base::WeakPtr<SpdySession> session2 =
401 CreateInsecureSpdySession(
402 http_session_, test_hosts[2].key, BoundNetLog());
404 // Verify that we have sessions for everything.
405 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[0].key));
406 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[1].key));
407 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[2].key));
409 // Grab the session to host 1 and verify that it is the same session
410 // we got with host 0, and that is a different from host 2's session.
411 base::WeakPtr<SpdySession> session1 =
412 spdy_session_pool_->FindAvailableSession(
413 test_hosts[1].key, BoundNetLog());
414 EXPECT_EQ(session.get(), session1.get());
415 EXPECT_NE(session2.get(), session1.get());
417 // Remove the aliases and observe that we still have a session for host1.
418 SpdySessionPoolPeer pool_peer(spdy_session_pool_);
419 pool_peer.RemoveAliases(test_hosts[0].key);
420 pool_peer.RemoveAliases(test_hosts[1].key);
421 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[1].key));
423 // Expire the host cache
424 session_deps_.host_resolver->GetHostCache()->clear();
425 EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[1].key));
427 // Cleanup the sessions.
428 switch (close_sessions_type) {
429 case SPDY_POOL_CLOSE_SESSIONS_MANUALLY:
430 session->CloseSessionOnError(ERR_ABORTED, std::string());
431 session2->CloseSessionOnError(ERR_ABORTED, std::string());
432 base::MessageLoop::current()->RunUntilIdle();
433 EXPECT_TRUE(session == NULL);
434 EXPECT_TRUE(session2 == NULL);
435 break;
436 case SPDY_POOL_CLOSE_CURRENT_SESSIONS:
437 spdy_session_pool_->CloseCurrentSessions(ERR_ABORTED);
438 break;
439 case SPDY_POOL_CLOSE_IDLE_SESSIONS:
440 GURL url(test_hosts[0].url);
441 base::WeakPtr<SpdyStream> spdy_stream =
442 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
443 session, url, MEDIUM, BoundNetLog());
444 GURL url1(test_hosts[1].url);
445 base::WeakPtr<SpdyStream> spdy_stream1 =
446 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
447 session1, url1, MEDIUM, BoundNetLog());
448 GURL url2(test_hosts[2].url);
449 base::WeakPtr<SpdyStream> spdy_stream2 =
450 CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM,
451 session2, url2, MEDIUM, BoundNetLog());
453 // Close streams to make spdy_session and spdy_session1 inactive.
454 session->CloseCreatedStream(spdy_stream, OK);
455 EXPECT_EQ(NULL, spdy_stream.get());
456 session1->CloseCreatedStream(spdy_stream1, OK);
457 EXPECT_EQ(NULL, spdy_stream1.get());
459 // Check spdy_session and spdy_session1 are not closed.
460 EXPECT_FALSE(session->is_active());
461 EXPECT_TRUE(session->IsAvailable());
462 EXPECT_FALSE(session1->is_active());
463 EXPECT_TRUE(session1->IsAvailable());
464 EXPECT_TRUE(session2->is_active());
465 EXPECT_TRUE(session2->IsAvailable());
467 // Test that calling CloseIdleSessions, does not cause a crash.
468 // http://crbug.com/181400
469 spdy_session_pool_->CloseCurrentIdleSessions();
470 base::MessageLoop::current()->RunUntilIdle();
472 // Verify spdy_session and spdy_session1 are closed.
473 EXPECT_TRUE(session == NULL);
474 EXPECT_TRUE(session1 == NULL);
475 EXPECT_TRUE(session2->is_active());
476 EXPECT_TRUE(session2->IsAvailable());
478 spdy_stream2->Cancel();
479 EXPECT_EQ(NULL, spdy_stream.get());
480 EXPECT_EQ(NULL, spdy_stream1.get());
481 EXPECT_EQ(NULL, spdy_stream2.get());
483 session2->CloseSessionOnError(ERR_ABORTED, std::string());
484 base::MessageLoop::current()->RunUntilIdle();
485 EXPECT_TRUE(session2 == NULL);
486 break;
489 // Verify that the map is all cleaned up.
490 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[0].key));
491 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[1].key));
492 EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[2].key));
495 TEST_P(SpdySessionPoolTest, IPPooling) {
496 RunIPPoolingTest(SPDY_POOL_CLOSE_SESSIONS_MANUALLY);
499 TEST_P(SpdySessionPoolTest, IPPoolingCloseCurrentSessions) {
500 RunIPPoolingTest(SPDY_POOL_CLOSE_CURRENT_SESSIONS);
503 TEST_P(SpdySessionPoolTest, IPPoolingCloseIdleSessions) {
504 RunIPPoolingTest(SPDY_POOL_CLOSE_IDLE_SESSIONS);
507 // Construct a Pool with SpdySessions in various availability states. Simulate
508 // an IP address change. Ensure sessions gracefully shut down. Regression test
509 // for crbug.com/379469.
510 TEST_P(SpdySessionPoolTest, IPAddressChanged) {
511 MockConnect connect_data(SYNCHRONOUS, OK);
512 session_deps_.host_resolver->set_synchronous_mode(true);
513 SpdyTestUtil spdy_util(GetParam());
515 MockRead reads[] = {
516 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
518 scoped_ptr<SpdyFrame> req(
519 spdy_util.ConstructSpdyGet("http://www.a.com", false, 1, MEDIUM));
520 MockWrite writes[] = {CreateMockWrite(*req, 1)};
522 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
523 data.set_connect_data(connect_data);
524 session_deps_.socket_factory->AddSocketDataProvider(&data);
526 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
527 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
529 CreateNetworkSession();
531 // Set up session A: Going away, but with an active stream.
532 session_deps_.socket_factory->AddSocketDataProvider(&data);
533 const std::string kTestHostA("http://www.a.com");
534 HostPortPair test_host_port_pairA(kTestHostA, 80);
535 SpdySessionKey keyA(
536 test_host_port_pairA, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
537 base::WeakPtr<SpdySession> sessionA =
538 CreateInsecureSpdySession(http_session_, keyA, BoundNetLog());
540 GURL urlA(kTestHostA);
541 base::WeakPtr<SpdyStream> spdy_streamA = CreateStreamSynchronously(
542 SPDY_BIDIRECTIONAL_STREAM, sessionA, urlA, MEDIUM, BoundNetLog());
543 test::StreamDelegateDoNothing delegateA(spdy_streamA);
544 spdy_streamA->SetDelegate(&delegateA);
546 scoped_ptr<SpdyHeaderBlock> headers(
547 spdy_util.ConstructGetHeaderBlock(urlA.spec()));
548 spdy_streamA->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND);
549 EXPECT_TRUE(spdy_streamA->HasUrlFromHeaders());
551 base::MessageLoop::current()->RunUntilIdle(); // Allow headers to write.
552 EXPECT_TRUE(delegateA.send_headers_completed());
554 sessionA->MakeUnavailable();
555 EXPECT_TRUE(sessionA->IsGoingAway());
556 EXPECT_FALSE(delegateA.StreamIsClosed());
558 // Set up session B: Available, with a created stream.
559 const std::string kTestHostB("http://www.b.com");
560 HostPortPair test_host_port_pairB(kTestHostB, 80);
561 SpdySessionKey keyB(
562 test_host_port_pairB, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
563 base::WeakPtr<SpdySession> sessionB =
564 CreateInsecureSpdySession(http_session_, keyB, BoundNetLog());
565 EXPECT_TRUE(sessionB->IsAvailable());
567 GURL urlB(kTestHostB);
568 base::WeakPtr<SpdyStream> spdy_streamB = CreateStreamSynchronously(
569 SPDY_BIDIRECTIONAL_STREAM, sessionB, urlB, MEDIUM, BoundNetLog());
570 test::StreamDelegateDoNothing delegateB(spdy_streamB);
571 spdy_streamB->SetDelegate(&delegateB);
573 // Set up session C: Draining.
574 session_deps_.socket_factory->AddSocketDataProvider(&data);
575 const std::string kTestHostC("http://www.c.com");
576 HostPortPair test_host_port_pairC(kTestHostC, 80);
577 SpdySessionKey keyC(
578 test_host_port_pairC, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
579 base::WeakPtr<SpdySession> sessionC =
580 CreateInsecureSpdySession(http_session_, keyC, BoundNetLog());
582 sessionC->CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Error!");
583 EXPECT_TRUE(sessionC->IsDraining());
585 spdy_session_pool_->OnIPAddressChanged();
587 #if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
588 EXPECT_TRUE(sessionA->IsGoingAway());
589 EXPECT_TRUE(sessionB->IsDraining());
590 EXPECT_TRUE(sessionC->IsDraining());
592 EXPECT_EQ(1u,
593 sessionA->num_active_streams()); // Active stream is still active.
594 EXPECT_FALSE(delegateA.StreamIsClosed());
596 EXPECT_TRUE(delegateB.StreamIsClosed()); // Created stream was closed.
597 EXPECT_EQ(ERR_NETWORK_CHANGED, delegateB.WaitForClose());
599 sessionA->CloseSessionOnError(ERR_ABORTED, "Closing");
600 sessionB->CloseSessionOnError(ERR_ABORTED, "Closing");
602 EXPECT_TRUE(delegateA.StreamIsClosed());
603 EXPECT_EQ(ERR_ABORTED, delegateA.WaitForClose());
604 #else
605 EXPECT_TRUE(sessionA->IsDraining());
606 EXPECT_TRUE(sessionB->IsDraining());
607 EXPECT_TRUE(sessionC->IsDraining());
609 // Both streams were closed with an error.
610 EXPECT_TRUE(delegateA.StreamIsClosed());
611 EXPECT_EQ(ERR_NETWORK_CHANGED, delegateA.WaitForClose());
612 EXPECT_TRUE(delegateB.StreamIsClosed());
613 EXPECT_EQ(ERR_NETWORK_CHANGED, delegateB.WaitForClose());
614 #endif // defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_IOS)
617 } // namespace
619 } // namespace net