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