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)).close();
132 
133         conn.close();
134         Mockito.verify(socket, Mockito.times(1)).close();
135         Mockito.verify(outStream, Mockito.times(1)).write(
136                 Matchers.<byte []>any(), Matchers.anyInt(), Matchers.anyInt());
137     }
138 
139     @Test
140     public void testConnectionShutdown() throws Exception {
141         final InputStream inStream = Mockito.mock(InputStream.class);
142         final OutputStream outStream = Mockito.mock(OutputStream.class);
143         Mockito.when(socket.getInputStream()).thenReturn(inStream);
144         Mockito.when(socket.getOutputStream()).thenReturn(outStream);
145 
146         conn.bind(socket);
147         conn.ensureOpen();
148         conn.getSessionOutputBuffer().write(0);
149 
150         Assert.assertTrue(conn.isOpen());
151 
152         conn.shutdown();
153 
154         Assert.assertFalse(conn.isOpen());
155 
156         Mockito.verify(outStream, Mockito.never()).write(
157                 Matchers.<byte []>any(), Matchers.anyInt(), Matchers.anyInt());
158         Mockito.verify(socket, Mockito.never()).shutdownInput();
159         Mockito.verify(socket, Mockito.never()).shutdownOutput();
160         Mockito.verify(socket, Mockito.times(1)).close();
161 
162         conn.close();
163         Mockito.verify(socket, Mockito.times(1)).close();
164 
165         conn.shutdown();
166         Mockito.verify(socket, Mockito.times(1)).close();
167     }
168 
169     @Test
170     public void testPrepareInputLengthDelimited() throws Exception {
171         final HttpResponse message = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
172         message.addHeader("Content-Length", "10");
173         message.addHeader("Content-Type", "stuff");
174         message.addHeader("Content-Encoding", "identity");
175         final HttpEntity entity = conn.prepareInput(message);
176         Assert.assertNotNull(entity);
177         Assert.assertFalse(entity.isChunked());
178         Assert.assertEquals(10, entity.getContentLength());
179         final Header ct = entity.getContentType();
180         Assert.assertNotNull(ct);
181         Assert.assertEquals("stuff", ct.getValue());
182         final Header ce = entity.getContentEncoding();
183         Assert.assertNotNull(ce);
184         Assert.assertEquals("identity", ce.getValue());
185         final InputStream inStream = entity.getContent();
186         Assert.assertNotNull(inStream);
187         Assert.assertTrue((inStream instanceof ContentLengthInputStream));
188     }
189 
190     @Test
191     public void testPrepareInputChunked() throws Exception {
192         final HttpResponse message = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
193         message.addHeader("Transfer-Encoding", "chunked");
194         final HttpEntity entity = conn.prepareInput(message);
195         Assert.assertNotNull(entity);
196         Assert.assertTrue(entity.isChunked());
197         Assert.assertEquals(-1, entity.getContentLength());
198         final InputStream inStream = entity.getContent();
199         Assert.assertNotNull(inStream);
200         Assert.assertTrue((inStream instanceof ChunkedInputStream));
201     }
202 
203     @Test
204     public void testPrepareInputIdentity() throws Exception {
205         final HttpResponse message = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
206         final HttpEntity entity = conn.prepareInput(message);
207         Assert.assertNotNull(entity);
208         Assert.assertFalse(entity.isChunked());
209         Assert.assertEquals(-1, entity.getContentLength());
210         final InputStream inStream = entity.getContent();
211         Assert.assertNotNull(inStream);
212         Assert.assertTrue((inStream instanceof IdentityInputStream));
213     }
214 
215     @Test
216     public void testPrepareOutputLengthDelimited() throws Exception {
217         final HttpResponse message = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
218         message.addHeader("Content-Length", "10");
219         final OutputStream outStream = conn.prepareOutput(message);
220         Assert.assertNotNull(outStream);
221         Assert.assertTrue((outStream instanceof ContentLengthOutputStream));
222     }
223 
224     @Test
225     public void testPrepareOutputChunked() throws Exception {
226         final HttpResponse message = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
227         message.addHeader("Transfer-Encoding", "chunked");
228         final OutputStream outStream = conn.prepareOutput(message);
229         Assert.assertNotNull(outStream);
230         Assert.assertTrue((outStream instanceof ChunkedOutputStream));
231     }
232 
233     @Test
234     public void testPrepareOutputIdentity() throws Exception {
235         final HttpResponse message = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
236         final OutputStream outStream = conn.prepareOutput(message);
237         Assert.assertNotNull(outStream);
238         Assert.assertTrue((outStream instanceof IdentityOutputStream));
239     }
240 
241     @Test
242     public void testSetSocketTimeout() throws Exception {
243         conn.bind(socket);
244 
245         conn.setSocketTimeout(123);
246 
247         Mockito.verify(socket, Mockito.times(1)).setSoTimeout(123);
248     }
249 
250     @Test
251     public void testSetSocketTimeoutException() throws Exception {
252         conn.bind(socket);
253 
254         Mockito.doThrow(new SocketException()).when(socket).setSoTimeout(Matchers.anyInt());
255 
256         conn.setSocketTimeout(123);
257 
258         Mockito.verify(socket, Mockito.times(1)).setSoTimeout(123);
259     }
260 
261     @Test
262     public void testGetSocketTimeout() throws Exception {
263         Assert.assertEquals(-1, conn.getSocketTimeout());
264 
265         Mockito.when(socket.getSoTimeout()).thenReturn(345);
266         conn.bind(socket);
267 
268         Assert.assertEquals(345, conn.getSocketTimeout());
269     }
270 
271     @Test
272     public void testGetSocketTimeoutException() throws Exception {
273         Assert.assertEquals(-1, conn.getSocketTimeout());
274 
275         Mockito.when(socket.getSoTimeout()).thenThrow(new SocketException());
276         conn.bind(socket);
277 
278         Assert.assertEquals(-1, conn.getSocketTimeout());
279     }
280 
281     @Test
282     public void testAwaitInputInBuffer() throws Exception {
283         final ByteArrayInputStream inStream = Mockito.spy(new ByteArrayInputStream(
284                 new byte[] {1, 2, 3, 4, 5}));
285         Mockito.when(socket.getInputStream()).thenReturn(inStream);
286 
287         conn.bind(socket);
288         conn.ensureOpen();
289         conn.getSessionInputBuffer().read();
290 
291         Assert.assertTrue(conn.awaitInput(432));
292 
293         Mockito.verify(socket, Mockito.never()).setSoTimeout(Matchers.anyInt());
294         Mockito.verify(inStream, Mockito.times(1)).read(
295                 Matchers.<byte []>any(), Matchers.anyInt(), Matchers.anyInt());
296     }
297 
298     @Test
299     public void testAwaitInputInSocket() throws Exception {
300         final ByteArrayInputStream inStream = Mockito.spy(new ByteArrayInputStream(
301                 new byte[] {1, 2, 3, 4, 5}));
302         Mockito.when(socket.getInputStream()).thenReturn(inStream);
303         Mockito.when(socket.getSoTimeout()).thenReturn(345);
304 
305         conn.bind(socket);
306         conn.ensureOpen();
307 
308         Assert.assertTrue(conn.awaitInput(432));
309 
310         Mockito.verify(socket, Mockito.times(1)).setSoTimeout(432);
311         Mockito.verify(socket, Mockito.times(1)).setSoTimeout(345);
312         Mockito.verify(inStream, Mockito.times(1)).read(
313                 Matchers.<byte []>any(), Matchers.anyInt(), Matchers.anyInt());
314     }
315 
316     @Test
317     public void testAwaitInputNoData() throws Exception {
318         final InputStream inStream = Mockito.mock(InputStream.class);
319         Mockito.when(socket.getInputStream()).thenReturn(inStream);
320         Mockito.when(inStream.read(Matchers.<byte []>any(), Matchers.anyInt(), Matchers.anyInt()))
321             .thenReturn(-1);
322 
323         conn.bind(socket);
324         conn.ensureOpen();
325 
326         Assert.assertFalse(conn.awaitInput(432));
327     }
328 
329     @Test
330     public void testStaleWhenClosed() throws Exception {
331         conn.bind(socket);
332         conn.ensureOpen();
333         conn.close();
334         Assert.assertTrue(conn.isStale());
335     }
336 
337     @Test
338     public void testNotStaleWhenHasData() throws Exception {
339         final ByteArrayInputStream inStream = Mockito.spy(new ByteArrayInputStream(
340                 new byte[] {1, 2, 3, 4, 5}));
341         Mockito.when(socket.getInputStream()).thenReturn(inStream);
342 
343         conn.bind(socket);
344         conn.ensureOpen();
345 
346         Assert.assertFalse(conn.isStale());
347     }
348 
349     @Test
350     public void testStaleWhenEndOfStream() throws Exception {
351         final InputStream inStream = Mockito.mock(InputStream.class);
352         Mockito.when(socket.getInputStream()).thenReturn(inStream);
353         Mockito.when(inStream.read(Matchers.<byte []>any(), Matchers.anyInt(), Matchers.anyInt()))
354             .thenReturn(-1);
355 
356         conn.bind(socket);
357         conn.ensureOpen();
358 
359         Assert.assertTrue(conn.isStale());
360     }
361 
362     @Test
363     public void testNotStaleWhenTimeout() throws Exception {
364         final InputStream inStream = Mockito.mock(InputStream.class);
365         Mockito.when(socket.getInputStream()).thenReturn(inStream);
366         Mockito.when(inStream.read(Matchers.<byte []>any(), Matchers.anyInt(), Matchers.anyInt()))
367             .thenThrow(new SocketTimeoutException());
368 
369         conn.bind(socket);
370         conn.ensureOpen();
371 
372         Assert.assertFalse(conn.isStale());
373     }
374 
375     @Test
376     public void testStaleWhenIOError() throws Exception {
377         final InputStream inStream = Mockito.mock(InputStream.class);
378         Mockito.when(socket.getInputStream()).thenReturn(inStream);
379         Mockito.when(inStream.read(Matchers.<byte []>any(), Matchers.anyInt(), Matchers.anyInt()))
380             .thenThrow(new SocketException());
381 
382         conn.bind(socket);
383         conn.ensureOpen();
384 
385         Assert.assertTrue(conn.isStale());
386     }
387 
388 }