1   /*
2    * $HeadURL: https://svn.apache.org/repos/asf/httpcomponents/oac.hc3x/trunk/src/test/org/apache/commons/httpclient/TestHttpConnection.java $
3    * $Revision: 1425331 $
4    * $Date: 2012-12-22 19:29:41 +0100 (Sat, 22 Dec 2012) $
5    * ====================================================================
6    *
7    *  Licensed to the Apache Software Foundation (ASF) under one or more
8    *  contributor license agreements.  See the NOTICE file distributed with
9    *  this work for additional information regarding copyright ownership.
10   *  The ASF licenses this file to You under the Apache License, Version 2.0
11   *  (the "License"); you may not use this file except in compliance with
12   *  the License.  You may obtain a copy of the License at
13   *
14   *      http://www.apache.org/licenses/LICENSE-2.0
15   *
16   *  Unless required by applicable law or agreed to in writing, software
17   *  distributed under the License is distributed on an "AS IS" BASIS,
18   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19   *  See the License for the specific language governing permissions and
20   *  limitations under the License.
21   * ====================================================================
22   *
23   * This software consists of voluntary contributions made by many
24   * individuals on behalf of the Apache Software Foundation.  For more
25   * information on the Apache Software Foundation, please see
26   * <http://www.apache.org/>.
27   *
28   * [Additional notices, if required by prior licensing conditions]
29   *
30   */
31  
32  package org.apache.commons.httpclient;
33  
34  import java.io.IOException;
35  import java.io.InputStream;
36  import java.io.OutputStream;
37  import java.net.InetAddress;
38  import java.net.Socket;
39  import java.net.UnknownHostException;
40  
41  import junit.framework.Test;
42  import junit.framework.TestSuite;
43  
44  import org.apache.commons.httpclient.methods.GetMethod;
45  import org.apache.commons.httpclient.params.HttpConnectionParams;
46  import org.apache.commons.httpclient.protocol.Protocol;
47  import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
48  import org.apache.commons.httpclient.protocol.ControllerThreadSocketFactory;
49  
50  /***
51   *
52   * Unit tests for {@link HttpConnection}.
53   *
54   * @author Sean C. Sullivan
55   *
56   * @version $Id: TestHttpConnection.java 608018 2008-01-02 05:57:23Z rolandw $
57   *
58   */
59  public class TestHttpConnection extends HttpClientTestBase {
60      
61      // ------------------------------------------------------------ Constructor
62      public TestHttpConnection(String testName) throws Exception {
63          super(testName);
64      }
65  
66      // ------------------------------------------------------------------- Main
67      public static void main(String args[]) {
68          String[] testCaseName = { TestHttpConnection.class.getName() };
69          junit.textui.TestRunner.main(testCaseName);
70      }
71  
72      // ------------------------------------------------------- TestCase Methods
73  
74      public static Test suite() {
75          return new TestSuite(TestHttpConnection.class);
76      }
77  
78  
79      // ----------------------------------------------------------- Test Methods
80  
81      public void testConstructThenClose() {
82  		this.server.setHttpService(new EchoService());
83          HttpConnection conn = new HttpConnection(
84  				this.server.getLocalAddress(), this.server.getLocalPort());
85          conn.close();
86          assertTrue(!conn.isOpen());
87      }
88  
89      public void testConnTimeoutRelease() {
90  		this.server.setHttpService(new EchoService());
91          // create a custom protocol that will delay for 500 milliseconds
92          Protocol testProtocol = new Protocol(
93              "timeout",
94              new DelayedProtocolSocketFactory(
95                  500, 
96                  Protocol.getProtocol("http").getSocketFactory()
97              ),
98  			this.server.getLocalPort()
99          );
100 
101         NoHostHttpConnectionManager connectionManager = new NoHostHttpConnectionManager();
102         connectionManager.setConnection(
103 				new HttpConnection(
104 						this.server.getLocalAddress(), this.server.getLocalPort(), testProtocol));
105         this.client.setHttpConnectionManager(connectionManager);
106         client.getHostConfiguration().setHost(
107 				this.server.getLocalAddress(), this.server.getLocalPort(), testProtocol);
108         client.getHttpConnectionManager().getParams().setConnectionTimeout(1);
109         
110         try {
111             GetMethod get = new GetMethod();
112             client.executeMethod(get);
113             fail("Should have timed out");
114         } catch(IOException e) {
115             /* should fail */
116             assertTrue(e instanceof ConnectTimeoutException);
117             assertTrue(connectionManager.isConnectionReleased());
118         }
119     }
120 
121 
122     public void testConnTimeout() {
123 
124         // create a custom protocol that will delay for 500 milliseconds
125         Protocol testProtocol = new Protocol(
126             "timeout",
127             new DelayedProtocolSocketFactory(
128                 500, 
129                 Protocol.getProtocol("http").getSocketFactory()
130             ),
131 			this.server.getLocalPort()
132         );
133 
134         HttpConnection conn = new HttpConnection(
135 				this.server.getLocalAddress(), this.server.getLocalPort(), testProtocol);
136         // 1 ms is short enough to make this fail
137         conn.getParams().setConnectionTimeout(1);
138         try {
139             conn.open();
140             fail("Should have timed out");
141         } catch(IOException e) {
142             assertTrue(e instanceof ConnectTimeoutException);
143             /* should fail */
144         }
145     }
146 
147     public void testForIllegalStateExceptions() {
148         HttpConnection conn = new HttpConnection(
149 				this.server.getLocalAddress(), this.server.getLocalPort());
150         try {
151             OutputStream out = conn.getRequestOutputStream();
152             fail("getRequestOutputStream did not throw the expected exception");
153         }
154         catch (IllegalStateException expected) {
155             // this exception is expected
156         }
157         catch (IOException ex) {
158             fail("getRequestOutputStream did not throw the expected exception");
159         }
160 
161         try {
162             OutputStream out = new ChunkedOutputStream(conn.getRequestOutputStream());
163             fail("getRequestOutputStream(true) did not throw the expected exception");
164         }
165         catch (IllegalStateException expected) {
166             // this exception is expected
167         }
168         catch (IOException ex) {
169             fail("getRequestOutputStream(true) did not throw the expected exception");
170         }
171 
172         try {
173             InputStream in = conn.getResponseInputStream();
174             fail("getResponseInputStream() did not throw the expected exception");
175         }
176         catch (IllegalStateException expected) {
177             // this exception is expected
178         }
179         catch (IOException ex) {
180             fail("getResponseInputStream() did not throw the expected exception");
181         }
182 
183     }
184     
185     /***
186      * A ProtocolSocketFactory that delays before creating a socket.
187      */
188     class DelayedProtocolSocketFactory implements ProtocolSocketFactory {
189         
190         private int delay;
191         private ProtocolSocketFactory realFactory;
192             
193         public DelayedProtocolSocketFactory(int delay, ProtocolSocketFactory realFactory) {
194             this.delay = delay;
195             this.realFactory = realFactory;            
196         }
197                 
198         public Socket createSocket(
199             String host,
200             int port,
201             InetAddress localAddress,
202             int localPort
203         ) throws IOException, UnknownHostException {
204             
205             synchronized (this) {
206                 try {
207                     this.wait(delay);
208                 } catch (InterruptedException e) {}
209             }
210             return realFactory.createSocket(host, port, localAddress, localPort);
211         }
212 
213         public Socket createSocket(
214             final String host,
215             final int port,
216             final InetAddress localAddress,
217             final int localPort,
218             final HttpConnectionParams params
219         ) throws IOException, UnknownHostException {
220             
221             if (params == null) {
222                 throw new IllegalArgumentException("Parameters may not be null");
223             }
224             int timeout = params.getConnectionTimeout();
225             ControllerThreadSocketFactory.SocketTask task = new ControllerThreadSocketFactory.SocketTask() {
226                 public void doit() throws IOException {
227                     synchronized (this) {
228                         try {
229                             this.wait(delay);
230                         } catch (InterruptedException e) {}
231                     }
232                     setSocket(realFactory.createSocket(host, port, localAddress, localPort));
233                 }
234             };
235             return ControllerThreadSocketFactory.createSocket(task, timeout);
236         }
237 
238         public Socket createSocket(String host, int port)
239             throws IOException, UnknownHostException {
240             synchronized (this) {
241                 try {
242                     this.wait(delay);
243                 } catch (InterruptedException e) {}
244             }
245             return realFactory.createSocket(host, port);
246         }
247 
248     }
249 
250 }
251