1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 package org.apache.commons.httpclient;
32
33 import java.io.IOException;
34 import java.lang.ref.WeakReference;
35 import java.net.InetAddress;
36 import java.net.Socket;
37 import java.net.UnknownHostException;
38
39 import junit.framework.Test;
40 import junit.framework.TestSuite;
41
42 import org.apache.commons.httpclient.methods.GetMethod;
43 import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
44 import org.apache.commons.httpclient.params.HttpConnectionParams;
45 import org.apache.commons.httpclient.protocol.Protocol;
46 import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
47 import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
48
49 /***
50 * Unit tests for {@link HttpConnectionManager}.
51 *
52 * @author Marc A. Saegesser
53 * @version $Id: TestHttpConnectionManager.java,v 1.21 2004/04/13 21:47:29 olegk Exp $
54 */
55 public class TestHttpConnectionManager extends TestLocalHostBase {
56
57
58 public TestHttpConnectionManager(String testName) {
59 super(testName);
60 }
61
62
63 public static void main(String args[]) {
64 String[] testCaseName = { TestHttpConnectionManager.class.getName() };
65 junit.textui.TestRunner.main(testCaseName);
66 }
67
68
69
70 public static Test suite() {
71 return new TestSuite(TestHttpConnectionManager.class);
72 }
73
74
75
76
77 /***
78 * Test that the ConnectMethod correctly releases connections when
79 * CONNECT fails.
80 */
81 public void testConnectMethodFailureRelease() throws Exception {
82
83 MultiThreadedHttpConnectionManager mgr = new MultiThreadedHttpConnectionManager();
84 mgr.getParams().setIntParameter(
85 HttpConnectionManagerParams.MAX_TOTAL_CONNECTIONS, 1);
86 HttpClient client = createHttpClient(mgr);
87
88
89
90
91 client.getHostConfiguration().setProxy(getHost(), getPort());
92
93
94 client.getHostConfiguration().setHost(
95 "notARealHost",
96 1234,
97 new Protocol(
98 "https",
99 (ProtocolSocketFactory)new FakeSecureProtocolSocketFactory(),
100 443)
101 );
102
103 GetMethod get = new GetMethod("/");
104 try {
105 assertTrue(client.executeMethod(get) != 200);
106 } catch (IOException e) {
107 e.printStackTrace();
108 fail("Error executing connect: " + e);
109 }
110
111
112 try {
113 get.releaseConnection();
114 mgr.getConnectionWithTimeout(client.getHostConfiguration(), 1).releaseConnection();
115 } catch (ConnectTimeoutException e1) {
116 fail("Connection should have been available.");
117 }
118
119 get = new GetMethod("/");
120
121 try {
122 assertTrue(client.executeMethod(get) != 200);
123 } catch (IOException e) {
124 e.printStackTrace();
125 fail("Error executing connect: " + e);
126 }
127
128
129 try {
130 get.getResponseBodyAsString();
131 mgr.getConnectionWithTimeout(client.getHostConfiguration(), 1).releaseConnection();
132 } catch (ConnectTimeoutException e1) {
133 fail("Connection should have been available.");
134 }
135
136 get = new GetMethod("/");
137
138 try {
139 assertTrue(client.executeMethod(get) != 200);
140 } catch (IOException e) {
141 e.printStackTrace();
142 fail("Error executing connect: " + e);
143 }
144
145
146 try {
147 get.getResponseBodyAsStream().close();
148 mgr.getConnectionWithTimeout(client.getHostConfiguration(), 1).releaseConnection();
149 } catch (ConnectTimeoutException e) {
150 fail("Connection should have been available.");
151 } catch (IOException e) {
152 e.printStackTrace();
153 fail("Close connection failed: " + e);
154 }
155 }
156
157 public void testGetConnection() {
158 MultiThreadedHttpConnectionManager mgr = new MultiThreadedHttpConnectionManager();
159
160 HostConfiguration hostConfiguration = new HostConfiguration();
161 hostConfiguration.setHost("www.nosuchserver.com", 80, "http");
162
163
164 HttpConnection conn = mgr.getConnection(hostConfiguration);
165
166 assertEquals("Host", "www.nosuchserver.com", conn.getHost());
167 assertEquals("Port", 80, conn.getPort());
168
169 mgr.releaseConnection(conn);
170
171
172 hostConfiguration.setHost("www.nosuchserver.com", -1, "https");
173 conn = mgr.getConnection(hostConfiguration);
174
175 assertEquals("Host", "www.nosuchserver.com", conn.getHost());
176 assertEquals("Port", 443, conn.getPort());
177
178 mgr.releaseConnection(conn);
179
180
181 hostConfiguration.setHost("www.nowhere.org", 8080, "http");
182 conn = mgr.getConnection(hostConfiguration);
183
184 assertEquals("Host", "www.nowhere.org", conn.getHost());
185 assertEquals("Port", 8080, conn.getPort());
186
187 mgr.releaseConnection(conn);
188
189 }
190
191 public void testDroppedThread() throws Exception {
192
193 MultiThreadedHttpConnectionManager mthcm = new MultiThreadedHttpConnectionManager();
194 HttpClient httpClient = createHttpClient(mthcm);
195 WeakReference wr = new WeakReference(mthcm);
196
197 GetMethod method = new GetMethod("/");
198 httpClient.executeMethod(method);
199 method.releaseConnection();
200
201 mthcm = null;
202 httpClient = null;
203 method = null;
204
205 System.gc();
206
207
208
209 try {
210 Thread.sleep(1000);
211 } catch (InterruptedException e) {
212 fail("shouldn't be interrupted.");
213 }
214
215 Object connectionManager = wr.get();
216 assertNull("connectionManager should be null", connectionManager);
217 }
218
219 public void testWriteRequestReleaseConnection() {
220
221 MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
222 connectionManager.getParams().setIntParameter(
223 HttpConnectionManagerParams.MAX_HOST_CONNECTIONS, 1);
224
225 HttpClient client = createHttpClient(connectionManager);
226
227 GetMethod get = new GetMethod("/") {
228 protected boolean writeRequestBody(HttpState state, HttpConnection conn)
229 throws IOException, HttpException {
230 throw new IOException("Oh no!!");
231 }
232 };
233
234 try {
235 client.executeMethod(get);
236 fail("An exception should have occurred.");
237 } catch (HttpException e) {
238 e.printStackTrace();
239 fail("HttpException should not have occurred: " + e);
240 } catch (IOException e) {
241
242 }
243
244 try {
245 connectionManager.getConnectionWithTimeout(client.getHostConfiguration(), 1);
246 } catch (ConnectTimeoutException e) {
247 e.printStackTrace();
248 fail("Connection was not released: " + e);
249 }
250
251 }
252
253 public void testReleaseConnection() {
254
255 MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
256 connectionManager.getParams().setIntParameter(
257 HttpConnectionManagerParams.MAX_HOST_CONNECTIONS, 1);
258
259 HttpClient client = createHttpClient(connectionManager);
260
261 client.getParams().setConnectionManagerTimeout(1);
262
263 GetMethod getMethod = new GetMethod("/");
264
265 try {
266 client.executeMethod(getMethod);
267 } catch (Exception e) {
268 fail("error reading from server: " + e);
269 }
270
271 try {
272
273 client.executeMethod(getMethod);
274 fail("a httpConnection should not be available");
275 } catch (ConnectTimeoutException e) {
276 } catch (HttpException e) {
277 fail("error reading from server; " + e);
278 } catch (IOException e) {
279 e.printStackTrace();
280 fail("error reading from server; " + e);
281 }
282
283
284 getMethod.releaseConnection();
285
286 getMethod = new GetMethod("/");
287
288 try {
289
290 client.executeMethod(getMethod);
291 } catch (HttpException e) {
292 fail("httpConnection does not appear to have been released: " + e);
293 } catch (IOException e) {
294 fail("error reading from server; " + e);
295 }
296
297 }
298
299 /***
300 * Makes sure that a connection gets released after the content of the body
301 * is read.
302 */
303 public void testResponseAutoRelease() throws Exception {
304
305 MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
306 connectionManager.getParams().setIntParameter(
307 HttpConnectionManagerParams.MAX_HOST_CONNECTIONS, 1);
308
309 HttpClient client = createHttpClient(connectionManager);
310
311 client.getParams().setConnectionManagerTimeout( 1 );
312
313 GetMethod getMethod = new GetMethod("/");
314
315 try {
316 client.executeMethod(getMethod);
317 } catch (Exception e) {
318 fail("error reading from server: " + e);
319 }
320
321
322 getMethod.getResponseBody();
323
324 getMethod = new GetMethod("/");
325
326 try {
327
328 client.executeMethod(getMethod);
329 } catch (HttpException e) {
330 fail("httpConnection does not appear to have been released: " + e);
331 } catch (IOException e) {
332 fail("error reading from server; " + e);
333 }
334
335 }
336
337 /***
338 * Tests the MultiThreadedHttpConnectionManager's ability to reclaim unused
339 * connections.
340 */
341 public void testConnectionReclaiming() {
342
343 MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
344 connectionManager.getParams().setIntParameter(
345 HttpConnectionManagerParams.MAX_HOST_CONNECTIONS, 1);
346 connectionManager.getParams().setIntParameter(
347 HttpConnectionManagerParams.MAX_TOTAL_CONNECTIONS, 1);
348
349 HostConfiguration host1 = new HostConfiguration();
350 host1.setHost("host1", -1, "http");
351
352 HostConfiguration host2 = new HostConfiguration();
353 host2.setHost("host2", -1, "http");
354
355 HttpConnection connection = connectionManager.getConnection(host1);
356
357 connection.releaseConnection();
358 connection = null;
359
360 try {
361
362 connection = connectionManager.getConnectionWithTimeout(host2, 100);
363 } catch (ConnectTimeoutException e) {
364 e.printStackTrace();
365 fail("a httpConnection should have been available: " + e);
366 }
367 }
368
369 /***
370 * Tests that {@link MultiThreadedHttpConnectionManager#shutdownAll()} closes all resources
371 * and makes all connection mangers unusable.
372 */
373 public void testShutdownAll() {
374
375 MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
376 connectionManager.getParams().setIntParameter(
377 HttpConnectionManagerParams.MAX_HOST_CONNECTIONS, 1);
378 connectionManager.getParams().setIntParameter(
379 HttpConnectionManagerParams.MAX_TOTAL_CONNECTIONS, 1);
380
381 HostConfiguration host1 = new HostConfiguration();
382 host1.setHost("host1", -1, "http");
383
384
385 HttpConnection connection = connectionManager.getConnection(host1);
386
387
388 GetConnectionThread getConn = new GetConnectionThread(host1, connectionManager, 0);
389 getConn.start();
390
391 MultiThreadedHttpConnectionManager.shutdownAll();
392
393
394 connection.releaseConnection();
395 connection = null;
396
397 try {
398 getConn.join();
399 } catch (InterruptedException e) {
400 e.printStackTrace();
401 }
402
403
404 assertNull("Not connection should have been checked out", getConn.getConnection());
405 assertNotNull("There should have been an exception", getConn.getException());
406
407 try {
408 connectionManager.getConnection(host1);
409 fail("An exception should have occurred");
410 } catch (Exception e) {
411
412 }
413 }
414
415 /***
416 * Tests that {@link MultiThreadedHttpConnectionManager#shutdown()} closes all resources
417 * and makes the connection manger unusable.
418 */
419 public void testShutdown() {
420
421 MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
422 connectionManager.getParams().setIntParameter(
423 HttpConnectionManagerParams.MAX_HOST_CONNECTIONS, 1);
424 connectionManager.getParams().setIntParameter(
425 HttpConnectionManagerParams.MAX_TOTAL_CONNECTIONS, 1);
426
427 HostConfiguration host1 = new HostConfiguration();
428 host1.setHost("host1", -1, "http");
429
430
431 HttpConnection connection = connectionManager.getConnection(host1);
432
433
434 GetConnectionThread getConn = new GetConnectionThread(host1, connectionManager, 0);
435 getConn.start();
436
437 connectionManager.shutdown();
438
439
440 connection.releaseConnection();
441 connection = null;
442
443 try {
444 getConn.join();
445 } catch (InterruptedException e) {
446 e.printStackTrace();
447 }
448
449
450 assertNull("Not connection should have been checked out", getConn.getConnection());
451 assertNotNull("There should have been an exception", getConn.getException());
452
453 try {
454 connectionManager.getConnection(host1);
455 fail("An exception should have occurred");
456 } catch (Exception e) {
457
458 }
459 }
460
461 /***
462 * Tests the MultiThreadedHttpConnectionManager's ability to restrict the maximum number
463 * of connections.
464 */
465 public void testMaxConnections() {
466
467 MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
468 connectionManager.getParams().setIntParameter(
469 HttpConnectionManagerParams.MAX_HOST_CONNECTIONS, 1);
470 connectionManager.getParams().setIntParameter(
471 HttpConnectionManagerParams.MAX_TOTAL_CONNECTIONS, 2);
472
473 HostConfiguration host1 = new HostConfiguration();
474 host1.setHost("host1", -1, "http");
475
476 HostConfiguration host2 = new HostConfiguration();
477 host2.setHost("host2", -1, "http");
478
479 HttpConnection connection1 = connectionManager.getConnection(host1);
480 HttpConnection connection2 = connectionManager.getConnection(host2);
481
482 try {
483
484 connectionManager.getConnectionWithTimeout(host2, 100);
485 fail("a httpConnection should not be available");
486 } catch (ConnectTimeoutException e) {
487
488 }
489
490
491 connection2.releaseConnection();
492 connection2 = null;
493
494 try {
495
496 connection2 = connectionManager.getConnectionWithTimeout(host2, 100);
497 } catch (ConnectTimeoutException e) {
498 e.printStackTrace();
499 fail("a httpConnection should have been available: " + e);
500 }
501 }
502
503 public void testHostReusePreference() {
504
505 final MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
506 connectionManager.getParams().setIntParameter(
507 HttpConnectionManagerParams.MAX_HOST_CONNECTIONS, 1);
508 connectionManager.getParams().setIntParameter(
509 HttpConnectionManagerParams.MAX_TOTAL_CONNECTIONS, 1);
510
511 final HostConfiguration host1 = new HostConfiguration();
512 host1.setHost("host1", -1, "http");
513
514 final HostConfiguration host2 = new HostConfiguration();
515 host2.setHost("host2", -1, "http");
516
517 HttpConnection connection = connectionManager.getConnection(host1);
518
519 GetConnectionThread getHost1 = new GetConnectionThread(host1, connectionManager, 200);
520 GetConnectionThread getHost2 = new GetConnectionThread(host2, connectionManager, 200);
521
522 getHost2.start();
523 getHost1.start();
524
525
526 try {
527 Thread.sleep(100);
528 } catch (InterruptedException e1) {
529 e1.printStackTrace();
530 }
531
532
533 connection.releaseConnection();
534 connection = null;
535
536 try {
537 getHost1.join();
538 getHost2.join();
539 } catch (InterruptedException e) {
540 e.printStackTrace();
541 }
542
543 assertNotSame(
544 "Connection should have been given to someone",
545 getHost1.getConnection(),
546 getHost2.getConnection()
547 );
548 assertNotNull("Connection should have been given to host1", getHost1.getConnection());
549 assertNull("Connection should NOT have been given to host2", getHost2.getConnection());
550
551 }
552
553 public void testMaxConnectionsPerServer() {
554
555 MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
556 connectionManager.getParams().setIntParameter(
557 HttpConnectionManagerParams.MAX_HOST_CONNECTIONS, 1);
558
559 HttpClient client = createHttpClient(connectionManager);
560
561 client.getParams().setConnectionManagerTimeout( 1 );
562
563 GetMethod getMethod = new GetMethod("/");
564
565 try {
566 client.executeMethod(getMethod);
567 } catch (Exception e) {
568 fail("error reading from server: " + e);
569 }
570
571 GetMethod getMethod2 = new GetMethod("/");
572
573 try {
574
575 client.executeMethod(getMethod2);
576 fail("a httpConnection should not be available");
577 } catch (ConnectTimeoutException e) {
578 } catch (HttpException e) {
579 fail("error reading from server; " + e);
580 } catch (IOException e) {
581 fail("error reading from server; " + e);
582 }
583
584 }
585
586 public void testReclaimUnusedConnection() {
587
588 MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
589 connectionManager.getParams().setIntParameter(
590 HttpConnectionManagerParams.MAX_TOTAL_CONNECTIONS, 1);
591
592 HttpClient client = createHttpClient(connectionManager);
593
594 client.getParams().setConnectionManagerTimeout( 30000 );
595
596 GetMethod getMethod = new GetMethod("/");
597
598 try {
599 client.executeMethod(getMethod);
600 } catch (Exception e) {
601 fail("error reading from server: " + e);
602 }
603
604 getMethod = new GetMethod("/");
605
606 Runtime.getRuntime().gc();
607
608 try {
609
610
611 client.executeMethod(getMethod);
612 } catch (HttpException e) {
613 fail("httpConnection does not appear to have been reclaimed by the GC: " + e);
614 } catch (IOException e) {
615 fail("error reading from server; " + e);
616 }
617
618 }
619
620 public void testGetFromMultipleThreads() {
621
622 HttpClient client = createHttpClient(new MultiThreadedHttpConnectionManager());
623 ExecuteMethodThread[] threads = new ExecuteMethodThread[10];
624
625 for (int i = 0; i < threads.length; i++) {
626 GetMethod method = new GetMethod("/");
627 method.setFollowRedirects(true);
628
629 threads[i] = new ExecuteMethodThread(method, client);
630 threads[i].start();
631 }
632
633 for (int i = 0; i < threads.length; i++) {
634 try {
635
636
637 threads[i].join(10000);
638 } catch (InterruptedException e) {
639 }
640
641 Exception e = threads[i].getException();
642 if (e != null) {
643 fail("An error occured in the get: " + e);
644 }
645
646 assertEquals(threads[i].getMethod().getStatusCode(), HttpStatus.SC_OK);
647 }
648 }
649
650 public void testTimeout() {
651 MultiThreadedHttpConnectionManager mgr = new MultiThreadedHttpConnectionManager();
652 mgr.getParams().setIntParameter(
653 HttpConnectionManagerParams.MAX_HOST_CONNECTIONS, 2);
654
655 try{
656 HostConfiguration hostConfig = new HostConfiguration();
657 hostConfig.setHost("www.nosuchserver.com", 80, "http");
658
659 HttpConnection conn1 = mgr.getConnection(hostConfig);
660 HttpConnection conn2 = mgr.getConnection(hostConfig);
661
662 HttpConnection conn3 = mgr.getConnectionWithTimeout(hostConfig, 1000);
663 fail("Expected an HttpException.");
664
665 }catch(ConnectTimeoutException e){
666
667 }
668 }
669
670 static class FakeSecureProtocolSocketFactory implements SecureProtocolSocketFactory {
671
672 public Socket createSocket(Socket socket, String host, int port, boolean autoClose)
673 throws IOException, UnknownHostException {
674 throw new IllegalStateException("createSocket() should never have been called.");
675 }
676
677 public Socket createSocket(String host, int port)
678 throws IOException, UnknownHostException {
679 throw new IllegalStateException("createSocket() should never have been called.");
680 }
681
682 public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort)
683 throws IOException, UnknownHostException {
684 throw new IllegalStateException("createSocket() should never have been called.");
685 }
686
687 public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort,
688 HttpConnectionParams params)
689 throws IOException, UnknownHostException {
690 throw new IllegalStateException("createSocket() should never have been called.");
691 }
692 }
693
694 static class GetConnectionThread extends Thread {
695
696 private HostConfiguration hostConfiguration;
697 private MultiThreadedHttpConnectionManager connectionManager;
698 private HttpConnection connection;
699 private long timeout;
700 private Exception exception;
701
702 public GetConnectionThread(
703 HostConfiguration hostConfiguration,
704 MultiThreadedHttpConnectionManager connectionManager,
705 long timeout
706 ) {
707 this.hostConfiguration = hostConfiguration;
708 this.connectionManager = connectionManager;
709 this.timeout = timeout;
710 }
711
712 public void run() {
713 try {
714 connection = connectionManager.getConnectionWithTimeout(hostConfiguration, timeout);
715 } catch (Exception e) {
716 this.exception = e;
717 }
718 }
719
720 public Exception getException() {
721 return exception;
722 }
723
724 public HttpConnection getConnection() {
725 return connection;
726 }
727
728 }
729
730 }
731