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.Matchers;
56  import org.mockito.Mock;
57  import org.mockito.Mockito;
58  import org.mockito.MockitoAnnotations;
59  
60  public class TestBHttpConnectionBase {
61  
62      @Mock
63      private Socket socket;
64  
65      private BHttpConnectionBase conn;
66  
67      @Before
68      public void setUp() throws Exception {
69          MockitoAnnotations.initMocks(this);
70          conn = new BHttpConnectionBase(1024, 1024,
71              null, null,
72              MessageConstraints.DEFAULT,
73              LaxContentLengthStrategy.INSTANCE,
74              StrictContentLengthStrategy.INSTANCE);
75      }
76  
77      @Test
78      public void testBasics() throws Exception {
79          Assert.assertFalse(conn.isOpen());
80          Assert.assertEquals(-1, conn.getLocalPort());
81          Assert.assertEquals(-1, conn.getRemotePort());
82          Assert.assertEquals(null, conn.getLocalAddress());
83          Assert.assertEquals(null, conn.getRemoteAddress());
84          Assert.assertEquals("[Not bound]", conn.toString());
85      }
86  
87      @Test
88      public void testSocketBind() throws Exception {
89          final InetAddress localAddress = InetAddress.getByAddress(new byte[] {127, 0, 0, 1});
90          final int localPort = 8888;
91          final InetAddress remoteAddress = InetAddress.getByAddress(new byte[] {10, 0, 0, 2});
92          final int remotePort = 80;
93          final InetSocketAddress localSockAddress = new InetSocketAddress(localAddress, localPort);
94          final InetSocketAddress remoteSockAddress = new InetSocketAddress(remoteAddress, remotePort);
95          Mockito.when(socket.getLocalSocketAddress()).thenReturn(localSockAddress);
96          Mockito.when(socket.getRemoteSocketAddress()).thenReturn(remoteSockAddress);
97          Mockito.when(socket.getLocalAddress()).thenReturn(localAddress);
98          Mockito.when(socket.getLocalPort()).thenReturn(localPort);
99          Mockito.when(socket.getInetAddress()).thenReturn(remoteAddress);
100         Mockito.when(socket.getPort()).thenReturn(remotePort);
101         conn.bind(socket);
102 
103         Assert.assertEquals("127.0.0.1:8888<->10.0.0.2:80", conn.toString());
104         Assert.assertTrue(conn.isOpen());
105         Assert.assertEquals(8888, conn.getLocalPort());
106         Assert.assertEquals(80, conn.getRemotePort());
107         Assert.assertEquals(InetAddress.getByAddress(new byte[] {127, 0, 0, 1}), conn.getLocalAddress());
108         Assert.assertEquals(InetAddress.getByAddress(new byte[] {10, 0, 0, 2}), conn.getRemoteAddress());
109     }
110 
111     @Test
112     public void testConnectionClose() throws Exception {
113         final InputStream inStream = Mockito.mock(InputStream.class);
114         final OutputStream outStream = Mockito.mock(OutputStream.class);
115 
116         Mockito.when(socket.getInputStream()).thenReturn(inStream);
117         Mockito.when(socket.getOutputStream()).thenReturn(outStream);
118 
119         conn.bind(socket);
120         conn.ensureOpen();
121         conn.getSessionOutputBuffer().write(0);
122 
123         Assert.assertTrue(conn.isOpen());
124 
125         conn.close();
126 
127         Assert.assertFalse(conn.isOpen());
128 
129         Mockito.verify(outStream, Mockito.times(1)).write(
130                 Matchers.<byte []>any(), Matchers.anyInt(), Matchers.anyInt());
131         Mockito.verify(socket, Mockito.times(1)).shutdownInput();
132         Mockito.verify(socket, Mockito.times(1)).shutdownOutput();
133         Mockito.verify(socket, Mockito.times(1)).close();
134 
135         conn.close();
136         Mockito.verify(socket, Mockito.times(1)).close();
137         Mockito.verify(outStream, Mockito.times(1)).write(
138                 Matchers.<byte []>any(), Matchers.anyInt(), Matchers.anyInt());
139     }
140 
141     @Test
142     public void testConnectionShutdown() throws Exception {
143         final InputStream inStream = Mockito.mock(InputStream.class);
144         final OutputStream outStream = Mockito.mock(OutputStream.class);
145         Mockito.when(socket.getInputStream()).thenReturn(inStream);
146         Mockito.when(socket.getOutputStream()).thenReturn(outStream);
147 
148         conn.bind(socket);
149         conn.ensureOpen();
150         conn.getSessionOutputBuffer().write(0);
151 
152         Assert.assertTrue(conn.isOpen());
153 
154         conn.shutdown();
155 
156         Assert.assertFalse(conn.isOpen());
157 
158         Mockito.verify(outStream, Mockito.never()).write(
159                 Matchers.<byte []>any(), Matchers.anyInt(), Matchers.anyInt());
160         Mockito.verify(socket, Mockito.never()).shutdownInput();
161         Mockito.verify(socket, Mockito.never()).shutdownOutput();
162         Mockito.verify(socket, Mockito.times(1)).close();
163 
164         conn.close();
165         Mockito.verify(socket, Mockito.times(1)).close();
166 
167         conn.shutdown();
168         Mockito.verify(socket, Mockito.times(1)).close();
169     }
170 
171     @Test
172     public void testPrepareInputLengthDelimited() throws Exception {
173         final HttpResponse message = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
174         message.addHeader("Content-Length", "10");
175         message.addHeader("Content-Type", "stuff");
176         message.addHeader("Content-Encoding", "identity");
177         final HttpEntity entity = conn.prepareInput(message);
178         Assert.assertNotNull(entity);
179         Assert.assertFalse(entity.isChunked());
180         Assert.assertEquals(10, entity.getContentLength());
181         final Header ct = entity.getContentType();
182         Assert.assertNotNull(ct);
183         Assert.assertEquals("stuff", ct.getValue());
184         final Header ce = entity.getContentEncoding();
185         Assert.assertNotNull(ce);
186         Assert.assertEquals("identity", ce.getValue());
187         final InputStream inStream = entity.getContent();
188         Assert.assertNotNull(inStream);
189         Assert.assertTrue((inStream instanceof ContentLengthInputStream));
190     }
191 
192     @Test
193     public void testPrepareInputChunked() throws Exception {
194         final HttpResponse message = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
195         message.addHeader("Transfer-Encoding", "chunked");
196         final HttpEntity entity = conn.prepareInput(message);
197         Assert.assertNotNull(entity);
198         Assert.assertTrue(entity.isChunked());
199         Assert.assertEquals(-1, entity.getContentLength());
200         final InputStream inStream = entity.getContent();
201         Assert.assertNotNull(inStream);
202         Assert.assertTrue((inStream instanceof ChunkedInputStream));
203     }
204 
205     @Test
206     public void testPrepareInputIdentity() throws Exception {
207         final HttpResponse message = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
208         final HttpEntity entity = conn.prepareInput(message);
209         Assert.assertNotNull(entity);
210         Assert.assertFalse(entity.isChunked());
211         Assert.assertEquals(-1, entity.getContentLength());
212         final InputStream inStream = entity.getContent();
213         Assert.assertNotNull(inStream);
214         Assert.assertTrue((inStream instanceof IdentityInputStream));
215     }
216 
217     @Test
218     public void testPrepareOutputLengthDelimited() throws Exception {
219         final HttpResponse message = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
220         message.addHeader("Content-Length", "10");
221         final OutputStream outStream = conn.prepareOutput(message);
222         Assert.assertNotNull(outStream);
223         Assert.assertTrue((outStream instanceof ContentLengthOutputStream));
224     }
225 
226     @Test
227     public void testPrepareOutputChunked() throws Exception {
228         final HttpResponse message = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
229         message.addHeader("Transfer-Encoding", "chunked");
230         final OutputStream outStream = conn.prepareOutput(message);
231         Assert.assertNotNull(outStream);
232         Assert.assertTrue((outStream instanceof ChunkedOutputStream));
233     }
234 
235     @Test
236     public void testPrepareOutputIdentity() throws Exception {
237         final HttpResponse message = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
238         final OutputStream outStream = conn.prepareOutput(message);
239         Assert.assertNotNull(outStream);
240         Assert.assertTrue((outStream instanceof IdentityOutputStream));
241     }
242 
243     @Test
244     public void testSetSocketTimeout() throws Exception {
245         conn.bind(socket);
246 
247         conn.setSocketTimeout(123);
248 
249         Mockito.verify(socket, Mockito.times(1)).setSoTimeout(123);
250     }
251 
252     @Test
253     public void testSetSocketTimeoutException() throws Exception {
254         conn.bind(socket);
255 
256         Mockito.doThrow(new SocketException()).when(socket).setSoTimeout(Matchers.anyInt());
257 
258         conn.setSocketTimeout(123);
259 
260         Mockito.verify(socket, Mockito.times(1)).setSoTimeout(123);
261     }
262 
263     @Test
264     public void testGetSocketTimeout() throws Exception {
265         Assert.assertEquals(-1, conn.getSocketTimeout());
266 
267         Mockito.when(socket.getSoTimeout()).thenReturn(345);
268         conn.bind(socket);
269 
270         Assert.assertEquals(345, conn.getSocketTimeout());
271     }
272 
273     @Test
274     public void testGetSocketTimeoutException() throws Exception {
275         Assert.assertEquals(-1, conn.getSocketTimeout());
276 
277         Mockito.when(socket.getSoTimeout()).thenThrow(new SocketException());
278         conn.bind(socket);
279 
280         Assert.assertEquals(-1, conn.getSocketTimeout());
281     }
282 
283     @Test
284     public void testAwaitInputInBuffer() throws Exception {
285         final ByteArrayInputStream inStream = Mockito.spy(new ByteArrayInputStream(
286                 new byte[] {1, 2, 3, 4, 5}));
287         Mockito.when(socket.getInputStream()).thenReturn(inStream);
288 
289         conn.bind(socket);
290         conn.ensureOpen();
291         conn.getSessionInputBuffer().read();
292 
293         Assert.assertTrue(conn.awaitInput(432));
294 
295         Mockito.verify(socket, Mockito.never()).setSoTimeout(Matchers.anyInt());
296         Mockito.verify(inStream, Mockito.times(1)).read(
297                 Matchers.<byte []>any(), Matchers.anyInt(), Matchers.anyInt());
298     }
299 
300     @Test
301     public void testAwaitInputInSocket() throws Exception {
302         final ByteArrayInputStream inStream = Mockito.spy(new ByteArrayInputStream(
303                 new byte[] {1, 2, 3, 4, 5}));
304         Mockito.when(socket.getInputStream()).thenReturn(inStream);
305         Mockito.when(socket.getSoTimeout()).thenReturn(345);
306 
307         conn.bind(socket);
308         conn.ensureOpen();
309 
310         Assert.assertTrue(conn.awaitInput(432));
311 
312         Mockito.verify(socket, Mockito.times(1)).setSoTimeout(432);
313         Mockito.verify(socket, Mockito.times(1)).setSoTimeout(345);
314         Mockito.verify(inStream, Mockito.times(1)).read(
315                 Matchers.<byte []>any(), Matchers.anyInt(), Matchers.anyInt());
316     }
317 
318     @Test
319     public void testAwaitInputNoData() throws Exception {
320         final InputStream inStream = Mockito.mock(InputStream.class);
321         Mockito.when(socket.getInputStream()).thenReturn(inStream);
322         Mockito.when(inStream.read(Matchers.<byte []>any(), Matchers.anyInt(), Matchers.anyInt()))
323             .thenReturn(-1);
324 
325         conn.bind(socket);
326         conn.ensureOpen();
327 
328         Assert.assertFalse(conn.awaitInput(432));
329     }
330 
331     @Test
332     public void testStaleWhenClosed() throws Exception {
333         conn.bind(socket);
334         conn.ensureOpen();
335         conn.close();
336         Assert.assertTrue(conn.isStale());
337     }
338 
339     @Test
340     public void testNotStaleWhenHasData() throws Exception {
341         final ByteArrayInputStream inStream = Mockito.spy(new ByteArrayInputStream(
342                 new byte[] {1, 2, 3, 4, 5}));
343         Mockito.when(socket.getInputStream()).thenReturn(inStream);
344 
345         conn.bind(socket);
346         conn.ensureOpen();
347 
348         Assert.assertFalse(conn.isStale());
349     }
350 
351     @Test
352     public void testStaleWhenEndOfStream() throws Exception {
353         final InputStream inStream = Mockito.mock(InputStream.class);
354         Mockito.when(socket.getInputStream()).thenReturn(inStream);
355         Mockito.when(inStream.read(Matchers.<byte []>any(), Matchers.anyInt(), Matchers.anyInt()))
356             .thenReturn(-1);
357 
358         conn.bind(socket);
359         conn.ensureOpen();
360 
361         Assert.assertTrue(conn.isStale());
362     }
363 
364     @Test
365     public void testNotStaleWhenTimeout() throws Exception {
366         final InputStream inStream = Mockito.mock(InputStream.class);
367         Mockito.when(socket.getInputStream()).thenReturn(inStream);
368         Mockito.when(inStream.read(Matchers.<byte []>any(), Matchers.anyInt(), Matchers.anyInt()))
369             .thenThrow(new SocketTimeoutException());
370 
371         conn.bind(socket);
372         conn.ensureOpen();
373 
374         Assert.assertFalse(conn.isStale());
375     }
376 
377     @Test
378     public void testStaleWhenIOError() throws Exception {
379         final InputStream inStream = Mockito.mock(InputStream.class);
380         Mockito.when(socket.getInputStream()).thenReturn(inStream);
381         Mockito.when(inStream.read(Matchers.<byte []>any(), Matchers.anyInt(), Matchers.anyInt()))
382             .thenThrow(new SocketException());
383 
384         conn.bind(socket);
385         conn.ensureOpen();
386 
387         Assert.assertTrue(conn.isStale());
388     }
389 
390 }