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.nio;
28  
29  import java.net.InetAddress;
30  import java.net.InetSocketAddress;
31  import java.nio.channels.ByteChannel;
32  import java.nio.channels.SelectionKey;
33  
34  import org.apache.http.HttpEntity;
35  import org.apache.http.HttpVersion;
36  import org.apache.http.impl.entity.LaxContentLengthStrategy;
37  import org.apache.http.impl.entity.StrictContentLengthStrategy;
38  import org.apache.http.impl.nio.codecs.ChunkDecoder;
39  import org.apache.http.impl.nio.codecs.ChunkEncoder;
40  import org.apache.http.impl.nio.codecs.IdentityDecoder;
41  import org.apache.http.impl.nio.codecs.IdentityEncoder;
42  import org.apache.http.impl.nio.codecs.LengthDelimitedDecoder;
43  import org.apache.http.impl.nio.codecs.LengthDelimitedEncoder;
44  import org.apache.http.message.BasicHttpResponse;
45  import org.apache.http.nio.NHttpConnection;
46  import org.apache.http.nio.reactor.IOSession;
47  import org.apache.http.nio.util.HeapByteBufferAllocator;
48  import org.apache.http.protocol.HTTP;
49  import org.junit.Assert;
50  import org.junit.Before;
51  import org.junit.Test;
52  import org.mockito.Mock;
53  import org.mockito.Mockito;
54  import org.mockito.MockitoAnnotations;
55  
56  public class TestNHttpConnectionBase {
57  
58      @Mock
59      private IOSession session;
60      @Mock
61      private ByteChannel channel;
62  
63      private NHttpConnectionBase conn;
64  
65      @Before
66      public void setUp() throws Exception {
67          MockitoAnnotations.initMocks(this);
68          conn = new NHttpConnectionBase(session, 1024, 1024, HeapByteBufferAllocator.INSTANCE,
69              null, null,
70              LaxContentLengthStrategy.INSTANCE,
71              StrictContentLengthStrategy.INSTANCE);
72      }
73  
74      @Test
75      public void testBasics() throws Exception {
76          Assert.assertEquals("[Not bound]", conn.toString());
77  
78          Mockito.verify(session).setBufferStatus(conn);
79      }
80  
81      @Test
82      public void testSessionBind() throws Exception {
83          final InetSocketAddress local = new InetSocketAddress(
84              InetAddress.getByAddress(new byte[] {127, 0, 0, 1}), 8888);
85          final InetSocketAddress remote = new InetSocketAddress(
86              InetAddress.getByAddress(new byte[] {10, 0, 0, 2}), 80);
87          Mockito.when(session.getLocalAddress()).thenReturn(local);
88          Mockito.when(session.getRemoteAddress()).thenReturn(remote);
89          Mockito.when(session.isClosed()).thenReturn(Boolean.FALSE);
90  
91          conn.bind(session);
92  
93          Mockito.verify(session, Mockito.times(2)).setBufferStatus(conn);
94  
95          Assert.assertEquals("127.0.0.1:8888<->10.0.0.2:80", conn.toString());
96          Assert.assertTrue(conn.isOpen());
97          Assert.assertEquals(8888, conn.getLocalPort());
98          Assert.assertEquals(80, conn.getRemotePort());
99          Assert.assertEquals(InetAddress.getByAddress(new byte[] {127, 0, 0, 1}), conn.getLocalAddress());
100         Assert.assertEquals(InetAddress.getByAddress(new byte[] {10, 0, 0, 2}), conn.getRemoteAddress());
101     }
102 
103     @Test
104     public void testClose() throws Exception {
105         final InetSocketAddress local = new InetSocketAddress(
106             InetAddress.getByAddress(new byte[] {127, 0, 0, 1}), 8888);
107         final InetSocketAddress remote = new InetSocketAddress(
108             InetAddress.getByAddress(new byte[] {10, 0, 0, 2}), 80);
109         Mockito.when(session.getLocalAddress()).thenReturn(local);
110         Mockito.when(session.getRemoteAddress()).thenReturn(remote);
111         Mockito.when(session.isClosed()).thenReturn(Boolean.FALSE);
112 
113         conn.close();
114 
115         Assert.assertEquals(NHttpConnection.CLOSED, conn.getStatus());
116         Assert.assertEquals("127.0.0.1:8888<->10.0.0.2:80", conn.toString());
117 
118         Mockito.verify(session).close();
119     }
120 
121     @Test
122     public void testCloseWithBufferedData() throws Exception {
123         final InetSocketAddress local = new InetSocketAddress(
124             InetAddress.getByAddress(new byte[] {127, 0, 0, 1}), 8888);
125         final InetSocketAddress remote = new InetSocketAddress(
126             InetAddress.getByAddress(new byte[] {10, 0, 0, 2}), 80);
127         Mockito.when(session.getLocalAddress()).thenReturn(local);
128         Mockito.when(session.getRemoteAddress()).thenReturn(remote);
129         Mockito.when(session.isClosed()).thenReturn(Boolean.FALSE);
130 
131         conn.outbuf.writeLine("stuff");
132         conn.close();
133 
134         Assert.assertEquals(NHttpConnection.CLOSING, conn.getStatus());
135         conn.close();
136         Assert.assertEquals(NHttpConnection.CLOSING, conn.getStatus());
137         Assert.assertEquals("127.0.0.1:8888<->10.0.0.2:80", conn.toString());
138 
139         Mockito.verify(session).setEvent(SelectionKey.OP_WRITE);
140         Mockito.verify(session, Mockito.never()).close();
141     }
142 
143     @Test
144     public void testShutdown() throws Exception {
145         final InetSocketAddress local = new InetSocketAddress(
146             InetAddress.getByAddress(new byte[] {127, 0, 0, 1}), 8888);
147         final InetSocketAddress remote = new InetSocketAddress(
148             InetAddress.getByAddress(new byte[] {10, 0, 0, 2}), 80);
149         Mockito.when(session.getLocalAddress()).thenReturn(local);
150         Mockito.when(session.getRemoteAddress()).thenReturn(remote);
151         Mockito.when(session.isClosed()).thenReturn(Boolean.FALSE);
152 
153         conn.outbuf.writeLine("stuff");
154         conn.shutdown();
155 
156         Assert.assertEquals(NHttpConnection.CLOSED, conn.getStatus());
157         Assert.assertEquals("127.0.0.1:8888<->10.0.0.2:80", conn.toString());
158 
159         Mockito.verify(session).shutdown();
160     }
161 
162     @Test
163     public void testContextOperations() throws Exception {
164         conn.getContext().getAttribute("stuff");
165         conn.getContext().setAttribute("stuff", "blah");
166         conn.getContext().removeAttribute("other stuff");
167 
168         Mockito.verify(session).getAttribute("stuff");
169         Mockito.verify(session).setAttribute("stuff", "blah");
170         Mockito.verify(session).removeAttribute("other stuff");
171     }
172 
173     @Test
174     public void testIOOperations() throws Exception {
175         conn.suspendInput();
176         Mockito.verify(session).clearEvent(SelectionKey.OP_READ);
177 
178         conn.suspendOutput();
179         Mockito.verify(session).clearEvent(SelectionKey.OP_WRITE);
180 
181         conn.requestInput();
182         Mockito.verify(session).setEvent(SelectionKey.OP_READ);
183 
184         conn.requestOutput();
185         Mockito.verify(session).setEvent(SelectionKey.OP_WRITE);
186     }
187 
188     @Test
189     public void testSocketTimeout() throws Exception {
190         conn.getSocketTimeout();
191         Mockito.verify(session).getSocketTimeout();
192 
193         conn.setSocketTimeout(123);
194         Mockito.verify(session).setSocketTimeout(123);
195     }
196 
197     @Test
198     public void testPrepareIdentityDecoder() throws Exception {
199         final BasicHttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
200         Mockito.when(session.channel()).thenReturn(channel);
201 
202         final HttpEntity entity = conn.prepareDecoder(response);
203         Assert.assertNotNull(entity);
204         Assert.assertEquals(-1, entity.getContentLength());
205         Assert.assertFalse(entity.isChunked());
206         Assert.assertTrue(conn.contentDecoder instanceof IdentityDecoder);
207     }
208 
209     @Test
210     public void testPrepareLengthDelimitedDecoder() throws Exception {
211         final BasicHttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
212         response.addHeader(HTTP.CONTENT_LEN, "10");
213         response.addHeader(HTTP.CONTENT_TYPE, "stuff");
214         response.addHeader(HTTP.CONTENT_ENCODING, "identity");
215         Mockito.when(session.channel()).thenReturn(channel);
216 
217         final HttpEntity entity = conn.prepareDecoder(response);
218         Assert.assertNotNull(entity);
219         Assert.assertEquals(10, entity.getContentLength());
220         Assert.assertFalse(entity.isChunked());
221         Assert.assertNotNull(entity.getContentType());
222         Assert.assertEquals("stuff", entity.getContentType().getValue());
223         Assert.assertNotNull(entity.getContentEncoding());
224         Assert.assertEquals("identity", entity.getContentEncoding().getValue());
225         Assert.assertTrue(conn.contentDecoder instanceof LengthDelimitedDecoder);
226     }
227 
228     @Test
229     public void testPrepareChunkDecoder() throws Exception {
230         final BasicHttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
231         response.addHeader(HTTP.TRANSFER_ENCODING, "chunked");
232         response.addHeader(HTTP.CONTENT_TYPE, "stuff");
233         response.addHeader(HTTP.CONTENT_ENCODING, "identity");
234         Mockito.when(session.channel()).thenReturn(channel);
235 
236         final HttpEntity entity = conn.prepareDecoder(response);
237         Assert.assertNotNull(entity);
238         Assert.assertEquals(-1, entity.getContentLength());
239         Assert.assertTrue(entity.isChunked());
240         Assert.assertNotNull(entity.getContentType());
241         Assert.assertEquals("stuff", entity.getContentType().getValue());
242         Assert.assertNotNull(entity.getContentEncoding());
243         Assert.assertEquals("identity", entity.getContentEncoding().getValue());
244         Assert.assertTrue(conn.contentDecoder instanceof ChunkDecoder);
245     }
246 
247     @Test
248     public void testPrepareIdentityEncoder() throws Exception {
249         final BasicHttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
250         Mockito.when(session.channel()).thenReturn(channel);
251 
252         conn.prepareEncoder(response);
253         Assert.assertTrue(conn.contentEncoder instanceof IdentityEncoder);
254     }
255 
256     @Test
257     public void testPrepareLengthDelimitedEncoder() throws Exception {
258         final BasicHttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
259         response.addHeader(HTTP.CONTENT_LEN, "10");
260         Mockito.when(session.channel()).thenReturn(channel);
261 
262         conn.prepareEncoder(response);
263         Assert.assertTrue(conn.contentEncoder instanceof LengthDelimitedEncoder);
264     }
265 
266     @Test
267     public void testPrepareChunkEncoder() throws Exception {
268         final BasicHttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
269         response.addHeader(HTTP.TRANSFER_ENCODING, "chunked");
270         Mockito.when(session.channel()).thenReturn(channel);
271 
272         conn.prepareEncoder(response);
273         Assert.assertTrue(conn.contentEncoder instanceof ChunkEncoder);
274     }
275 
276 }