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 1114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1125 net::NetLog::TYPE_SPDY_SESSION_CLOSE, | 1125 net::NetLog::TYPE_SPDY_SESSION_CLOSE, |
1126 net::NetLog::PHASE_NONE); | 1126 net::NetLog::PHASE_NONE); |
1127 | 1127 |
1128 CapturingNetLog::Entry entry = entries[pos]; | 1128 CapturingNetLog::Entry entry = entries[pos]; |
1129 NetLogSpdySessionCloseParameter* request_params = | 1129 NetLogSpdySessionCloseParameter* request_params = |
1130 static_cast<NetLogSpdySessionCloseParameter*>( | 1130 static_cast<NetLogSpdySessionCloseParameter*>( |
1131 entry.extra_parameters.get()); | 1131 entry.extra_parameters.get()); |
1132 EXPECT_EQ(ERR_CONNECTION_CLOSED, request_params->status()); | 1132 EXPECT_EQ(ERR_CONNECTION_CLOSED, request_params->status()); |
1133 } | 1133 } |
1134 | 1134 |
1135 TEST_F(SpdySessionSpdy3Test, CloseOneIdleConnection) { | |
1136 MockHostResolver host_resolver; | |
1137 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); | |
1138 ClientSocketPoolHistograms tcp_histograms(""); | |
1139 MockClientSocketFactory socket_factory; | |
1140 MockConnect connect_data(SYNCHRONOUS, OK); | |
1141 MockRead reads[] = { | |
1142 MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. | |
1143 }; | |
1144 StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); | |
1145 data.set_connect_data(connect_data); | |
1146 socket_factory.AddSocketDataProvider(&data); | |
1147 socket_factory.AddSocketDataProvider(&data); | |
1148 socket_factory.AddSocketDataProvider(&data); | |
1149 socket_factory.AddSocketDataProvider(&data); | |
1150 socket_factory.AddSocketDataProvider(&data); | |
1151 socket_factory.AddSocketDataProvider(&data); | |
1152 TransportClientSocketPool pool( | |
1153 3, 2, | |
1154 &tcp_histograms, | |
1155 &host_resolver, | |
1156 &socket_factory, NULL); | |
1157 // Now if I check out 1 socket from 3 different groups, the next request | |
1158 // will leave us stalled. | |
1159 | |
1160 TestCompletionCallback callback1; | |
1161 HostPortPair host_port1("1.com", 80); | |
1162 scoped_refptr<TransportSocketParams> params1( | |
1163 new TransportSocketParams(host_port1, MEDIUM, false, false)); | |
1164 scoped_ptr<ClientSocketHandle> connection1(new ClientSocketHandle); | |
1165 EXPECT_EQ(ERR_IO_PENDING, | |
1166 connection1->Init(host_port1.ToString(), params1, MEDIUM, | |
1167 callback1.callback(), &pool, log.bound())); | |
1168 EXPECT_EQ(OK, callback1.WaitForResult()); | |
1169 EXPECT_FALSE(pool.IsStalled()); | |
1170 EXPECT_TRUE(connection1->is_initialized()); | |
1171 EXPECT_TRUE(connection1->socket()); | |
1172 | |
1173 TestCompletionCallback callback2; | |
1174 HostPortPair host_port2("2.com", 80); | |
1175 scoped_refptr<TransportSocketParams> params2( | |
1176 new TransportSocketParams(host_port2, MEDIUM, false, false)); | |
1177 scoped_ptr<ClientSocketHandle> connection2(new ClientSocketHandle); | |
1178 EXPECT_EQ(ERR_IO_PENDING, | |
1179 connection2->Init(host_port2.ToString(), params2, MEDIUM, | |
1180 callback2.callback(), &pool, log.bound())); | |
1181 EXPECT_EQ(OK, callback2.WaitForResult()); | |
1182 EXPECT_FALSE(pool.IsStalled()); | |
1183 | |
1184 TestCompletionCallback callback3; | |
1185 HostPortPair host_port3("3.com", 80); | |
1186 scoped_refptr<TransportSocketParams> params3( | |
1187 new TransportSocketParams(host_port3, MEDIUM, false, false)); | |
1188 scoped_ptr<ClientSocketHandle> connection3(new ClientSocketHandle); | |
1189 EXPECT_EQ(ERR_IO_PENDING, | |
1190 connection3->Init(host_port3.ToString(), params3, MEDIUM, | |
1191 callback3.callback(), &pool, log.bound())); | |
1192 EXPECT_EQ(OK, callback3.WaitForResult()); | |
1193 EXPECT_FALSE(pool.IsStalled()); | |
1194 | |
1195 TestCompletionCallback callback4; | |
1196 HostPortPair host_port4("4.com", 80); | |
1197 scoped_refptr<TransportSocketParams> params4( | |
1198 new TransportSocketParams(host_port4, MEDIUM, false, false)); | |
1199 scoped_ptr<ClientSocketHandle> connection4(new ClientSocketHandle); | |
1200 EXPECT_EQ(ERR_IO_PENDING, | |
1201 connection4->Init(host_port4.ToString(), params4, MEDIUM, | |
1202 callback4.callback(), &pool, log.bound())); | |
1203 EXPECT_TRUE(pool.IsStalled()); | |
1204 | |
1205 // Return 1 socket to the pool so that we are no longer stalled | |
1206 connection3->socket()->Disconnect(); | |
1207 connection3->Reset(); | |
1208 EXPECT_EQ(OK, callback4.WaitForResult()); | |
1209 EXPECT_FALSE(pool.IsStalled()); | |
1210 | |
1211 // Now, wrap one of the sockets in a SpdySession | |
1212 HttpServerPropertiesImpl props; | |
1213 SpdySessionPool spdy_session_pool(&host_resolver, NULL, &props); | |
1214 HostPortProxyPair pair1(host_port1, ProxyServer::Direct()); | |
1215 EXPECT_FALSE(spdy_session_pool.HasSession(pair1)); | |
1216 scoped_refptr<SpdySession> session1 = | |
1217 spdy_session_pool.Get(pair1, log.bound()); | |
1218 EXPECT_TRUE(spdy_session_pool.HasSession(pair1)); | |
1219 EXPECT_EQ(OK, | |
1220 session1->InitializeWithSocket(connection1.release(), false, OK)); | |
1221 session1 = NULL; | |
1222 EXPECT_TRUE(spdy_session_pool.HasSession(pair1)); | |
1223 | |
1224 // The SpdySession is now idle. When we request the next socket from the | |
1225 // transport pool, the session will be closed via CloseOneIdleConnection(). | |
1226 TestCompletionCallback callback5; | |
1227 HostPortPair host_port5("5.com", 80); | |
1228 scoped_refptr<TransportSocketParams> params5( | |
1229 new TransportSocketParams(host_port5, MEDIUM, false, false)); | |
1230 scoped_ptr<ClientSocketHandle> connection5(new ClientSocketHandle); | |
1231 EXPECT_EQ(ERR_IO_PENDING, | |
1232 connection5->Init(host_port5.ToString(), params5, MEDIUM, | |
1233 callback5.callback(), &pool, log.bound())); | |
1234 EXPECT_FALSE(pool.IsStalled()); | |
1235 EXPECT_EQ(OK, callback5.WaitForResult()); | |
1236 EXPECT_FALSE(spdy_session_pool.HasSession(pair1)); | |
1237 EXPECT_FALSE(pool.IsStalled()); | |
1238 | |
1239 // Now, wrap one of the sockets in a SpdySession | |
1240 HostPortProxyPair pair2(host_port2, ProxyServer::Direct()); | |
1241 EXPECT_FALSE(spdy_session_pool.HasSession(pair2)); | |
1242 scoped_refptr<SpdySession> session2 = | |
1243 spdy_session_pool.Get(pair2, log.bound()); | |
1244 EXPECT_TRUE(spdy_session_pool.HasSession(pair2)); | |
1245 EXPECT_EQ(OK, | |
1246 session2->InitializeWithSocket(connection2.release(), false, OK)); | |
1247 | |
1248 // Manually remove the socket from the pool. This does *not* return the | |
1249 // transport socket. It will be returned only when the SpdySession is | |
1250 // destructed. | |
1251 session2->RemoveFromPool(); | |
1252 EXPECT_FALSE(spdy_session_pool.HasSession(pair2)); | |
1253 | |
1254 // Although there are no active streams on the session, the pool does not | |
1255 // hold a reference. This means that CloseOneIdleConnection should not | |
1256 // return true, and this request should stall. | |
1257 TestCompletionCallback callback6; | |
1258 HostPortPair host_port6("6.com", 80); | |
1259 scoped_refptr<TransportSocketParams> params6( | |
1260 new TransportSocketParams(host_port5, MEDIUM, false, false)); | |
1261 scoped_ptr<ClientSocketHandle> connection6(new ClientSocketHandle); | |
1262 EXPECT_EQ(ERR_IO_PENDING, | |
1263 connection6->Init(host_port6.ToString(), params6, MEDIUM, | |
1264 callback6.callback(), &pool, log.bound())); | |
1265 EXPECT_TRUE(pool.IsStalled()); | |
1266 | |
1267 // But now if we drop our reference to the session, it will be destructed | |
1268 // and the transport socket will return to the pool, unblocking this | |
1269 // request. | |
1270 session2 = NULL; | |
1271 EXPECT_EQ(OK, callback6.WaitForResult()); | |
1272 EXPECT_FALSE(pool.IsStalled()); | |
1273 } | |
1274 | |
1275 } // namespace net | 1135 } // namespace net |
OLD | NEW |