OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/spdy/spdy_session.h" | 5 #include "net/spdy/spdy_session.h" |
6 | 6 |
7 #include "net/base/host_cache.h" | 7 #include "net/base/host_cache.h" |
8 #include "net/base/ip_endpoint.h" | 8 #include "net/base/ip_endpoint.h" |
9 #include "net/base/net_log_unittest.h" | 9 #include "net/base/net_log_unittest.h" |
10 #include "net/spdy/spdy_io_buffer.h" | 10 #include "net/spdy/spdy_io_buffer.h" |
(...skipping 1049 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1060 net::NetLog::TYPE_SPDY_SESSION_CLOSE, | 1060 net::NetLog::TYPE_SPDY_SESSION_CLOSE, |
1061 net::NetLog::PHASE_NONE); | 1061 net::NetLog::PHASE_NONE); |
1062 | 1062 |
1063 CapturingNetLog::Entry entry = entries[pos]; | 1063 CapturingNetLog::Entry entry = entries[pos]; |
1064 NetLogSpdySessionCloseParameter* request_params = | 1064 NetLogSpdySessionCloseParameter* request_params = |
1065 static_cast<NetLogSpdySessionCloseParameter*>( | 1065 static_cast<NetLogSpdySessionCloseParameter*>( |
1066 entry.extra_parameters.get()); | 1066 entry.extra_parameters.get()); |
1067 EXPECT_EQ(ERR_CONNECTION_CLOSED, request_params->status()); | 1067 EXPECT_EQ(ERR_CONNECTION_CLOSED, request_params->status()); |
1068 } | 1068 } |
1069 | 1069 |
| 1070 TEST_F(SpdySessionSpdy2Test, CloseOneIdleConnection) { |
| 1071 MockHostResolver host_resolver; |
| 1072 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); |
| 1073 ClientSocketPoolHistograms tcp_histograms(""); |
| 1074 MockClientSocketFactory socket_factory; |
| 1075 MockConnect connect_data(SYNCHRONOUS, OK); |
| 1076 MockRead reads[] = { |
| 1077 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. |
| 1078 }; |
| 1079 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); |
| 1080 data.set_connect_data(connect_data); |
| 1081 socket_factory.AddSocketDataProvider(&data); |
| 1082 socket_factory.AddSocketDataProvider(&data); |
| 1083 socket_factory.AddSocketDataProvider(&data); |
| 1084 socket_factory.AddSocketDataProvider(&data); |
| 1085 socket_factory.AddSocketDataProvider(&data); |
| 1086 socket_factory.AddSocketDataProvider(&data); |
| 1087 TransportClientSocketPool pool( |
| 1088 3, 2, |
| 1089 &tcp_histograms, |
| 1090 &host_resolver, |
| 1091 &socket_factory, NULL); |
| 1092 // Now if I check out 1 socket from 3 different groups, the next request |
| 1093 // will leave us stalled. |
| 1094 |
| 1095 TestCompletionCallback callback1; |
| 1096 HostPortPair host_port1("1.com", 80); |
| 1097 scoped_refptr<TransportSocketParams> params1( |
| 1098 new TransportSocketParams(host_port1, MEDIUM, false, false)); |
| 1099 scoped_ptr<ClientSocketHandle> connection1(new ClientSocketHandle); |
| 1100 EXPECT_EQ(ERR_IO_PENDING, |
| 1101 connection1->Init(host_port1.ToString(), params1, MEDIUM, |
| 1102 callback1.callback(), &pool, log.bound())); |
| 1103 EXPECT_EQ(OK, callback1.WaitForResult()); |
| 1104 EXPECT_FALSE(pool.IsStalled()); |
| 1105 EXPECT_TRUE(connection1->is_initialized()); |
| 1106 EXPECT_TRUE(connection1->socket()); |
| 1107 |
| 1108 TestCompletionCallback callback2; |
| 1109 HostPortPair host_port2("2.com", 80); |
| 1110 scoped_refptr<TransportSocketParams> params2( |
| 1111 new TransportSocketParams(host_port2, MEDIUM, false, false)); |
| 1112 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle); |
| 1113 EXPECT_EQ(ERR_IO_PENDING, |
| 1114 connection2->Init(host_port2.ToString(), params2, MEDIUM, |
| 1115 callback2.callback(), &pool, log.bound())); |
| 1116 EXPECT_EQ(OK, callback2.WaitForResult()); |
| 1117 EXPECT_FALSE(pool.IsStalled()); |
| 1118 |
| 1119 TestCompletionCallback callback3; |
| 1120 HostPortPair host_port3("3.com", 80); |
| 1121 scoped_refptr<TransportSocketParams> params3( |
| 1122 new TransportSocketParams(host_port3, MEDIUM, false, false)); |
| 1123 scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle); |
| 1124 EXPECT_EQ(ERR_IO_PENDING, |
| 1125 connection3->Init(host_port3.ToString(), params3, MEDIUM, |
| 1126 callback3.callback(), &pool, log.bound())); |
| 1127 EXPECT_EQ(OK, callback3.WaitForResult()); |
| 1128 EXPECT_FALSE(pool.IsStalled()); |
| 1129 |
| 1130 TestCompletionCallback callback4; |
| 1131 HostPortPair host_port4("4.com", 80); |
| 1132 scoped_refptr<TransportSocketParams> params4( |
| 1133 new TransportSocketParams(host_port4, MEDIUM, false, false)); |
| 1134 scoped_ptr<ClientSocketHandle> connection4(new ClientSocketHandle); |
| 1135 EXPECT_EQ(ERR_IO_PENDING, |
| 1136 connection4->Init(host_port4.ToString(), params4, MEDIUM, |
| 1137 callback4.callback(), &pool, log.bound())); |
| 1138 EXPECT_TRUE(pool.IsStalled()); |
| 1139 |
| 1140 // Return 1 socket to the pool so that we are no longer stalled |
| 1141 connection3->socket()->Disconnect(); |
| 1142 connection3->Reset(); |
| 1143 EXPECT_EQ(OK, callback4.WaitForResult()); |
| 1144 EXPECT_FALSE(pool.IsStalled()); |
| 1145 |
| 1146 // Now, wrap one of the sockets in a SpdySession |
| 1147 HttpServerPropertiesImpl props; |
| 1148 SpdySessionPool spdy_session_pool(&host_resolver, NULL, &props); |
| 1149 HostPortProxyPair pair1(host_port1, ProxyServer::Direct()); |
| 1150 EXPECT_FALSE(spdy_session_pool.HasSession(pair1)); |
| 1151 scoped_refptr<SpdySession> session1 = |
| 1152 spdy_session_pool.Get(pair1, log.bound()); |
| 1153 EXPECT_TRUE(spdy_session_pool.HasSession(pair1)); |
| 1154 EXPECT_EQ(OK, |
| 1155 session1->InitializeWithSocket(connection1.release(), false, OK)); |
| 1156 session1 = NULL; |
| 1157 EXPECT_TRUE(spdy_session_pool.HasSession(pair1)); |
| 1158 |
| 1159 // The SpdySession is now idle. When we request the next socket from the |
| 1160 // transport pool, the session will be closed via CloseOneIdleConnection(). |
| 1161 TestCompletionCallback callback5; |
| 1162 HostPortPair host_port5("5.com", 80); |
| 1163 scoped_refptr<TransportSocketParams> params5( |
| 1164 new TransportSocketParams(host_port5, MEDIUM, false, false)); |
| 1165 scoped_ptr<ClientSocketHandle> connection5(new ClientSocketHandle); |
| 1166 EXPECT_EQ(ERR_IO_PENDING, |
| 1167 connection5->Init(host_port5.ToString(), params5, MEDIUM, |
| 1168 callback5.callback(), &pool, log.bound())); |
| 1169 EXPECT_FALSE(pool.IsStalled()); |
| 1170 EXPECT_EQ(OK, callback5.WaitForResult()); |
| 1171 EXPECT_FALSE(spdy_session_pool.HasSession(pair1)); |
| 1172 EXPECT_FALSE(pool.IsStalled()); |
| 1173 |
| 1174 // Now, wrap one of the sockets in a SpdySession |
| 1175 HostPortProxyPair pair2(host_port2, ProxyServer::Direct()); |
| 1176 EXPECT_FALSE(spdy_session_pool.HasSession(pair2)); |
| 1177 scoped_refptr<SpdySession> session2 = |
| 1178 spdy_session_pool.Get(pair2, log.bound()); |
| 1179 EXPECT_TRUE(spdy_session_pool.HasSession(pair2)); |
| 1180 EXPECT_EQ(OK, |
| 1181 session2->InitializeWithSocket(connection2.release(), false, OK)); |
| 1182 |
| 1183 // Manually remove the socket from the pool. This does *not* return the |
| 1184 // transport socket. It will be returned only when the SpdySession is |
| 1185 // destructed. |
| 1186 session2->RemoveFromPool(); |
| 1187 EXPECT_FALSE(spdy_session_pool.HasSession(pair2)); |
| 1188 |
| 1189 // Although there are no active streams on the session, the pool does not |
| 1190 // hold a reference. This means that CloseOneIdleConnection should not |
| 1191 // return true, and this request should stall. |
| 1192 TestCompletionCallback callback6; |
| 1193 HostPortPair host_port6("6.com", 80); |
| 1194 scoped_refptr<TransportSocketParams> params6( |
| 1195 new TransportSocketParams(host_port5, MEDIUM, false, false)); |
| 1196 scoped_ptr<ClientSocketHandle> connection6(new ClientSocketHandle); |
| 1197 EXPECT_EQ(ERR_IO_PENDING, |
| 1198 connection6->Init(host_port6.ToString(), params6, MEDIUM, |
| 1199 callback6.callback(), &pool, log.bound())); |
| 1200 EXPECT_TRUE(pool.IsStalled()); |
| 1201 |
| 1202 // But now if we drop our reference to the session, it will be destructed |
| 1203 // and the transport socket will return to the pool, unblocking this |
| 1204 // request. |
| 1205 session2 = NULL; |
| 1206 EXPECT_EQ(OK, callback6.WaitForResult()); |
| 1207 EXPECT_FALSE(pool.IsStalled()); |
| 1208 } |
| 1209 |
1070 } // namespace net | 1210 } // namespace net |
OLD | NEW |