1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.apache.hc.core5.http.impl.io;
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.hc.core5.http.ClassicHttpResponse;
39 import org.apache.hc.core5.http.ContentLengthStrategy;
40 import org.apache.hc.core5.http.HttpEntity;
41 import org.apache.hc.core5.http.config.Http1Config;
42 import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
43 import org.apache.hc.core5.io.CloseMode;
44 import org.apache.hc.core5.util.Timeout;
45 import org.junit.jupiter.api.Assertions;
46 import org.junit.jupiter.api.BeforeEach;
47 import org.junit.jupiter.api.Test;
48 import org.mockito.ArgumentMatchers;
49 import org.mockito.Mock;
50 import org.mockito.Mockito;
51 import org.mockito.MockitoAnnotations;
52
53 public class TestBHttpConnectionBase {
54
55 @Mock
56 private Socket socket;
57
58 private BHttpConnectionBase conn;
59
60 @BeforeEach
61 public void prepareMocks() {
62 MockitoAnnotations.openMocks(this);
63 conn = new BHttpConnectionBase(Http1Config.DEFAULT, null, null);
64 }
65
66 @Test
67 public void testBasics() throws Exception {
68 Assertions.assertFalse(conn.isOpen());
69 Assertions.assertNull(conn.getLocalAddress());
70 Assertions.assertNull(conn.getRemoteAddress());
71 Assertions.assertEquals("[Not bound]", conn.toString());
72 }
73
74 @Test
75 public void testSocketBind() throws Exception {
76 final InetAddress localAddress = InetAddress.getByAddress(new byte[] {127, 0, 0, 1});
77 final int localPort = 8888;
78 final InetAddress remoteAddress = InetAddress.getByAddress(new byte[] {10, 0, 0, 2});
79 final int remotePort = 80;
80 final InetSocketAddress localSockAddress = new InetSocketAddress(localAddress, localPort);
81 final InetSocketAddress remoteSockAddress = new InetSocketAddress(remoteAddress, remotePort);
82 Mockito.when(socket.getLocalSocketAddress()).thenReturn(localSockAddress);
83 Mockito.when(socket.getRemoteSocketAddress()).thenReturn(remoteSockAddress);
84 conn.bind(socket);
85
86 Assertions.assertEquals("127.0.0.1:8888<->10.0.0.2:80", conn.toString());
87 Assertions.assertTrue(conn.isOpen());
88
89 Assertions.assertEquals(new InetSocketAddress(
90 InetAddress.getByAddress(new byte[] {127, 0, 0, 1}), 8888), conn.getLocalAddress());
91 Assertions.assertEquals(new InetSocketAddress(
92 InetAddress.getByAddress(new byte[] {10, 0, 0, 2}), 80), conn.getRemoteAddress());
93 }
94
95 @Test
96 public void testConnectionClose() throws Exception {
97 final OutputStream outStream = Mockito.mock(OutputStream.class);
98 Mockito.when(socket.getOutputStream()).thenReturn(outStream);
99
100 conn.bind(socket);
101 conn.ensureOpen();
102 conn.outbuffer.write(0, outStream);
103
104 Assertions.assertTrue(conn.isOpen());
105
106 conn.close();
107
108 Assertions.assertFalse(conn.isOpen());
109
110 Mockito.verify(outStream, Mockito.times(1)).write(
111 ArgumentMatchers.any(), ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt());
112 Mockito.verify(socket, Mockito.times(1)).close();
113
114 conn.close();
115 Mockito.verify(socket, Mockito.times(1)).close();
116 Mockito.verify(outStream, Mockito.times(1)).write(
117 ArgumentMatchers.any(), ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt());
118 }
119
120 @Test
121 public void testConnectionShutdown() throws Exception {
122 final OutputStream outStream = Mockito.mock(OutputStream.class);
123
124 conn.bind(socket);
125 conn.ensureOpen();
126 conn.outbuffer.write(0, outStream);
127
128 Assertions.assertTrue(conn.isOpen());
129
130 conn.close(CloseMode.GRACEFUL);
131
132 Assertions.assertFalse(conn.isOpen());
133
134 Mockito.verify(outStream, Mockito.never()).write(
135 ArgumentMatchers.any(), ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt());
136 Mockito.verify(socket, Mockito.never()).shutdownInput();
137 Mockito.verify(socket, Mockito.never()).shutdownOutput();
138 Mockito.verify(socket, Mockito.times(1)).close();
139
140 conn.close();
141 Mockito.verify(socket, Mockito.times(1)).close();
142
143 conn.close(CloseMode.GRACEFUL);
144 Mockito.verify(socket, Mockito.times(1)).close();
145 }
146
147 @Test
148 public void testCreateEntityLengthDelimited() throws Exception {
149 final InputStream inStream = Mockito.mock(InputStream.class);
150 final ClassicHttpResponse message = new BasicClassicHttpResponse(200, "OK");
151 message.addHeader("Content-Length", "10");
152 message.addHeader("Content-Type", "stuff");
153 message.addHeader("Content-Encoding", "chunked");
154 final HttpEntity entity = conn.createIncomingEntity(message, conn.inBuffer, inStream, 10);
155 Assertions.assertNotNull(entity);
156 Assertions.assertFalse(entity.isChunked());
157 Assertions.assertEquals(10, entity.getContentLength());
158 Assertions.assertEquals("stuff", entity.getContentType());
159 Assertions.assertEquals("chunked", entity.getContentEncoding());
160 final InputStream content = entity.getContent();
161 Assertions.assertNotNull(content);
162 Assertions.assertTrue((content instanceof ContentLengthInputStream));
163 }
164
165 @Test
166 public void testCreateEntityInputChunked() throws Exception {
167 final InputStream inStream = Mockito.mock(InputStream.class);
168 final ClassicHttpResponse message = new BasicClassicHttpResponse(200, "OK");
169 final HttpEntity entity = conn.createIncomingEntity(message, conn.inBuffer, inStream, ContentLengthStrategy.CHUNKED);
170 Assertions.assertNotNull(entity);
171 Assertions.assertTrue(entity.isChunked());
172 Assertions.assertEquals(-1, entity.getContentLength());
173 final InputStream content = entity.getContent();
174 Assertions.assertNotNull(content);
175 Assertions.assertTrue((content instanceof ChunkedInputStream));
176 }
177
178 @Test
179 public void testCreateEntityInputUndefined() throws Exception {
180 final InputStream inStream = Mockito.mock(InputStream.class);
181 final ClassicHttpResponse message = new BasicClassicHttpResponse(200, "OK");
182 final HttpEntity entity = conn.createIncomingEntity(message, conn.inBuffer, inStream, ContentLengthStrategy.UNDEFINED);
183 Assertions.assertNotNull(entity);
184 Assertions.assertFalse(entity.isChunked());
185 Assertions.assertEquals(-1, entity.getContentLength());
186 final InputStream content = entity.getContent();
187 Assertions.assertNotNull(content);
188 Assertions.assertTrue((content instanceof IdentityInputStream));
189 }
190
191 @Test
192 public void testSetSocketTimeout() throws Exception {
193 conn.bind(socket);
194
195 conn.setSocketTimeout(Timeout.ofMilliseconds(123));
196
197 Mockito.verify(socket, Mockito.times(1)).setSoTimeout(123);
198 }
199
200 @Test
201 public void testSetSocketTimeoutException() throws Exception {
202 conn.bind(socket);
203
204 Mockito.doThrow(new SocketException()).when(socket).setSoTimeout(ArgumentMatchers.anyInt());
205
206 conn.setSocketTimeout(Timeout.ofMilliseconds(123));
207
208 Mockito.verify(socket, Mockito.times(1)).setSoTimeout(123);
209 }
210
211 @Test
212 public void testGetSocketTimeout() throws Exception {
213 Assertions.assertEquals(Timeout.INFINITE, conn.getSocketTimeout());
214
215 Mockito.when(socket.getSoTimeout()).thenReturn(345);
216 conn.bind(socket);
217
218 Assertions.assertEquals(Timeout.ofMilliseconds(345), conn.getSocketTimeout());
219 }
220
221 @Test
222 public void testGetSocketTimeoutException() throws Exception {
223 Assertions.assertEquals(Timeout.INFINITE, conn.getSocketTimeout());
224
225 Mockito.when(socket.getSoTimeout()).thenThrow(new SocketException());
226 conn.bind(socket);
227
228 Assertions.assertEquals(Timeout.INFINITE, conn.getSocketTimeout());
229 }
230
231 @Test
232 public void testAwaitInputInBuffer() throws Exception {
233 final ByteArrayInputStream inStream = new ByteArrayInputStream(
234 new byte[] {1, 2, 3, 4, 5});
235 conn.bind(socket);
236 conn.ensureOpen();
237 conn.inBuffer.read(inStream);
238
239 Assertions.assertTrue(conn.awaitInput(Timeout.ofMilliseconds(432)));
240
241 Mockito.verify(socket, Mockito.never()).setSoTimeout(ArgumentMatchers.anyInt());
242 }
243
244 @Test
245 public void testAwaitInputInSocket() throws Exception {
246 final ByteArrayInputStream inStream = new ByteArrayInputStream(
247 new byte[] {1, 2, 3, 4, 5});
248 Mockito.when(socket.getInputStream()).thenReturn(inStream);
249 Mockito.when(socket.getSoTimeout()).thenReturn(345);
250
251 conn.bind(socket);
252 conn.ensureOpen();
253
254 Assertions.assertTrue(conn.awaitInput(Timeout.ofMilliseconds(432)));
255
256 Mockito.verify(socket, Mockito.times(1)).setSoTimeout(432);
257 Mockito.verify(socket, Mockito.times(1)).setSoTimeout(345);
258 }
259
260 @Test
261 public void testAwaitInputNoData() throws Exception {
262 final InputStream inStream = Mockito.mock(InputStream.class);
263 Mockito.when(socket.getInputStream()).thenReturn(inStream);
264 Mockito.when(inStream.read(ArgumentMatchers.any(), ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt()))
265 .thenReturn(-1);
266
267 conn.bind(socket);
268 conn.ensureOpen();
269
270 Assertions.assertFalse(conn.awaitInput(Timeout.ofMilliseconds(432)));
271 }
272
273 @Test
274 public void testStaleWhenClosed() throws Exception {
275 final OutputStream outStream = Mockito.mock(OutputStream.class);
276
277 Mockito.when(socket.getOutputStream()).thenReturn(outStream);
278
279 conn.bind(socket);
280 conn.ensureOpen();
281 conn.close();
282 Assertions.assertTrue(conn.isStale());
283 }
284
285 @Test
286 public void testNotStaleWhenHasData() throws Exception {
287 final ByteArrayInputStream inStream = new ByteArrayInputStream(
288 new byte[] {1, 2, 3, 4, 5});
289 Mockito.when(socket.getInputStream()).thenReturn(inStream);
290
291 conn.bind(socket);
292 conn.ensureOpen();
293
294 Assertions.assertFalse(conn.isStale());
295 }
296
297 @Test
298 public void testStaleWhenEndOfStream() throws Exception {
299 final InputStream inStream = Mockito.mock(InputStream.class);
300 Mockito.when(socket.getInputStream()).thenReturn(inStream);
301 Mockito.when(inStream.read(ArgumentMatchers.any(), ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt()))
302 .thenReturn(-1);
303
304 conn.bind(socket);
305 conn.ensureOpen();
306
307 Assertions.assertTrue(conn.isStale());
308 }
309
310 @Test
311 public void testNotStaleWhenTimeout() throws Exception {
312 final InputStream inStream = Mockito.mock(InputStream.class);
313 Mockito.when(socket.getInputStream()).thenReturn(inStream);
314 Mockito.when(inStream.read(ArgumentMatchers.any(), ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt()))
315 .thenThrow(new SocketTimeoutException());
316
317 conn.bind(socket);
318 conn.ensureOpen();
319
320 Assertions.assertFalse(conn.isStale());
321 }
322
323 @Test
324 public void testStaleWhenIOError() throws Exception {
325 final InputStream inStream = Mockito.mock(InputStream.class);
326 Mockito.when(socket.getInputStream()).thenReturn(inStream);
327 Mockito.when(inStream.read(ArgumentMatchers.any(), ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt()))
328 .thenThrow(new SocketException());
329
330 conn.bind(socket);
331 conn.ensureOpen();
332
333 Assertions.assertTrue(conn.isStale());
334 }
335
336 }