View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  package org.apache.http.impl;
28  
29  import java.io.ByteArrayInputStream;
30  import java.io.InputStream;
31  import java.io.OutputStream;
32  import java.net.InetAddress;
33  import java.net.InetSocketAddress;
34  import java.net.Socket;
35  import java.net.SocketException;
36  import java.net.SocketTimeoutException;
37  
38  import org.apache.http.Header;
39  import org.apache.http.HttpEntity;
40  import org.apache.http.HttpResponse;
41  import org.apache.http.HttpVersion;
42  import org.apache.http.config.MessageConstraints;
43  import org.apache.http.impl.entity.LaxContentLengthStrategy;
44  import org.apache.http.impl.entity.StrictContentLengthStrategy;
45  import org.apache.http.impl.io.ChunkedInputStream;
46  import org.apache.http.impl.io.ChunkedOutputStream;
47  import org.apache.http.impl.io.ContentLengthInputStream;
48  import org.apache.http.impl.io.ContentLengthOutputStream;
49  import org.apache.http.impl.io.IdentityInputStream;
50  import org.apache.http.impl.io.IdentityOutputStream;
51  import org.apache.http.message.BasicHttpResponse;
52  import org.junit.Assert;
53  import org.junit.Before;
54  import org.junit.Test;
55  import org.mockito.Mock;
56  import org.mockito.Mockito;
57  import org.mockito.MockitoAnnotations;
58  
59  public class TestBHttpConnectionBase {
60  
61      @Mock
62      private Socket socket;
63  
64      private BHttpConnectionBase conn;
65  
66      @Before
67      public void setUp() throws Exception {
68          MockitoAnnotations.initMocks(this);
69          conn = new BHttpConnectionBase(1024, 1024,
70              null, null,
71              MessageConstraints.DEFAULT,
72              LaxContentLengthStrategy.INSTANCE,
73              StrictContentLengthStrategy.INSTANCE);
74      }
75  
76      @Test
77      public void testBasics() throws Exception {
78          Assert.assertFalse(conn.isOpen());
79          Assert.assertEquals(-1, conn.getLocalPort());
80          Assert.assertEquals(-1, conn.getRemotePort());
81          Assert.assertEquals(null, conn.getLocalAddress());
82          Assert.assertEquals(null, conn.getRemoteAddress());
83          Assert.assertEquals("[Not bound]", conn.toString());
84      }
85  
86      @Test
87      public void testSocketBind() throws Exception {
88          final InetAddress localAddress = InetAddress.getByAddress(new byte[] {127, 0, 0, 1});
89          final int localPort = 8888;
90          final InetAddress remoteAddress = InetAddress.getByAddress(new byte[] {10, 0, 0, 2});
91          final int remotePort = 80;
92          final InetSocketAddress localSockAddress = new InetSocketAddress(localAddress, localPort);
93          final InetSocketAddress remoteSockAddress = new InetSocketAddress(remoteAddress, remotePort);
94          Mockito.when(socket.getLocalSocketAddress()).thenReturn(localSockAddress);
95          Mockito.when(socket.getRemoteSocketAddress()).thenReturn(remoteSockAddress);
96          Mockito.when(socket.getLocalAddress()).thenReturn(localAddress);
97          Mockito.when(socket.getLocalPort()).thenReturn(localPort);
98          Mockito.when(socket.getInetAddress()).thenReturn(remoteAddress);
99          Mockito.when(socket.getPort()).thenReturn(remotePort);
100         conn.bind(socket);
101 
102         Assert.assertEquals("127.0.0.1:8888<->10.0.0.2:80", conn.toString());
103         Assert.assertTrue(conn.isOpen());
104         Assert.assertEquals(8888, conn.getLocalPort());
105         Assert.assertEquals(80, conn.getRemotePort());
106         Assert.assertEquals(InetAddress.getByAddress(new byte[] {127, 0, 0, 1}), conn.getLocalAddress());
107         Assert.assertEquals(InetAddress.getByAddress(new byte[] {10, 0, 0, 2}), conn.getRemoteAddress());
108     }
109 
110     @Test
111     public void testConnectionClose() throws Exception {
112         final InputStream instream = Mockito.mock(InputStream.class);
113         final OutputStream outstream = Mockito.mock(OutputStream.class);
114 
115         Mockito.when(socket.getInputStream()).thenReturn(instream);
116         Mockito.when(socket.getOutputStream()).thenReturn(outstream);
117 
118         conn.bind(socket);
119         conn.ensureOpen();
120         conn.getSessionOutputBuffer().write(0);
121 
122         Assert.assertTrue(conn.isOpen());
123 
124         conn.close();
125 
126         Assert.assertFalse(conn.isOpen());
127 
128         Mockito.verify(outstream, Mockito.times(1)).write(
129                 Mockito.<byte []>any(), Mockito.anyInt(), Mockito.anyInt());
130         Mockito.verify(socket, Mockito.times(1)).shutdownInput();
131         Mockito.verify(socket, Mockito.times(1)).shutdownOutput();
132         Mockito.verify(socket, Mockito.times(1)).close();
133 
134         conn.close();
135         Mockito.verify(socket, Mockito.times(1)).close();
136         Mockito.verify(outstream, Mockito.times(1)).write(
137                 Mockito.<byte []>any(), Mockito.anyInt(), Mockito.anyInt());
138     }
139 
140     @Test
141     public void testConnectionShutdown() throws Exception {
142         final InputStream instream = Mockito.mock(InputStream.class);
143         final OutputStream outstream = Mockito.mock(OutputStream.class);
144         Mockito.when(socket.getInputStream()).thenReturn(instream);
145         Mockito.when(socket.getOutputStream()).thenReturn(outstream);
146 
147         conn.bind(socket);
148         conn.ensureOpen();
149         conn.getSessionOutputBuffer().write(0);
150 
151         Assert.assertTrue(conn.isOpen());
152 
153         conn.shutdown();
154 
155         Assert.assertFalse(conn.isOpen());
156 
157         Mockito.verify(outstream, Mockito.never()).write(
158                 Mockito.<byte []>any(), Mockito.anyInt(), Mockito.anyInt());
159         Mockito.verify(socket, Mockito.never()).shutdownInput();
160         Mockito.verify(socket, Mockito.never()).shutdownOutput();
161         Mockito.verify(socket, Mockito.times(1)).close();
162 
163         conn.close();
164         Mockito.verify(socket, Mockito.times(1)).close();
165 
166         conn.shutdown();
167         Mockito.verify(socket, Mockito.times(1)).close();
168     }
169 
170     @Test
171     public void testPrepareInputLengthDelimited() throws Exception {
172         final HttpResponse message = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
173         message.addHeader("Content-Length", "10");
174         message.addHeader("Content-Type", "stuff");
175         message.addHeader("Content-Encoding", "identity");
176         final HttpEntity entity = conn.prepareInput(message);
177         Assert.assertNotNull(entity);
178         Assert.assertFalse(entity.isChunked());
179         Assert.assertEquals(10, entity.getContentLength());
180         final Header ct = entity.getContentType();
181         Assert.assertNotNull(ct);
182         Assert.assertEquals("stuff", ct.getValue());
183         final Header ce = entity.getContentEncoding();
184         Assert.assertNotNull(ce);
185         Assert.assertEquals("identity", ce.getValue());
186         final InputStream instream = entity.getContent();
187         Assert.assertNotNull(instream);
188         Assert.assertTrue((instream instanceof ContentLengthInputStream));
189     }
190 
191     @Test
192     public void testPrepareInputChunked() throws Exception {
193         final HttpResponse message = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
194         message.addHeader("Transfer-Encoding", "chunked");
195         final HttpEntity entity = conn.prepareInput(message);
196         Assert.assertNotNull(entity);
197         Assert.assertTrue(entity.isChunked());
198         Assert.assertEquals(-1, entity.getContentLength());
199         final InputStream instream = entity.getContent();
200         Assert.assertNotNull(instream);
201         Assert.assertTrue((instream instanceof ChunkedInputStream));
202     }
203 
204     @Test
205     public void testPrepareInputIdentity() throws Exception {
206         final HttpResponse message = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
207         final HttpEntity entity = conn.prepareInput(message);
208         Assert.assertNotNull(entity);
209         Assert.assertFalse(entity.isChunked());
210         Assert.assertEquals(-1, entity.getContentLength());
211         final InputStream instream = entity.getContent();
212         Assert.assertNotNull(instream);
213         Assert.assertTrue((instream instanceof IdentityInputStream));
214     }
215 
216     @Test
217     public void testPrepareOutputLengthDelimited() throws Exception {
218         final HttpResponse message = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
219         message.addHeader("Content-Length", "10");
220         final OutputStream outstream = conn.prepareOutput(message);
221         Assert.assertNotNull(outstream);
222         Assert.assertTrue((outstream instanceof ContentLengthOutputStream));
223     }
224 
225     @Test
226     public void testPrepareOutputChunked() throws Exception {
227         final HttpResponse message = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
228         message.addHeader("Transfer-Encoding", "chunked");
229         final OutputStream outstream = conn.prepareOutput(message);
230         Assert.assertNotNull(outstream);
231         Assert.assertTrue((outstream instanceof ChunkedOutputStream));
232     }
233 
234     @Test
235     public void testPrepareOutputIdentity() throws Exception {
236         final HttpResponse message = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
237         final OutputStream outstream = conn.prepareOutput(message);
238         Assert.assertNotNull(outstream);
239         Assert.assertTrue((outstream instanceof IdentityOutputStream));
240     }
241 
242     @Test
243     public void testSetSocketTimeout() throws Exception {
244         conn.bind(socket);
245 
246         conn.setSocketTimeout(123);
247 
248         Mockito.verify(socket, Mockito.times(1)).setSoTimeout(123);
249     }
250 
251     @Test
252     public void testSetSocketTimeoutException() throws Exception {
253         conn.bind(socket);
254 
255         Mockito.doThrow(new SocketException()).when(socket).setSoTimeout(Mockito.anyInt());
256 
257         conn.setSocketTimeout(123);
258 
259         Mockito.verify(socket, Mockito.times(1)).setSoTimeout(123);
260     }
261 
262     @Test
263     public void testGetSocketTimeout() throws Exception {
264         Assert.assertEquals(-1, conn.getSocketTimeout());
265 
266         Mockito.when(socket.getSoTimeout()).thenReturn(345);
267         conn.bind(socket);
268 
269         Assert.assertEquals(345, conn.getSocketTimeout());
270     }
271 
272     @Test
273     public void testGetSocketTimeoutException() throws Exception {
274         Assert.assertEquals(-1, conn.getSocketTimeout());
275 
276         Mockito.when(socket.getSoTimeout()).thenThrow(new SocketException());
277         conn.bind(socket);
278 
279         Assert.assertEquals(-1, conn.getSocketTimeout());
280     }
281 
282     @Test
283     public void testAwaitInputInBuffer() throws Exception {
284         final ByteArrayInputStream instream = Mockito.spy(new ByteArrayInputStream(
285                 new byte[] {1, 2, 3, 4, 5}));
286         Mockito.when(socket.getInputStream()).thenReturn(instream);
287 
288         conn.bind(socket);
289         conn.ensureOpen();
290         conn.getSessionInputBuffer().read();
291 
292         Assert.assertTrue(conn.awaitInput(432));
293 
294         Mockito.verify(socket, Mockito.never()).setSoTimeout(Mockito.anyInt());
295         Mockito.verify(instream, Mockito.times(1)).read(
296                 Mockito.<byte []>any(), Mockito.anyInt(), Mockito.anyInt());
297     }
298 
299     @Test
300     public void testAwaitInputInSocket() throws Exception {
301         final ByteArrayInputStream instream = Mockito.spy(new ByteArrayInputStream(
302                 new byte[] {1, 2, 3, 4, 5}));
303         Mockito.when(socket.getInputStream()).thenReturn(instream);
304         Mockito.when(socket.getSoTimeout()).thenReturn(345);
305 
306         conn.bind(socket);
307         conn.ensureOpen();
308 
309         Assert.assertTrue(conn.awaitInput(432));
310 
311         Mockito.verify(socket, Mockito.times(1)).setSoTimeout(432);
312         Mockito.verify(socket, Mockito.times(1)).setSoTimeout(345);
313         Mockito.verify(instream, Mockito.times(1)).read(
314                 Mockito.<byte []>any(), Mockito.anyInt(), Mockito.anyInt());
315     }
316 
317     @Test
318     public void testAwaitInputNoData() throws Exception {
319         final InputStream instream = Mockito.mock(InputStream.class);
320         Mockito.when(socket.getInputStream()).thenReturn(instream);
321         Mockito.when(instream.read(Mockito.<byte []>any(), Mockito.anyInt(), Mockito.anyInt()))
322             .thenReturn(-1);
323 
324         conn.bind(socket);
325         conn.ensureOpen();
326 
327         Assert.assertFalse(conn.awaitInput(432));
328     }
329 
330     @Test
331     public void testStaleWhenClosed() throws Exception {
332         conn.bind(socket);
333         conn.ensureOpen();
334         conn.close();
335         Assert.assertTrue(conn.isStale());
336     }
337 
338     @Test
339     public void testNotStaleWhenHasData() throws Exception {
340         final ByteArrayInputStream instream = Mockito.spy(new ByteArrayInputStream(
341                 new byte[] {1, 2, 3, 4, 5}));
342         Mockito.when(socket.getInputStream()).thenReturn(instream);
343 
344         conn.bind(socket);
345         conn.ensureOpen();
346 
347         Assert.assertFalse(conn.isStale());
348     }
349 
350     @Test
351     public void testStaleWhenEndOfStream() throws Exception {
352         final InputStream instream = Mockito.mock(InputStream.class);
353         Mockito.when(socket.getInputStream()).thenReturn(instream);
354         Mockito.when(instream.read(Mockito.<byte []>any(), Mockito.anyInt(), Mockito.anyInt()))
355             .thenReturn(-1);
356 
357         conn.bind(socket);
358         conn.ensureOpen();
359 
360         Assert.assertTrue(conn.isStale());
361     }
362 
363     @Test
364     public void testNotStaleWhenTimeout() throws Exception {
365         final InputStream instream = Mockito.mock(InputStream.class);
366         Mockito.when(socket.getInputStream()).thenReturn(instream);
367         Mockito.when(instream.read(Mockito.<byte []>any(), Mockito.anyInt(), Mockito.anyInt()))
368             .thenThrow(new SocketTimeoutException());
369 
370         conn.bind(socket);
371         conn.ensureOpen();
372 
373         Assert.assertFalse(conn.isStale());
374     }
375 
376     @Test
377     public void testStaleWhenIOError() throws Exception {
378         final InputStream instream = Mockito.mock(InputStream.class);
379         Mockito.when(socket.getInputStream()).thenReturn(instream);
380         Mockito.when(instream.read(Mockito.<byte []>any(), Mockito.anyInt(), Mockito.anyInt()))
381             .thenThrow(new SocketException());
382 
383         conn.bind(socket);
384         conn.ensureOpen();
385 
386         Assert.assertTrue(conn.isStale());
387     }
388 
389 }