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