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

This page was automatically generated by Maven