PageRenderTime 75ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/external/okhttp/src/test/java/com/squareup/okhttp/ConnectionPoolTest.java

https://bitbucket.org/rlyspn/androidrr
Java | 391 lines | 303 code | 55 blank | 33 comment | 0 complexity | b87f87c1d049ab4e6eb9065b96d69228 MD5 | raw file
  1. /*
  2. * Copyright (C) 2013 Square, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.squareup.okhttp;
  17. import com.google.mockwebserver.MockWebServer;
  18. import com.squareup.okhttp.internal.RecordingHostnameVerifier;
  19. import com.squareup.okhttp.internal.SslContextBuilder;
  20. import com.squareup.okhttp.internal.Util;
  21. import com.squareup.okhttp.internal.mockspdyserver.MockSpdyServer;
  22. import java.io.IOException;
  23. import java.net.InetAddress;
  24. import java.net.InetSocketAddress;
  25. import java.net.Proxy;
  26. import java.net.UnknownHostException;
  27. import java.security.GeneralSecurityException;
  28. import java.util.Arrays;
  29. import javax.net.ssl.SSLContext;
  30. import org.junit.After;
  31. import org.junit.Before;
  32. import org.junit.Test;
  33. import static org.junit.Assert.assertEquals;
  34. import static org.junit.Assert.assertNotNull;
  35. import static org.junit.Assert.assertNull;
  36. import static org.junit.Assert.assertSame;
  37. import static org.junit.Assert.assertTrue;
  38. public final class ConnectionPoolTest {
  39. private static final int KEEP_ALIVE_DURATION_MS = 500;
  40. private static final SSLContext sslContext;
  41. static {
  42. try {
  43. sslContext = new SslContextBuilder(InetAddress.getLocalHost().getHostName()).build();
  44. } catch (GeneralSecurityException e) {
  45. throw new RuntimeException(e);
  46. } catch (UnknownHostException e) {
  47. throw new RuntimeException(e);
  48. }
  49. }
  50. private final MockSpdyServer spdyServer = new MockSpdyServer(sslContext.getSocketFactory());
  51. private InetSocketAddress spdySocketAddress;
  52. private Address spdyAddress;
  53. private final MockWebServer httpServer = new MockWebServer();
  54. private Address httpAddress;
  55. private InetSocketAddress httpSocketAddress;
  56. private Connection httpA;
  57. private Connection httpB;
  58. private Connection httpC;
  59. private Connection httpD;
  60. private Connection httpE;
  61. private Connection spdyA;
  62. private Connection spdyB;
  63. @Before public void setUp() throws Exception {
  64. httpServer.play();
  65. httpAddress = new Address(httpServer.getHostName(), httpServer.getPort(), null, null, null);
  66. httpSocketAddress = new InetSocketAddress(InetAddress.getByName(httpServer.getHostName()),
  67. httpServer.getPort());
  68. spdyServer.play();
  69. spdyAddress =
  70. new Address(spdyServer.getHostName(), spdyServer.getPort(), sslContext.getSocketFactory(),
  71. new RecordingHostnameVerifier(), null);
  72. spdySocketAddress = new InetSocketAddress(InetAddress.getByName(spdyServer.getHostName()),
  73. spdyServer.getPort());
  74. httpA = new Connection(httpAddress, Proxy.NO_PROXY, httpSocketAddress, true);
  75. httpA.connect(100, 100, null);
  76. httpB = new Connection(httpAddress, Proxy.NO_PROXY, httpSocketAddress, true);
  77. httpB.connect(100, 100, null);
  78. httpC = new Connection(httpAddress, Proxy.NO_PROXY, httpSocketAddress, true);
  79. httpC.connect(100, 100, null);
  80. httpD = new Connection(httpAddress, Proxy.NO_PROXY, httpSocketAddress, true);
  81. httpD.connect(100, 100, null);
  82. httpE = new Connection(httpAddress, Proxy.NO_PROXY, httpSocketAddress, true);
  83. httpE.connect(100, 100, null);
  84. spdyA = new Connection(spdyAddress, Proxy.NO_PROXY, spdySocketAddress, true);
  85. spdyA.connect(100, 100, null);
  86. spdyB = new Connection(spdyAddress, Proxy.NO_PROXY, spdySocketAddress, true);
  87. spdyB.connect(100, 100, null);
  88. }
  89. @After public void tearDown() throws Exception {
  90. httpServer.shutdown();
  91. spdyServer.shutdown();
  92. Util.closeQuietly(httpA);
  93. Util.closeQuietly(httpB);
  94. Util.closeQuietly(httpC);
  95. Util.closeQuietly(httpD);
  96. Util.closeQuietly(httpE);
  97. Util.closeQuietly(spdyA);
  98. Util.closeQuietly(spdyB);
  99. }
  100. @Test public void poolSingleHttpConnection() throws IOException {
  101. ConnectionPool pool = new ConnectionPool(1, KEEP_ALIVE_DURATION_MS);
  102. Connection connection = pool.get(httpAddress);
  103. assertNull(connection);
  104. connection = new Connection(httpAddress, Proxy.NO_PROXY, httpSocketAddress, true);
  105. connection.connect(100, 100, null);
  106. assertEquals(0, pool.getConnectionCount());
  107. pool.recycle(connection);
  108. assertEquals(1, pool.getConnectionCount());
  109. assertEquals(1, pool.getHttpConnectionCount());
  110. assertEquals(0, pool.getSpdyConnectionCount());
  111. Connection recycledConnection = pool.get(httpAddress);
  112. assertEquals(connection, recycledConnection);
  113. assertTrue(recycledConnection.isAlive());
  114. recycledConnection = pool.get(httpAddress);
  115. assertNull(recycledConnection);
  116. }
  117. @Test public void poolPrefersMostRecentlyRecycled() throws Exception {
  118. ConnectionPool pool = new ConnectionPool(2, KEEP_ALIVE_DURATION_MS);
  119. pool.recycle(httpA);
  120. pool.recycle(httpB);
  121. pool.recycle(httpC);
  122. assertPooled(pool, httpC, httpB);
  123. }
  124. @Test public void getSpdyConnection() throws Exception {
  125. ConnectionPool pool = new ConnectionPool(2, KEEP_ALIVE_DURATION_MS);
  126. pool.maybeShare(spdyA);
  127. assertSame(spdyA, pool.get(spdyAddress));
  128. assertPooled(pool, spdyA);
  129. }
  130. @Test public void getHttpConnection() throws Exception {
  131. ConnectionPool pool = new ConnectionPool(2, KEEP_ALIVE_DURATION_MS);
  132. pool.recycle(httpA);
  133. assertSame(httpA, pool.get(httpAddress));
  134. assertPooled(pool);
  135. }
  136. @Test public void idleConnectionNotReturned() throws Exception {
  137. ConnectionPool pool = new ConnectionPool(2, KEEP_ALIVE_DURATION_MS);
  138. pool.recycle(httpA);
  139. Thread.sleep(KEEP_ALIVE_DURATION_MS * 2);
  140. assertNull(pool.get(httpAddress));
  141. assertPooled(pool);
  142. }
  143. @Test public void maxIdleConnectionLimitIsEnforced() throws Exception {
  144. ConnectionPool pool = new ConnectionPool(2, KEEP_ALIVE_DURATION_MS);
  145. pool.recycle(httpA);
  146. pool.recycle(httpB);
  147. pool.recycle(httpC);
  148. pool.recycle(httpD);
  149. assertPooled(pool, httpD, httpC);
  150. }
  151. @Test public void expiredConnectionsAreEvicted() throws Exception {
  152. ConnectionPool pool = new ConnectionPool(2, KEEP_ALIVE_DURATION_MS);
  153. pool.recycle(httpA);
  154. pool.recycle(httpB);
  155. Thread.sleep(2 * KEEP_ALIVE_DURATION_MS);
  156. pool.get(spdyAddress); // Force the cleanup callable to run.
  157. assertPooled(pool);
  158. }
  159. @Test public void nonAliveConnectionNotReturned() throws Exception {
  160. ConnectionPool pool = new ConnectionPool(2, KEEP_ALIVE_DURATION_MS);
  161. pool.recycle(httpA);
  162. httpA.close();
  163. assertNull(pool.get(httpAddress));
  164. assertPooled(pool);
  165. }
  166. @Test public void differentAddressConnectionNotReturned() throws Exception {
  167. ConnectionPool pool = new ConnectionPool(2, KEEP_ALIVE_DURATION_MS);
  168. pool.recycle(httpA);
  169. assertNull(pool.get(spdyAddress));
  170. assertPooled(pool, httpA);
  171. }
  172. @Test public void gettingSpdyConnectionPromotesItToFrontOfQueue() throws Exception {
  173. ConnectionPool pool = new ConnectionPool(2, KEEP_ALIVE_DURATION_MS);
  174. pool.maybeShare(spdyA);
  175. pool.recycle(httpA);
  176. assertPooled(pool, httpA, spdyA);
  177. assertSame(spdyA, pool.get(spdyAddress));
  178. assertPooled(pool, spdyA, httpA);
  179. }
  180. @Test public void gettingConnectionReturnsOldestFirst() throws Exception {
  181. ConnectionPool pool = new ConnectionPool(2, KEEP_ALIVE_DURATION_MS);
  182. pool.recycle(httpA);
  183. pool.recycle(httpB);
  184. assertSame(httpA, pool.get(httpAddress));
  185. }
  186. @Test public void recyclingNonAliveConnectionClosesThatConnection() throws Exception {
  187. ConnectionPool pool = new ConnectionPool(2, KEEP_ALIVE_DURATION_MS);
  188. httpA.getSocket().shutdownInput();
  189. pool.recycle(httpA); // Should close httpA.
  190. assertTrue(httpA.getSocket().isClosed());
  191. }
  192. @Test public void shareHttpConnectionDoesNothing() throws Exception {
  193. ConnectionPool pool = new ConnectionPool(2, KEEP_ALIVE_DURATION_MS);
  194. pool.maybeShare(httpA);
  195. assertPooled(pool);
  196. }
  197. @Test public void recycleSpdyConnectionDoesNothing() throws Exception {
  198. ConnectionPool pool = new ConnectionPool(2, KEEP_ALIVE_DURATION_MS);
  199. pool.recycle(spdyA);
  200. assertPooled(pool);
  201. }
  202. @Test public void validateIdleSpdyConnectionTimeout() throws Exception {
  203. ConnectionPool pool = new ConnectionPool(2, KEEP_ALIVE_DURATION_MS);
  204. pool.maybeShare(spdyA);
  205. Thread.sleep((int) (KEEP_ALIVE_DURATION_MS * 0.7));
  206. assertNull(pool.get(httpAddress));
  207. assertPooled(pool, spdyA); // Connection should still be in the pool.
  208. Thread.sleep((int) (KEEP_ALIVE_DURATION_MS * 0.4));
  209. assertNull(pool.get(httpAddress));
  210. assertPooled(pool);
  211. }
  212. @Test public void validateIdleHttpConnectionTimeout() throws Exception {
  213. ConnectionPool pool = new ConnectionPool(2, KEEP_ALIVE_DURATION_MS);
  214. pool.recycle(httpA);
  215. Thread.sleep((int) (KEEP_ALIVE_DURATION_MS * 0.7));
  216. assertNull(pool.get(spdyAddress));
  217. assertPooled(pool, httpA); // Connection should still be in the pool.
  218. Thread.sleep((int) (KEEP_ALIVE_DURATION_MS * 0.4));
  219. assertNull(pool.get(spdyAddress));
  220. assertPooled(pool);
  221. }
  222. @Test public void maxConnections() throws IOException, InterruptedException {
  223. ConnectionPool pool = new ConnectionPool(2, KEEP_ALIVE_DURATION_MS);
  224. // Pool should be empty.
  225. assertEquals(0, pool.getConnectionCount());
  226. // http A should be added to the pool.
  227. pool.recycle(httpA);
  228. assertEquals(1, pool.getConnectionCount());
  229. assertEquals(1, pool.getHttpConnectionCount());
  230. assertEquals(0, pool.getSpdyConnectionCount());
  231. // http B should be added to the pool.
  232. pool.recycle(httpB);
  233. assertEquals(2, pool.getConnectionCount());
  234. assertEquals(2, pool.getHttpConnectionCount());
  235. assertEquals(0, pool.getSpdyConnectionCount());
  236. // http C should be added and http A should be removed.
  237. pool.recycle(httpC);
  238. Thread.sleep(50);
  239. assertEquals(2, pool.getConnectionCount());
  240. assertEquals(2, pool.getHttpConnectionCount());
  241. assertEquals(0, pool.getSpdyConnectionCount());
  242. // spdy A should be added and http B should be removed.
  243. pool.maybeShare(spdyA);
  244. Thread.sleep(50);
  245. assertEquals(2, pool.getConnectionCount());
  246. assertEquals(1, pool.getHttpConnectionCount());
  247. assertEquals(1, pool.getSpdyConnectionCount());
  248. // http C should be removed from the pool.
  249. Connection recycledHttpConnection = pool.get(httpAddress);
  250. assertNotNull(recycledHttpConnection);
  251. assertTrue(recycledHttpConnection.isAlive());
  252. assertEquals(1, pool.getConnectionCount());
  253. assertEquals(0, pool.getHttpConnectionCount());
  254. assertEquals(1, pool.getSpdyConnectionCount());
  255. // spdy A will be returned and kept in the pool.
  256. Connection sharedSpdyConnection = pool.get(spdyAddress);
  257. assertNotNull(sharedSpdyConnection);
  258. assertEquals(spdyA, sharedSpdyConnection);
  259. assertEquals(1, pool.getConnectionCount());
  260. assertEquals(0, pool.getHttpConnectionCount());
  261. assertEquals(1, pool.getSpdyConnectionCount());
  262. // Nothing should change.
  263. pool.recycle(httpC);
  264. Thread.sleep(50);
  265. assertEquals(2, pool.getConnectionCount());
  266. assertEquals(1, pool.getHttpConnectionCount());
  267. assertEquals(1, pool.getSpdyConnectionCount());
  268. // Nothing should change.
  269. pool.maybeShare(spdyB);
  270. Thread.sleep(50);
  271. assertEquals(2, pool.getConnectionCount());
  272. assertEquals(1, pool.getHttpConnectionCount());
  273. assertEquals(1, pool.getSpdyConnectionCount());
  274. // An http connection should be removed from the pool.
  275. recycledHttpConnection = pool.get(httpAddress);
  276. assertNotNull(recycledHttpConnection);
  277. assertTrue(recycledHttpConnection.isAlive());
  278. assertEquals(1, pool.getConnectionCount());
  279. assertEquals(0, pool.getHttpConnectionCount());
  280. assertEquals(1, pool.getSpdyConnectionCount());
  281. // Shouldn't change numbers because spdyConnections A and B user the same server address.
  282. pool.maybeShare(spdyB);
  283. Thread.sleep(50);
  284. assertEquals(1, pool.getConnectionCount());
  285. assertEquals(0, pool.getHttpConnectionCount());
  286. assertEquals(1, pool.getSpdyConnectionCount());
  287. // spdy A will be returned and kept in the pool. Pool shouldn't change.
  288. sharedSpdyConnection = pool.get(spdyAddress);
  289. assertEquals(spdyA, sharedSpdyConnection);
  290. assertNotNull(sharedSpdyConnection);
  291. assertEquals(1, pool.getConnectionCount());
  292. assertEquals(0, pool.getHttpConnectionCount());
  293. assertEquals(1, pool.getSpdyConnectionCount());
  294. // http D should be added to the pool.
  295. pool.recycle(httpD);
  296. Thread.sleep(50);
  297. assertEquals(2, pool.getConnectionCount());
  298. assertEquals(1, pool.getHttpConnectionCount());
  299. assertEquals(1, pool.getSpdyConnectionCount());
  300. // http E should be added to the pool. spdy A should be removed from the pool.
  301. pool.recycle(httpE);
  302. Thread.sleep(50);
  303. assertEquals(2, pool.getConnectionCount());
  304. assertEquals(2, pool.getHttpConnectionCount());
  305. assertEquals(0, pool.getSpdyConnectionCount());
  306. }
  307. @Test public void connectionCleanup() throws IOException, InterruptedException {
  308. ConnectionPool pool = new ConnectionPool(10, KEEP_ALIVE_DURATION_MS);
  309. // Add 3 connections to the pool.
  310. pool.recycle(httpA);
  311. pool.recycle(httpB);
  312. pool.maybeShare(spdyA);
  313. assertEquals(3, pool.getConnectionCount());
  314. assertEquals(2, pool.getHttpConnectionCount());
  315. assertEquals(1, pool.getSpdyConnectionCount());
  316. // Kill http A.
  317. Util.closeQuietly(httpA);
  318. // Force pool to run a clean up.
  319. assertNotNull(pool.get(spdyAddress));
  320. Thread.sleep(50);
  321. assertEquals(2, pool.getConnectionCount());
  322. assertEquals(1, pool.getHttpConnectionCount());
  323. assertEquals(1, pool.getSpdyConnectionCount());
  324. Thread.sleep(KEEP_ALIVE_DURATION_MS);
  325. // Force pool to run a clean up.
  326. assertNull(pool.get(httpAddress));
  327. assertNull(pool.get(spdyAddress));
  328. Thread.sleep(50);
  329. assertEquals(0, pool.getConnectionCount());
  330. assertEquals(0, pool.getHttpConnectionCount());
  331. assertEquals(0, pool.getSpdyConnectionCount());
  332. }
  333. private void assertPooled(ConnectionPool pool, Connection... connections) throws Exception {
  334. assertEquals(Arrays.asList(connections), pool.getConnections());
  335. }
  336. }