Make certificate viewer a tab-modal dialog.
[chromium-blink-merge.git] / net / spdy / spdy_session_spdy2_unittest.cc
blob0978f0671e55cb346e7ca85504016ef34950ef10
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;
26 namespace net {
28 namespace {
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);
39 } // namespace
41 class SpdySessionSpdy2Test : public PlatformTest {
42 protected:
43 SpdySessionSpdy2Test()
44 : spdy_session_pool_(NULL),
45 test_url_(kTestUrl),
46 test_host_port_pair_(kTestHost, kTestPort),
47 pair_(test_host_port_pair_, ProxyServer::Direct()) {
50 virtual void SetUp() {
51 g_delta_seconds = 0;
54 void CreateDeterministicNetworkSession() {
55 http_session_ =
56 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
57 spdy_session_pool_ = http_session_->spdy_session_pool();
60 void CreateNetworkSession() {
61 http_session_ =
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));
71 return session;
74 // Creates an initialized session to |pair_|.
75 scoped_refptr<SpdySession> CreateInitializedSession() {
76 scoped_refptr<SpdySession> session = GetSession(pair_);
77 EXPECT_EQ(
78 OK,
79 InitializeSession(
80 http_session_.get(), session.get(), test_host_port_pair_));
81 return session;
84 net::Error InitializeSession(HttpNetworkSession* http_session,
85 SpdySession* 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,
93 CompletionCallback(),
94 http_session->GetTransportSocketPool(
95 HttpNetworkSession::NORMAL_SOCKET_POOL),
96 BoundNetLog()));
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_;
104 GURL test_url_;
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));
114 MockRead reads[] = {
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);
162 data.RunFor(2);
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.
170 data.RunFor(1);
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();
180 spdy_stream1 = NULL;
181 spdy_stream2 = NULL;
183 // Delete the first session.
184 session = NULL;
186 // Delete the second session.
187 spdy_session_pool_->Remove(session2);
188 session2 = NULL;
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));
197 MockRead reads[] = {
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.
244 session = NULL;
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));
252 MockRead reads[] = {
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.
285 session = NULL;
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);
326 // Shift time.
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.
338 session = NULL;
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));
346 MockRead reads[] = {
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.
399 session = NULL;
402 TEST_F(SpdySessionSpdy2Test, CloseIdleSessions) {
403 CreateNetworkSession();
405 // Set up session 1
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);
415 // Set up session 2
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);
425 // Set up session 3
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());
477 // Make 2 not active
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
503 // streams to 2.
504 MockConnect connect_data(SYNCHRONOUS, OK);
505 scoped_ptr<SpdyFrame> settings_frame(ConstructSpdySettings(new_settings));
506 MockRead reads[] = {
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_,
523 kSpdySettingsIds1,
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,
539 BoundNetLog(),
540 stream_releaser.MakeCallback(&request)));
542 // Make sure |stream_releaser| holds the last refs.
543 session = NULL;
544 spdy_stream1 = NULL;
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);
556 MockRead reads[] = {
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,
592 BoundNetLog(),
593 callback->callback()));
595 // Release the first one, this will allow the second to be created.
596 spdy_stream1->Cancel();
597 spdy_stream1 = NULL;
599 request.CancelRequest();
600 callback.reset();
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);
609 MockRead reads[] = {
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);
645 MockRead reads[] = {
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_,
676 kSpdySettingsIds1,
677 SETTINGS_FLAG_PLEASE_PERSIST,
678 kBogusSettingValue);
680 scoped_refptr<SpdySession> session = CreateInitializedSession();
682 MessageLoop::current()->RunUntilIdle();
683 EXPECT_TRUE(data.at_write_eof());
686 namespace {
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;
704 struct TestHosts {
705 std::string url;
706 std::string name;
707 std::string iplist;
708 HostPortProxyPair pair;
709 AddressList addresses;
710 } test_hosts[] = {
711 { "http:://www.foo.com",
712 "www.foo.com",
713 "192.0.2.33,192.168.0.1,192.168.0.5"
715 { "http://js.foo.com",
716 "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",
720 "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,
736 BoundNetLog());
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);
744 MockRead reads[] = {
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,
769 MEDIUM,
770 false,
771 false,
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),
778 BoundNetLog()));
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);
832 session = NULL;
833 spdy_session_pool->Remove(session2);
834 session2 = NULL;
835 break;
836 case SPDY_POOL_CLOSE_CURRENT_SESSIONS:
837 spdy_session_pool->CloseCurrentSessions(net::ERR_ABORTED);
838 break;
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());
874 spdy_stream = NULL;
875 spdy_stream1 = NULL;
876 spdy_stream2->Cancel();
877 spdy_stream2 = NULL;
878 spdy_session_pool->Remove(session2);
879 session2 = NULL;
880 break;
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));
889 } // namespace
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());
926 MockRead reads[] = {
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(
959 entries, 0,
960 net::NetLog::TYPE_SPDY_SESSION_CLOSE,
961 net::NetLog::PHASE_NONE);
963 CapturingNetLog::CapturedEntry entry = entries[pos];
964 int error_code = 0;
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));
983 MockRead reads[] = {
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());
1113 data.RunFor(1);
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:
1217 // www.example.org
1218 // mail.example.org
1219 // www.example.com
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_,
1236 MEDIUM,
1237 false,
1238 false,
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,
1244 socks_params,
1245 http_proxy_params,
1246 ProxyServer::SCHEME_DIRECT,
1247 test_host_port_pair_,
1248 ssl_config,
1250 false,
1251 false));
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),
1257 BoundNetLog()));
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:
1285 // www.example.org
1286 // mail.example.org
1287 // www.example.com
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_,
1305 MEDIUM,
1306 false,
1307 false,
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,
1313 socks_params,
1314 http_proxy_params,
1315 ProxyServer::SCHEME_DIRECT,
1316 test_host_port_pair_,
1317 ssl_config,
1319 false,
1320 false));
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),
1326 BoundNetLog()));
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
1337 // this file.
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
1356 // streams to 1.
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.
1392 data.RunFor(1);
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,
1405 BoundNetLog(),
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,
1413 BoundNetLog(),
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());
1436 data.RunFor(3);
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());
1448 data.RunFor(3);
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());
1460 data.RunFor(4);
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,
1504 BoundNetLog(),
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,
1512 BoundNetLog(),
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,
1564 MEDIUM,
1565 false,
1566 false,
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,
1572 socks_params,
1573 http_proxy_params,
1574 ProxyServer::SCHEME_DIRECT,
1575 test_host_port_pair,
1576 ssl_config,
1578 false,
1579 false));
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),
1585 BoundNetLog()));
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
1626 // bytes.
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());
1672 data.RunFor(2);
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.
1677 data.RunFor(4);
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());
1762 data.RunFor(2);
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.
1767 data.RunFor(6);
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
1771 // to read.
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
1787 // synchronously.
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());
1875 data.RunFor(2);
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.
1880 data.RunFor(12);
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
1884 // it to read.
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());
1947 data.RunFor(1);
1948 EXPECT_EQ(1u, spdy_stream1->stream_id());
1950 // Drop the reference to the session.
1951 session = NULL;
1953 // Run until GoAway.
1954 data.RunFor(2);
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;
1962 data.RunFor(2);
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_);
1989 InitializeSession(
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_);
1999 } // namespace net