001: /*
002: * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/test/org/apache/commons/httpclient/TestHttpConnectionManager.java,v 1.23 2004/07/17 18:58:33 mbecke Exp $
003: * $Revision: 509320 $
004: * $Date: 2007-02-19 20:52:43 +0100 (Mon, 19 Feb 2007) $
005: * ====================================================================
006: *
007: * Licensed to the Apache Software Foundation (ASF) under one or more
008: * contributor license agreements. See the NOTICE file distributed with
009: * this work for additional information regarding copyright ownership.
010: * The ASF licenses this file to You under the Apache License, Version 2.0
011: * (the "License"); you may not use this file except in compliance with
012: * the License. You may obtain a copy of the License at
013: *
014: * http://www.apache.org/licenses/LICENSE-2.0
015: *
016: * Unless required by applicable law or agreed to in writing, software
017: * distributed under the License is distributed on an "AS IS" BASIS,
018: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
019: * See the License for the specific language governing permissions and
020: * limitations under the License.
021: * ====================================================================
022: *
023: * This software consists of voluntary contributions made by many
024: * individuals on behalf of the Apache Software Foundation. For more
025: * information on the Apache Software Foundation, please see
026: * <http://www.apache.org/>.
027: */
028:
029: package org.apache.commons.httpclient;
030:
031: import java.io.IOException;
032: import java.lang.ref.WeakReference;
033: import java.net.InetAddress;
034: import java.net.Socket;
035: import java.net.UnknownHostException;
036:
037: import junit.framework.Test;
038: import junit.framework.TestSuite;
039:
040: import org.apache.commons.httpclient.methods.GetMethod;
041: import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
042: import org.apache.commons.httpclient.params.HttpConnectionParams;
043: import org.apache.commons.httpclient.protocol.Protocol;
044: import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
045: import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
046: import org.apache.commons.httpclient.server.SimpleRequest;
047: import org.apache.commons.httpclient.server.SimpleResponse;
048:
049: /**
050: * Unit tests for {@link HttpConnectionManager}.
051: *
052: * @author Marc A. Saegesser
053: * @version $Id: TestHttpConnectionManager.java 509320 2007-02-19 19:52:43Z mbecke $
054: */
055: public class TestHttpConnectionManager extends HttpClientTestBase {
056:
057: // ------------------------------------------------------------ Constructor
058: public TestHttpConnectionManager(String testName)
059: throws IOException {
060: super (testName);
061: }
062:
063: // ------------------------------------------------------------------- Main
064: public static void main(String args[]) {
065: String[] testCaseName = { TestHttpConnectionManager.class
066: .getName() };
067: junit.textui.TestRunner.main(testCaseName);
068: }
069:
070: // ------------------------------------------------------- TestCase Methods
071:
072: public static Test suite() {
073: return new TestSuite(TestHttpConnectionManager.class);
074: }
075:
076: // ----------------------------------------------------------- Test Methods
077:
078: /**
079: * Test that the ConnectMethod correctly releases connections when
080: * CONNECT fails.
081: */
082: public void testConnectMethodFailureRelease() throws Exception {
083:
084: MultiThreadedHttpConnectionManager mgr = new MultiThreadedHttpConnectionManager();
085: mgr.getParams().setIntParameter(
086: HttpConnectionManagerParams.MAX_TOTAL_CONNECTIONS, 1);
087: client.setHttpConnectionManager(mgr);
088: this .server.setHttpService(new RejectConnectService());
089:
090: // we're going to execute a connect method against the localhost, assuming
091: // that CONNECT is not supported. This should test the fakeResponse()
092: // code on HttpMethodBase.
093: client.getHostConfiguration().setProxy(
094: server.getLocalAddress(), server.getLocalPort());
095: // we must set the host to a secure destination or the CONNECT method
096: // will not be used
097: client
098: .getHostConfiguration()
099: .setHost(
100: "notARealHost",
101: 1234,
102: new Protocol(
103: "https",
104: (ProtocolSocketFactory) new FakeSecureProtocolSocketFactory(),
105: 443));
106:
107: GetMethod get = new GetMethod("/");
108: try {
109: assertTrue(client.executeMethod(get) != 200);
110: } catch (IOException e) {
111: e.printStackTrace();
112: fail("Error executing connect: " + e);
113: }
114:
115: // this should calling releaseConnection() releases the connection
116: try {
117: get.releaseConnection();
118: mgr.getConnectionWithTimeout(client.getHostConfiguration(),
119: 1).releaseConnection();
120: } catch (ConnectTimeoutException e1) {
121: fail("Connection should have been available.");
122: }
123:
124: get = new GetMethod("/");
125:
126: try {
127: assertTrue(client.executeMethod(get) != 200);
128: } catch (IOException e) {
129: e.printStackTrace();
130: fail("Error executing connect: " + e);
131: }
132:
133: // make sure reading the response fully releases the connection
134: try {
135: get.getResponseBodyAsString();
136: mgr.getConnectionWithTimeout(client.getHostConfiguration(),
137: 1).releaseConnection();
138: } catch (ConnectTimeoutException e1) {
139: fail("Connection should have been available.");
140: }
141:
142: get = new GetMethod("/");
143:
144: try {
145: assertTrue(client.executeMethod(get) != 200);
146: } catch (IOException e) {
147: e.printStackTrace();
148: fail("Error executing connect: " + e);
149: }
150:
151: // make sure closing the output stream releases the connection
152: try {
153: get.getResponseBodyAsStream().close();
154: mgr.getConnectionWithTimeout(client.getHostConfiguration(),
155: 1).releaseConnection();
156: } catch (ConnectTimeoutException e) {
157: fail("Connection should have been available.");
158: } catch (IOException e) {
159: e.printStackTrace();
160: fail("Close connection failed: " + e);
161: }
162: }
163:
164: public void testGetConnection() {
165: MultiThreadedHttpConnectionManager mgr = new MultiThreadedHttpConnectionManager();
166:
167: HostConfiguration hostConfiguration = new HostConfiguration();
168: hostConfiguration.setHost("www.nosuchserver.com", 80, "http");
169:
170: // Create a new connection
171: HttpConnection conn = mgr.getConnection(hostConfiguration);
172: // Validate the connection properties
173: assertEquals("Host", "www.nosuchserver.com", conn.getHost());
174: assertEquals("Port", 80, conn.getPort());
175: // Release the connection
176: mgr.releaseConnection(conn);
177:
178: // Create a new connection
179: hostConfiguration.setHost("www.nosuchserver.com", -1, "https");
180: conn = mgr.getConnection(hostConfiguration);
181: // Validate the connection properties
182: assertEquals("Host", "www.nosuchserver.com", conn.getHost());
183: assertEquals("Port", 443, conn.getPort());
184: // Release the connection
185: mgr.releaseConnection(conn);
186:
187: // Create a new connection
188: hostConfiguration.setHost("www.nowhere.org", 8080, "http");
189: conn = mgr.getConnection(hostConfiguration);
190: // Validate the connection properties
191: assertEquals("Host", "www.nowhere.org", conn.getHost());
192: assertEquals("Port", 8080, conn.getPort());
193: // Release the connection
194: mgr.releaseConnection(conn);
195:
196: }
197:
198: public void testDroppedThread() throws Exception {
199:
200: this .server.setHttpService(new EchoService());
201:
202: MultiThreadedHttpConnectionManager mthcm = new MultiThreadedHttpConnectionManager();
203: client.setHttpConnectionManager(mthcm);
204: WeakReference wr = new WeakReference(mthcm);
205:
206: GetMethod method = new GetMethod("/");
207: client.executeMethod(method);
208: method.releaseConnection();
209:
210: mthcm = null;
211: client = null;
212: method = null;
213:
214: System.gc();
215:
216: // this sleep appears to be necessary in order to give the JVM
217: // time to clean up the miscellaneous pointers to the connection manager
218: try {
219: Thread.sleep(1000);
220: } catch (InterruptedException e) {
221: fail("shouldn't be interrupted.");
222: }
223:
224: Object connectionManager = wr.get();
225: assertNull("connectionManager should be null",
226: connectionManager);
227: }
228:
229: public void testWriteRequestReleaseConnection() {
230:
231: MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
232: connectionManager.getParams()
233: .setDefaultMaxConnectionsPerHost(1);
234:
235: client.setHttpConnectionManager(connectionManager);
236:
237: GetMethod get = new GetMethod("/") {
238: protected boolean writeRequestBody(HttpState state,
239: HttpConnection conn) throws IOException,
240: HttpException {
241: throw new IOException("Oh no!!");
242: }
243: };
244:
245: try {
246: client.executeMethod(get);
247: fail("An exception should have occurred.");
248: } catch (HttpException e) {
249: e.printStackTrace();
250: fail("HttpException should not have occurred: " + e);
251: } catch (IOException e) {
252: // expected
253: }
254:
255: try {
256: connectionManager.getConnectionWithTimeout(client
257: .getHostConfiguration(), 1);
258: } catch (ConnectTimeoutException e) {
259: e.printStackTrace();
260: fail("Connection was not released: " + e);
261: }
262:
263: }
264:
265: public void testReleaseConnection() {
266:
267: this .server.setHttpService(new EchoService());
268:
269: MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
270: connectionManager.getParams()
271: .setDefaultMaxConnectionsPerHost(1);
272:
273: client.setHttpConnectionManager(connectionManager);
274: // we shouldn't have to wait if a connection is available
275: client.getParams().setConnectionManagerTimeout(1);
276:
277: GetMethod getMethod = new GetMethod("/");
278:
279: try {
280: client.executeMethod(getMethod);
281: } catch (Exception e) {
282: fail("error reading from server: " + e);
283: }
284:
285: try {
286: // this should fail quickly since the connection has not been released
287: client.executeMethod(getMethod);
288: fail("a httpConnection should not be available");
289: } catch (ConnectTimeoutException e) {
290: } catch (HttpException e) {
291: fail("error reading from server; " + e);
292: } catch (IOException e) {
293: e.printStackTrace();
294: fail("error reading from server; " + e);
295: }
296:
297: // this should release the connection
298: getMethod.releaseConnection();
299:
300: getMethod = new GetMethod("/");
301:
302: try {
303: // this should fail quickly if the connection has not been released
304: client.executeMethod(getMethod);
305: } catch (HttpException e) {
306: fail("httpConnection does not appear to have been released: "
307: + e);
308: } catch (IOException e) {
309: fail("error reading from server; " + e);
310: }
311:
312: }
313:
314: /**
315: * Makes sure that a connection gets released after the content of the body
316: * is read.
317: */
318: public void testResponseAutoRelease() throws Exception {
319:
320: this .server.setHttpService(new EchoService());
321:
322: MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
323: connectionManager.getParams()
324: .setDefaultMaxConnectionsPerHost(1);
325:
326: client.setHttpConnectionManager(connectionManager);
327: // we shouldn't have to wait if a connection is available
328: client.getParams().setConnectionManagerTimeout(1);
329:
330: GetMethod getMethod = new GetMethod("/");
331:
332: try {
333: client.executeMethod(getMethod);
334: } catch (Exception e) {
335: fail("error reading from server: " + e);
336: }
337:
338: // this should release the connection
339: getMethod.getResponseBody();
340:
341: getMethod = new GetMethod("/");
342:
343: try {
344: // this should fail quickly if the connection has not been released
345: client.executeMethod(getMethod);
346: } catch (HttpException e) {
347: fail("httpConnection does not appear to have been released: "
348: + e);
349: } catch (IOException e) {
350: fail("error reading from server; " + e);
351: }
352:
353: }
354:
355: /**
356: * Tests the MultiThreadedHttpConnectionManager's ability to reclaim unused
357: * connections.
358: */
359: public void testConnectionReclaiming() {
360:
361: MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
362: connectionManager.getParams()
363: .setDefaultMaxConnectionsPerHost(1);
364: connectionManager.getParams().setMaxTotalConnections(1);
365:
366: HostConfiguration host1 = new HostConfiguration();
367: host1.setHost("host1", -1, "http");
368:
369: HostConfiguration host2 = new HostConfiguration();
370: host2.setHost("host2", -1, "http");
371:
372: HttpConnection connection = connectionManager
373: .getConnection(host1);
374: // now release this connection
375: connection.releaseConnection();
376: connection = null;
377:
378: try {
379: // the connection from host1 should be reclaimed
380: connection = connectionManager.getConnectionWithTimeout(
381: host2, 100);
382: } catch (ConnectTimeoutException e) {
383: e.printStackTrace();
384: fail("a httpConnection should have been available: " + e);
385: }
386: }
387:
388: /**
389: * Tests that {@link MultiThreadedHttpConnectionManager#shutdownAll()} closes all resources
390: * and makes all connection mangers unusable.
391: */
392: public void testShutdownAll() {
393:
394: MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
395: connectionManager.getParams()
396: .setDefaultMaxConnectionsPerHost(1);
397: connectionManager.getParams().setMaxTotalConnections(1);
398:
399: HostConfiguration host1 = new HostConfiguration();
400: host1.setHost("host1", -1, "http");
401:
402: // hold on to the only connection
403: HttpConnection connection = connectionManager
404: .getConnection(host1);
405:
406: // wait for a connection on another thread
407: GetConnectionThread getConn = new GetConnectionThread(host1,
408: connectionManager, 0);
409: getConn.start();
410:
411: MultiThreadedHttpConnectionManager.shutdownAll();
412:
413: // now release this connection, this should close the connection, but have no other effect
414: connection.releaseConnection();
415: connection = null;
416:
417: try {
418: getConn.join();
419: } catch (InterruptedException e) {
420: e.printStackTrace();
421: }
422:
423: // this thread should have caught an exception without getting a connection
424: assertNull("Not connection should have been checked out",
425: getConn.getConnection());
426: assertNotNull("There should have been an exception", getConn
427: .getException());
428:
429: try {
430: connectionManager.getConnection(host1);
431: fail("An exception should have occurred");
432: } catch (Exception e) {
433: // this is expected
434: }
435: }
436:
437: /**
438: * Tests that {@link MultiThreadedHttpConnectionManager#shutdown()} closes all resources
439: * and makes the connection manger unusable.
440: */
441: public void testShutdown() {
442:
443: MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
444: connectionManager.getParams()
445: .setDefaultMaxConnectionsPerHost(1);
446: connectionManager.getParams().setMaxTotalConnections(1);
447:
448: HostConfiguration host1 = new HostConfiguration();
449: host1.setHost("host1", -1, "http");
450:
451: // hold on to the only connection
452: HttpConnection connection = connectionManager
453: .getConnection(host1);
454:
455: // wait for a connection on another thread
456: GetConnectionThread getConn = new GetConnectionThread(host1,
457: connectionManager, 0);
458: getConn.start();
459:
460: connectionManager.shutdown();
461:
462: // now release this connection, this should close the connection, but have no other effect
463: connection.releaseConnection();
464: connection = null;
465:
466: try {
467: getConn.join();
468: } catch (InterruptedException e) {
469: e.printStackTrace();
470: }
471:
472: // this thread should have caught an exception without getting a connection
473: assertNull("Not connection should have been checked out",
474: getConn.getConnection());
475: assertNotNull("There should have been an exception", getConn
476: .getException());
477:
478: try {
479: connectionManager.getConnection(host1);
480: fail("An exception should have occurred");
481: } catch (Exception e) {
482: // this is expected
483: }
484: }
485:
486: /**
487: * Tests the MultiThreadedHttpConnectionManager's ability to restrict the maximum number
488: * of connections.
489: */
490: public void testMaxConnections() {
491:
492: MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
493: connectionManager.getParams()
494: .setDefaultMaxConnectionsPerHost(1);
495: connectionManager.getParams().setMaxTotalConnections(2);
496:
497: HostConfiguration host1 = new HostConfiguration();
498: host1.setHost("host1", -1, "http");
499:
500: HostConfiguration host2 = new HostConfiguration();
501: host2.setHost("host2", -1, "http");
502:
503: HttpConnection connection1 = connectionManager
504: .getConnection(host1);
505: HttpConnection connection2 = connectionManager
506: .getConnection(host2);
507:
508: try {
509: // this should fail quickly since the connection has not been released
510: connectionManager.getConnectionWithTimeout(host2, 100);
511: fail("ConnectionPoolTimeoutException should not be available");
512: } catch (ConnectionPoolTimeoutException e) {
513: // this should throw an exception
514: }
515:
516: // release one of the connections
517: connection2.releaseConnection();
518: connection2 = null;
519:
520: try {
521: // there should be a connection available now
522: connection2 = connectionManager.getConnectionWithTimeout(
523: host2, 100);
524: } catch (ConnectionPoolTimeoutException e) {
525: e.printStackTrace();
526: fail("a httpConnection should have been available: " + e);
527: }
528: }
529:
530: /**
531: * Tests the MultiThreadedHttpConnectionManager's ability to restrict the maximum number
532: * of connections per host.
533: */
534: public void testMaxConnectionsPerHost() throws Exception {
535:
536: MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
537: connectionManager.getParams()
538: .setDefaultMaxConnectionsPerHost(1);
539: connectionManager.getParams().setMaxTotalConnections(100);
540:
541: HostConfiguration host1 = new HostConfiguration();
542: host1.setHost("host1", -1, "http");
543:
544: HostConfiguration host2 = new HostConfiguration();
545: host2.setHost("host2", -1, "http");
546:
547: HostConfiguration host3 = new HostConfiguration();
548: host3.setHost("host3", -1, "http");
549:
550: connectionManager.getParams()
551: .setMaxConnectionsPerHost(host1, 3);
552: connectionManager.getParams()
553: .setMaxConnectionsPerHost(host2, 2);
554:
555: // Host1
556: HttpConnection connection1 = connectionManager
557: .getConnectionWithTimeout(host1, 1000);
558: HttpConnection connection2 = connectionManager
559: .getConnectionWithTimeout(host1, 1000);
560: HttpConnection connection3 = connectionManager
561: .getConnectionWithTimeout(host1, 1000);
562: try {
563: // this should fail quickly since the connection has not been released
564: connectionManager.getConnectionWithTimeout(host1, 100);
565: fail("ConnectionPoolTimeoutException should not be available");
566: } catch (ConnectionPoolTimeoutException e) {
567: // expected
568: }
569:
570: // Host2
571: connection1 = connectionManager.getConnectionWithTimeout(host2,
572: 1000);
573: connection2 = connectionManager.getConnectionWithTimeout(host2,
574: 1000);
575: try {
576: // this should fail quickly since the connection has not been released
577: connectionManager.getConnectionWithTimeout(host2, 100);
578: fail("ConnectionPoolTimeoutException should not be available");
579: } catch (ConnectionPoolTimeoutException e) {
580: // expected
581: }
582:
583: // Host3 (should use the default per host value)
584: connection1 = connectionManager.getConnectionWithTimeout(host3,
585: 1000);
586: try {
587: // this should fail quickly since the connection has not been released
588: connectionManager.getConnectionWithTimeout(host3, 100);
589: fail("ConnectionPoolTimeoutException should not be available");
590: } catch (ConnectionPoolTimeoutException e) {
591: // expected
592: }
593: }
594:
595: public void testHostReusePreference() {
596:
597: final MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
598: connectionManager.getParams()
599: .setDefaultMaxConnectionsPerHost(1);
600: connectionManager.getParams().setMaxTotalConnections(1);
601:
602: final HostConfiguration host1 = new HostConfiguration();
603: host1.setHost("host1", -1, "http");
604:
605: final HostConfiguration host2 = new HostConfiguration();
606: host2.setHost("host2", -1, "http");
607:
608: HttpConnection connection = connectionManager
609: .getConnection(host1);
610:
611: GetConnectionThread getHost1 = new GetConnectionThread(host1,
612: connectionManager, 200);
613: GetConnectionThread getHost2 = new GetConnectionThread(host2,
614: connectionManager, 200);
615:
616: getHost2.start();
617: getHost1.start();
618:
619: // give the threads some time to startup
620: try {
621: Thread.sleep(100);
622: } catch (InterruptedException e1) {
623: e1.printStackTrace();
624: }
625:
626: // after the connection to host1 is released it should be given to getHost1
627: connection.releaseConnection();
628: connection = null;
629:
630: try {
631: getHost1.join();
632: getHost2.join();
633: } catch (InterruptedException e) {
634: e.printStackTrace();
635: }
636:
637: assertNotSame("Connection should have been given to someone",
638: getHost1.getConnection(), getHost2.getConnection());
639: assertNotNull("Connection should have been given to host1",
640: getHost1.getConnection());
641: assertNull("Connection should NOT have been given to host2",
642: getHost2.getConnection());
643:
644: }
645:
646: public void testMaxConnectionsPerServer() {
647:
648: this .server.setHttpService(new EchoService());
649:
650: MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
651: connectionManager.getParams()
652: .setDefaultMaxConnectionsPerHost(1);
653:
654: client.setHttpConnectionManager(connectionManager);
655: // we shouldn't have to wait if a connection is available
656: client.getParams().setConnectionManagerTimeout(1);
657:
658: GetMethod getMethod = new GetMethod("/");
659:
660: try {
661: client.executeMethod(getMethod);
662: } catch (Exception e) {
663: fail("error reading from server: " + e);
664: }
665:
666: GetMethod getMethod2 = new GetMethod("/");
667:
668: try {
669: // this should fail quickly since the connection has not been released
670: client.executeMethod(getMethod2);
671: fail("a httpConnection should not be available");
672: } catch (ConnectTimeoutException e) {
673: } catch (HttpException e) {
674: fail("error reading from server; " + e);
675: } catch (IOException e) {
676: fail("error reading from server; " + e);
677: }
678:
679: }
680:
681: public void testDeleteClosedConnections() {
682:
683: MultiThreadedHttpConnectionManager manager = new MultiThreadedHttpConnectionManager();
684:
685: HttpConnection conn = manager.getConnection(client
686: .getHostConfiguration());
687:
688: assertEquals("connectionsInPool", manager
689: .getConnectionsInPool(), 1);
690: assertEquals("connectionsInPool(host)", manager
691: .getConnectionsInPool(client.getHostConfiguration()), 1);
692:
693: conn.close();
694: conn.releaseConnection();
695:
696: assertEquals("connectionsInPool", manager
697: .getConnectionsInPool(), 1);
698: assertEquals("connectionsInPool(host)", manager
699: .getConnectionsInPool(client.getHostConfiguration()), 1);
700:
701: manager.deleteClosedConnections();
702:
703: assertEquals("connectionsInPool", manager
704: .getConnectionsInPool(), 0);
705: assertEquals("connectionsInPool(host)", manager
706: .getConnectionsInPool(client.getHostConfiguration()), 0);
707: }
708:
709: /**
710: * Tests that thread waiting in the MultiThreadedHttpConnectionManager can be
711: * interrupted.
712: */
713: public void testWaitingThreadInterrupted() {
714:
715: this .server.setHttpService(new EchoService());
716:
717: MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
718: connectionManager.getParams().setIntParameter(
719: HttpConnectionManagerParams.MAX_TOTAL_CONNECTIONS, 1);
720:
721: HostConfiguration host1 = new HostConfiguration();
722: host1.setHost("host1", -1, "http");
723:
724: // hold on to the only connection
725: HttpConnection connection = connectionManager
726: .getConnection(host1);
727:
728: // wait for a connection on another thread
729: GetConnectionThread getConn = new GetConnectionThread(host1,
730: connectionManager, 1000);
731: getConn.start();
732:
733: // give the thread a chance to block
734: synchronized (this ) {
735: try {
736: this .wait(500);
737: } catch (InterruptedException e) {
738: e.printStackTrace();
739: }
740: }
741:
742: // interrupt the thread, this should cancel waiting with a RuntimeException
743: getConn.interrupt();
744:
745: try {
746: getConn.join();
747: } catch (InterruptedException e) {
748: e.printStackTrace();
749: }
750:
751: // make sure the correct exception was thrown
752: assertTrue(getConn.exception != null);
753: assertEquals(getConn.exception.getClass(),
754: IllegalThreadStateException.class);
755:
756: // make sure the connection manager is still working
757: connection.releaseConnection();
758: try {
759: connectionManager.getConnectionWithTimeout(host1, 10);
760: } catch (ConnectionPoolTimeoutException e) {
761: fail("Connection not available");
762: }
763: }
764:
765: public void testReclaimUnusedConnection() {
766:
767: this .server.setHttpService(new EchoService());
768:
769: MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
770: connectionManager.getParams().setIntParameter(
771: HttpConnectionManagerParams.MAX_TOTAL_CONNECTIONS, 1);
772:
773: client.setHttpConnectionManager(connectionManager);
774: // we shouldn't have to wait if a connection is available
775: client.getParams().setConnectionManagerTimeout(30000);
776:
777: GetMethod getMethod = new GetMethod("/");
778:
779: try {
780: client.executeMethod(getMethod);
781: } catch (Exception e) {
782: fail("error reading from server: " + e);
783: }
784:
785: getMethod = new GetMethod("/");
786:
787: Runtime.getRuntime().gc();
788:
789: try {
790: // we didn't explicitly release the connection, but it should be
791: // reclaimed by the garbage collector, we hope:)
792: client.executeMethod(getMethod);
793: } catch (HttpException e) {
794: fail("httpConnection does not appear to have been reclaimed by the GC: "
795: + e);
796: } catch (IOException e) {
797: fail("error reading from server; " + e);
798: }
799:
800: }
801:
802: public void testGetFromMultipleThreads() {
803:
804: this .server.setHttpService(new EchoService());
805:
806: client
807: .setHttpConnectionManager(new MultiThreadedHttpConnectionManager());
808: ExecuteMethodThread[] threads = new ExecuteMethodThread[10];
809:
810: for (int i = 0; i < threads.length; i++) {
811: GetMethod method = new GetMethod("/");
812: method.setFollowRedirects(true);
813:
814: threads[i] = new ExecuteMethodThread(method, client);
815: threads[i].start();
816: }
817:
818: for (int i = 0; i < threads.length; i++) {
819: try {
820: // wait until this thread finishes. we'll give it 10 seconds,
821: // but it shouldn't take that long
822: threads[i].join(10000);
823: } catch (InterruptedException e) {
824: }
825: // make sure an exception did not occur
826: Exception e = threads[i].getException();
827: if (e != null) {
828: fail("An error occured in the get: " + e);
829: }
830: // we should have a 200 status
831: assertEquals(threads[i].getMethod().getStatusCode(),
832: HttpStatus.SC_OK);
833: }
834: }
835:
836: public void testTimeout() {
837: MultiThreadedHttpConnectionManager mgr = new MultiThreadedHttpConnectionManager();
838: mgr.getParams().setDefaultMaxConnectionsPerHost(2);
839:
840: try {
841: HostConfiguration hostConfig = new HostConfiguration();
842: hostConfig.setHost("www.nosuchserver.com", 80, "http");
843:
844: HttpConnection conn1 = mgr.getConnection(hostConfig);
845: HttpConnection conn2 = mgr.getConnection(hostConfig);
846:
847: HttpConnection conn3 = mgr.getConnectionWithTimeout(
848: hostConfig, 1000);
849: fail("Expected an HttpException.");
850:
851: } catch (ConnectTimeoutException e) {
852: //Expected result
853: }
854: }
855:
856: static class FakeSecureProtocolSocketFactory implements
857: SecureProtocolSocketFactory {
858:
859: public Socket createSocket(Socket socket, String host,
860: int port, boolean autoClose) throws IOException,
861: UnknownHostException {
862: throw new IllegalStateException(
863: "createSocket() should never have been called.");
864: }
865:
866: public Socket createSocket(String host, int port)
867: throws IOException, UnknownHostException {
868: throw new IllegalStateException(
869: "createSocket() should never have been called.");
870: }
871:
872: public Socket createSocket(String host, int port,
873: InetAddress clientHost, int clientPort)
874: throws IOException, UnknownHostException {
875: throw new IllegalStateException(
876: "createSocket() should never have been called.");
877: }
878:
879: public Socket createSocket(String host, int port,
880: InetAddress clientHost, int clientPort,
881: HttpConnectionParams params) throws IOException,
882: UnknownHostException {
883: throw new IllegalStateException(
884: "createSocket() should never have been called.");
885: }
886: }
887:
888: static class RejectConnectService extends EchoService {
889: public boolean process(SimpleRequest request,
890: SimpleResponse response) throws IOException {
891: if (request.getRequestLine().getMethod().equalsIgnoreCase(
892: "CONNECT")) {
893: response.setStatusLine(request.getRequestLine()
894: .getHttpVersion(),
895: HttpStatus.SC_METHOD_NOT_ALLOWED);
896: response.setHeader(new Header("Connection", "close"));
897: return true;
898: } else {
899: return super .process(request, response);
900: }
901: }
902: }
903:
904: static class GetConnectionThread extends Thread {
905:
906: private HostConfiguration hostConfiguration;
907: private MultiThreadedHttpConnectionManager connectionManager;
908: private HttpConnection connection;
909: private long timeout;
910: private Exception exception;
911:
912: public GetConnectionThread(HostConfiguration hostConfiguration,
913: MultiThreadedHttpConnectionManager connectionManager,
914: long timeout) {
915: this .hostConfiguration = hostConfiguration;
916: this .connectionManager = connectionManager;
917: this .timeout = timeout;
918: }
919:
920: public void run() {
921: try {
922: connection = connectionManager
923: .getConnectionWithTimeout(hostConfiguration,
924: timeout);
925: } catch (Exception e) {
926: this .exception = e;
927: }
928: }
929:
930: public Exception getException() {
931: return exception;
932: }
933:
934: public HttpConnection getConnection() {
935: return connection;
936: }
937:
938: }
939:
940: }
|