1 /*
2 * $Header: /home/cvs/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestHttpConnectionManager.java,v 1.8 2003/04/28 23:19:58 mbecke Exp $
3 * $Revision: 1.8 $
4 * $Date: 2003/04/28 23:19:58 $
5 * ====================================================================
6 *
7 * The Apache Software License, Version 1.1
8 *
9 * Copyright (c) 1999-2003 The Apache Software Foundation. All rights
10 * reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 *
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 *
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in
21 * the documentation and/or other materials provided with the
22 * distribution.
23 *
24 * 3. The end-user documentation included with the redistribution, if
25 * any, must include the following acknowlegement:
26 * "This product includes software developed by the
27 * Apache Software Foundation (http://www.apache.org/)."
28 * Alternately, this acknowlegement may appear in the software itself,
29 * if and wherever such third-party acknowlegements normally appear.
30 *
31 * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
32 * Foundation" must not be used to endorse or promote products derived
33 * from this software without prior written permission. For written
34 * permission, please contact apache@apache.org.
35 *
36 * 5. Products derived from this software may not be called "Apache"
37 * nor may "Apache" appear in their names without prior written
38 * permission of the Apache Group.
39 *
40 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
41 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
42 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
43 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
46 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
47 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
48 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
49 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
50 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 * ====================================================================
53 *
54 * This software consists of voluntary contributions made by many
55 * individuals on behalf of the Apache Software Foundation. For more
56 * information on the Apache Software Foundation, please see
57 * <http://www.apache.org/>.
58 *
59 * [Additional notices, if required by prior licensing conditions]
60 *
61 */
62
63 package org.apache.commons.httpclient;
64
65 import java.io.IOException;
66
67 import junit.framework.Test;
68 import junit.framework.TestSuite;
69
70 import org.apache.commons.httpclient.methods.GetMethod;
71
72 /***
73 * Unit tests for {@link HttpConnectionManager}.
74 *
75 * @author Marc A. Saegesser
76 * @version $Id: TestHttpConnectionManager.java,v 1.8 2003/04/28 23:19:58 mbecke Exp $
77 */
78 public class TestHttpConnectionManager extends TestLocalHostBase {
79
80 // ------------------------------------------------------------ Constructor
81 public TestHttpConnectionManager(String testName) {
82 super(testName);
83 }
84
85 // ------------------------------------------------------------------- Main
86 public static void main(String args[]) {
87 String[] testCaseName = { TestHttpConnectionManager.class.getName() };
88 junit.textui.TestRunner.main(testCaseName);
89 }
90
91 // ------------------------------------------------------- TestCase Methods
92
93 public static Test suite() {
94 return new TestSuite(TestHttpConnectionManager.class);
95 }
96
97
98 // ----------------------------------------------------------- Test Methods
99
100 // Test the accessor methods
101 public void testMaxConnectionsAccessors() {
102 MultiThreadedHttpConnectionManager mgr = new MultiThreadedHttpConnectionManager();
103
104 // First test the default value
105 assertEquals("Default MaxConnections", 2, mgr.getMaxConnectionsPerHost());
106
107 mgr.setMaxConnectionsPerHost(10);
108 assertEquals("MaxConnections", 10, mgr.getMaxConnectionsPerHost());
109 }
110
111 /***
112 * Test that the ConnectMethod correctly releases connections when
113 * CONNECT fails.
114 */
115 public void testConnectMethodFailureRelease() {
116
117 MultiThreadedHttpConnectionManager mgr = new MultiThreadedHttpConnectionManager();
118 mgr.setMaxTotalConnections(1);
119
120 // we're going to execute a connect method against the localhost, assuming
121 // that CONNECT is not supported. This should test the fakeResponse()
122 // code on HttpMethodBase.
123 HostConfiguration hostConfiguration = new HostConfiguration();
124 hostConfiguration.setHost(getHost(), getPort(), getProtocol());
125
126 GetMethod get = new GetMethod("/");
127 try {
128 HttpConnection connection = mgr.getConnection(hostConfiguration);
129 ConnectMethod connect = new ConnectMethod(get);
130 assertTrue(connect.execute(new HttpState(), connection) != 200);
131 } catch (IOException e) {
132 e.printStackTrace();
133 fail("Error executing connect: " + e);
134 }
135
136 // this should calling releaseConnection() releases the connection
137 try {
138 get.releaseConnection();
139 mgr.getConnection(hostConfiguration, 1).releaseConnection();
140 } catch (HttpException e1) {
141 fail("Connection should have been available.");
142 }
143
144 get = new GetMethod("/");
145
146 try {
147 HttpConnection connection = mgr.getConnection(hostConfiguration);
148 ConnectMethod connect = new ConnectMethod(get);
149 assertTrue(connect.execute(new HttpState(), connection) != 200);
150 } catch (IOException e) {
151 e.printStackTrace();
152 fail("Error executing connect: " + e);
153 }
154
155 // make sure reading the response fully releases the connection
156 try {
157 get.getResponseBodyAsString();
158 mgr.getConnection(hostConfiguration, 1).releaseConnection();
159 } catch (HttpException e1) {
160 fail("Connection should have been available.");
161 }
162
163 get = new GetMethod("/");
164
165 try {
166 HttpConnection connection = mgr.getConnection(hostConfiguration);
167 ConnectMethod connect = new ConnectMethod(get);
168 assertTrue(connect.execute(new HttpState(), connection) != 200);
169 } catch (IOException e) {
170 e.printStackTrace();
171 fail("Error executing connect: " + e);
172 }
173
174 // make sure closing the output stream releases the connection
175 try {
176 get.getResponseBodyAsStream().close();
177 mgr.getConnection(hostConfiguration, 1).releaseConnection();
178 } catch (HttpException e) {
179 fail("Connection should have been available.");
180 } catch (IOException e) {
181 e.printStackTrace();
182 fail("Close connection failed: " + e);
183 }
184 }
185
186 public void testGetConnection() {
187 MultiThreadedHttpConnectionManager mgr = new MultiThreadedHttpConnectionManager();
188
189 HostConfiguration hostConfiguration = new HostConfiguration();
190 hostConfiguration.setHost("www.nosuchserver.com", 80, "http");
191
192 // Create a new connection
193 HttpConnection conn = mgr.getConnection(hostConfiguration);
194 // Validate the connection properties
195 assertEquals("Host", "www.nosuchserver.com", conn.getHost());
196 assertEquals("Port", 80, conn.getPort());
197 // Release the connection
198 mgr.releaseConnection(conn);
199
200 // Create a new connection
201 hostConfiguration.setHost("www.nosuchserver.com", -1, "https");
202 conn = mgr.getConnection(hostConfiguration);
203 // Validate the connection properties
204 assertEquals("Host", "www.nosuchserver.com", conn.getHost());
205 assertEquals("Port", 443, conn.getPort());
206 // Release the connection
207 mgr.releaseConnection(conn);
208
209 // Create a new connection
210 hostConfiguration.setHost("www.nowhere.org", 8080, "http");
211 conn = mgr.getConnection(hostConfiguration);
212 // Validate the connection properties
213 assertEquals("Host", "www.nowhere.org", conn.getHost());
214 assertEquals("Port", 8080, conn.getPort());
215 // Release the connection
216 mgr.releaseConnection(conn);
217
218 }
219
220 public void testReleaseConnection() {
221
222 MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
223 connectionManager.setMaxConnectionsPerHost(1);
224
225 HttpClient client = createHttpClient(connectionManager);
226 // we shouldn't have to wait if a connection is available
227 client.setHttpConnectionFactoryTimeout( 1 );
228
229 GetMethod getMethod = new GetMethod("/");
230
231 try {
232 client.executeMethod(getMethod);
233 } catch (Exception e) {
234 fail("error reading from server: " + e);
235 }
236
237 try {
238 // this should fail quickly since the connection has not been released
239 client.executeMethod(getMethod);
240 fail("a httpConnection should not be available");
241 } catch (HttpException e) {
242 } catch (IOException e) {
243 fail("error reading from server; " + e);
244 }
245
246 // this should release the connection
247 getMethod.releaseConnection();
248
249 getMethod = new GetMethod("/");
250
251 try {
252 // this should fail quickly if the connection has not been released
253 client.executeMethod(getMethod);
254 } catch (HttpException e) {
255 fail("httpConnection does not appear to have been released: " + e);
256 } catch (IOException e) {
257 fail("error reading from server; " + e);
258 }
259
260 }
261
262 /***
263 * Makes sure that a connection gets released after the content of the body
264 * is read.
265 */
266 public void testResponseAutoRelease() {
267
268 MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
269 connectionManager.setMaxConnectionsPerHost(1);
270
271 HttpClient client = createHttpClient(connectionManager);
272 // we shouldn't have to wait if a connection is available
273 client.setHttpConnectionFactoryTimeout( 1 );
274
275 GetMethod getMethod = new GetMethod("/");
276
277 try {
278 client.executeMethod(getMethod);
279 } catch (Exception e) {
280 fail("error reading from server: " + e);
281 }
282
283 // this should release the connection
284 getMethod.getResponseBody();
285
286 getMethod = new GetMethod("/");
287
288 try {
289 // this should fail quickly if the connection has not been released
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 * Tests the MultiThreadedHttpConnectionManager's ability to reclaim unused
301 * connections.
302 */
303 public void testConnectionReclaiming() {
304
305 MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
306 connectionManager.setMaxConnectionsPerHost(1);
307 connectionManager.setMaxTotalConnections(1);
308
309 HostConfiguration host1 = new HostConfiguration();
310 host1.setHost("host1", -1, "http");
311
312 HostConfiguration host2 = new HostConfiguration();
313 host2.setHost("host2", -1, "http");
314
315 HttpConnection connection = connectionManager.getConnection(host1);
316 // now release this connection
317 connection.releaseConnection();
318 connection = null;
319
320 try {
321 // the connection from host1 should be reclaimed
322 connection = connectionManager.getConnection(host2, 100);
323 } catch (HttpException e) {
324 e.printStackTrace();
325 fail("a httpConnection should have been available: " + e);
326 }
327 }
328
329 /***
330 * Tests the MultiThreadedHttpConnectionManager's ability to restrict the maximum number
331 * of connections.
332 */
333 public void testMaxConnections() {
334
335 MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
336 connectionManager.setMaxConnectionsPerHost(1);
337 connectionManager.setMaxTotalConnections(2);
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 connection1 = connectionManager.getConnection(host1);
346 HttpConnection connection2 = connectionManager.getConnection(host2);
347
348 try {
349 // this should fail quickly since the connection has not been released
350 connectionManager.getConnection(host2, 100);
351 fail("a httpConnection should not be available");
352 } catch (HttpException e) {
353 // this should throw an exception
354 }
355
356 // release one of the connections
357 connection2.releaseConnection();
358 connection2 = null;
359
360 try {
361 // there should be a connection available now
362 connection2 = connectionManager.getConnection(host2, 100);
363 } catch (HttpException e) {
364 e.printStackTrace();
365 fail("a httpConnection should have been available: " + e);
366 }
367 }
368
369 public void testHostReusePreference() {
370
371 final MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
372 connectionManager.setMaxConnectionsPerHost(1);
373 connectionManager.setMaxTotalConnections(1);
374
375 final HostConfiguration host1 = new HostConfiguration();
376 host1.setHost("host1", -1, "http");
377
378 final HostConfiguration host2 = new HostConfiguration();
379 host2.setHost("host2", -1, "http");
380
381 HttpConnection connection = connectionManager.getConnection(host1);
382
383 GetConnectionThread getHost1 = new GetConnectionThread(host1, connectionManager, 200);
384 GetConnectionThread getHost2 = new GetConnectionThread(host2, connectionManager, 200);
385
386 getHost2.start();
387 getHost1.start();
388
389 // give the threads some time to startup
390 try {
391 Thread.sleep(100);
392 } catch (InterruptedException e1) {
393 e1.printStackTrace();
394 }
395
396 // after the connection to host1 is released it should be given to getHost1
397 connection.releaseConnection();
398 connection = null;
399
400 try {
401 getHost1.join();
402 getHost2.join();
403 } catch (InterruptedException e) {
404 e.printStackTrace();
405 }
406
407 assertNotSame(
408 "Connection should have been given to someone",
409 getHost1.getConnection(),
410 getHost2.getConnection()
411 );
412 assertNotNull("Connection should have been given to host1", getHost1.getConnection());
413 assertNull("Connection should NOT have been given to host2", getHost2.getConnection());
414
415 }
416
417 public void testMaxConnectionsPerServer() {
418
419 MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
420 connectionManager.setMaxConnectionsPerHost(1);
421
422 HttpClient client = createHttpClient(connectionManager);
423 // we shouldn't have to wait if a connection is available
424 client.setHttpConnectionFactoryTimeout( 1 );
425
426 GetMethod getMethod = new GetMethod("/");
427
428 try {
429 client.executeMethod(getMethod);
430 } catch (Exception e) {
431 fail("error reading from server: " + e);
432 }
433
434 GetMethod getMethod2 = new GetMethod("/");
435
436 try {
437 // this should fail quickly since the connection has not been released
438 client.executeMethod(getMethod2);
439 fail("a httpConnection should not be available");
440 } catch (HttpException e) {
441 } catch (IOException e) {
442 fail("error reading from server; " + e);
443 }
444
445 }
446
447 public void testReclaimUnusedConnection() {
448
449 MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
450 connectionManager.setMaxConnectionsPerHost(1);
451
452 HttpClient client = createHttpClient(connectionManager);
453 // we shouldn't have to wait if a connection is available
454 client.setHttpConnectionFactoryTimeout( 30000 );
455
456 GetMethod getMethod = new GetMethod("/");
457
458 try {
459 client.executeMethod(getMethod);
460 } catch (Exception e) {
461 fail("error reading from server: " + e);
462 }
463
464 getMethod = new GetMethod("/");
465
466 Runtime.getRuntime().gc();
467
468 try {
469 // we didn't explicitly release the connection, but it should be
470 // reclaimed by the garbage collector, we hope:)
471 client.executeMethod(getMethod);
472 } catch (HttpException e) {
473 fail("httpConnection does not appear to have been reclaimed by the GC: " + e);
474 } catch (IOException e) {
475 fail("error reading from server; " + e);
476 }
477
478 }
479
480 public void testGetFromMultipleThreads() {
481
482 HttpClient client = createHttpClient(new MultiThreadedHttpConnectionManager());
483 ExecuteMethodThread[] threads = new ExecuteMethodThread[10];
484
485 for (int i = 0; i < threads.length; i++) {
486 GetMethod method = new GetMethod("/");
487 method.setFollowRedirects(true);
488
489 threads[i] = new ExecuteMethodThread(method, client);
490 threads[i].start();
491 }
492
493 for (int i = 0; i < threads.length; i++) {
494 try {
495 // wait until this thread finishes. we'll give it 10 seconds,
496 // but it shouldn't take that long
497 threads[i].join(10000);
498 } catch (InterruptedException e) {
499 }
500 // make sure an exception did not occur
501 Exception e = threads[i].getException();
502 if (e != null) {
503 fail("An error occured in the get: " + e);
504 }
505 // we should have a 200 status
506 assertEquals(threads[i].getMethod().getStatusCode(), HttpStatus.SC_OK);
507 }
508 }
509
510 public void testTimeout() {
511 MultiThreadedHttpConnectionManager mgr = new MultiThreadedHttpConnectionManager();
512 mgr.setMaxConnectionsPerHost(2);
513
514 try{
515 HostConfiguration hostConfig = new HostConfiguration();
516 hostConfig.setHost("www.nosuchserver.com", 80, "http");
517
518 HttpConnection conn1 = mgr.getConnection(hostConfig);
519 HttpConnection conn2 = mgr.getConnection(hostConfig);
520
521 HttpConnection conn3 = mgr.getConnection(hostConfig, 1000);
522 fail("Expected an HttpException.");
523
524 }catch(HttpException e){
525 //Expected result
526 }
527 }
528
529 static class GetConnectionThread extends Thread {
530
531 private HostConfiguration hostConfiguration;
532 private MultiThreadedHttpConnectionManager connectionManager;
533 private HttpConnection connection;
534 private long timeout;
535
536 public GetConnectionThread(
537 HostConfiguration hostConfiguration,
538 MultiThreadedHttpConnectionManager connectionManager,
539 long timeout
540 ) {
541 this.hostConfiguration = hostConfiguration;
542 this.connectionManager = connectionManager;
543 this.timeout = timeout;
544 }
545
546 public void run() {
547 try {
548 connection = connectionManager.getConnection(hostConfiguration, timeout);
549 } catch (HttpException e) {
550 }
551 }
552
553 public HttpConnection getConnection() {
554 return connection;
555 }
556
557 }
558
559 }
560
This page was automatically generated by Maven