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.client5.http.impl.classic;
28
29 import java.io.ByteArrayInputStream;
30 import java.io.IOException;
31 import java.io.InterruptedIOException;
32
33 import org.apache.hc.client5.http.ConnectionKeepAliveStrategy;
34 import org.apache.hc.client5.http.HttpRoute;
35 import org.apache.hc.client5.http.UserTokenHandler;
36 import org.apache.hc.client5.http.classic.ExecChain;
37 import org.apache.hc.client5.http.classic.ExecRuntime;
38 import org.apache.hc.client5.http.classic.methods.HttpGet;
39 import org.apache.hc.client5.http.entity.EntityBuilder;
40 import org.apache.hc.client5.http.impl.ConnectionShutdownException;
41 import org.apache.hc.client5.http.io.HttpClientConnectionManager;
42 import org.apache.hc.client5.http.protocol.HttpClientContext;
43 import org.apache.hc.core5.http.ClassicHttpRequest;
44 import org.apache.hc.core5.http.ClassicHttpResponse;
45 import org.apache.hc.core5.http.ConnectionReuseStrategy;
46 import org.apache.hc.core5.http.HttpEntity;
47 import org.apache.hc.core5.http.HttpException;
48 import org.apache.hc.core5.http.HttpHost;
49 import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
50 import org.apache.hc.core5.http.protocol.HttpProcessor;
51 import org.apache.hc.core5.util.TimeValue;
52 import org.junit.jupiter.api.Assertions;
53 import org.junit.jupiter.api.BeforeEach;
54 import org.junit.jupiter.api.Test;
55 import org.mockito.Mock;
56 import org.mockito.Mockito;
57 import org.mockito.MockitoAnnotations;
58
59 @SuppressWarnings({"boxing","static-access"})
60 public class TestMainClientExec {
61
62 @Mock
63 private HttpClientConnectionManager connectionManager;
64 @Mock
65 private HttpProcessor httpProcessor;
66 @Mock
67 private ConnectionReuseStrategy reuseStrategy;
68 @Mock
69 private ConnectionKeepAliveStrategy keepAliveStrategy;
70 @Mock
71 private UserTokenHandler userTokenHandler;
72 @Mock
73 private ExecRuntime execRuntime;
74
75 private MainClientExec mainClientExec;
76 private HttpHost target;
77
78 @BeforeEach
79 public void setup() throws Exception {
80 MockitoAnnotations.openMocks(this);
81 mainClientExec = new MainClientExec(connectionManager, httpProcessor, reuseStrategy, keepAliveStrategy, userTokenHandler);
82 target = new HttpHost("foo", 80);
83 }
84
85 @Test
86 public void testFundamentals() throws Exception {
87 final HttpRoute route = new HttpRoute(target);
88 final ClassicHttpRequest request = new HttpGet("/test");
89 final HttpClientContext context = HttpClientContext.create();
90
91 final ClassicHttpResponse response = new BasicClassicHttpResponse(200, "OK");
92 final HttpEntity responseEntity = EntityBuilder.create()
93 .setStream(new ByteArrayInputStream(new byte[]{}))
94 .build();
95 response.setEntity(responseEntity);
96
97 Mockito.when(execRuntime.execute(
98 Mockito.anyString(),
99 Mockito.same(request),
100 Mockito.any())).thenReturn(response);
101
102 final ExecChain.Scope scope = new ExecChain.Scope("test", route, request, execRuntime, context);
103 final ClassicHttpResponse finalResponse = mainClientExec.execute(request, scope, null);
104
105 Mockito.verify(httpProcessor).process(request, null, context);
106 Mockito.verify(execRuntime).execute("test", request, context);
107 Mockito.verify(httpProcessor).process(response, responseEntity, context);
108
109 Assertions.assertEquals(route, context.getHttpRoute());
110 Assertions.assertSame(request, context.getRequest());
111 Assertions.assertSame(response, context.getResponse());
112 }
113
114 @Test
115 public void testExecRequestNonPersistentConnection() throws Exception {
116 final HttpRoute route = new HttpRoute(target);
117 final HttpClientContext context = new HttpClientContext();
118 final ClassicHttpRequest request = new HttpGet("http://bar/test");
119 final ClassicHttpResponse response = new BasicClassicHttpResponse(200, "OK");
120 response.setEntity(EntityBuilder.create()
121 .setStream(new ByteArrayInputStream(new byte[]{}))
122 .build());
123
124 Mockito.when(execRuntime.execute(
125 Mockito.anyString(),
126 Mockito.same(request),
127 Mockito.any())).thenReturn(response);
128 Mockito.when(reuseStrategy.keepAlive(
129 Mockito.same(request),
130 Mockito.same(response),
131 Mockito.<HttpClientContext>any())).thenReturn(false);
132
133 final ExecChain.Scope scope = new ExecChain.Scope("test", route, request, execRuntime, context);
134 final ClassicHttpResponse finalResponse = mainClientExec.execute(request, scope, null);
135 Mockito.verify(execRuntime).execute("test", request, context);
136 Mockito.verify(execRuntime, Mockito.times(1)).markConnectionNonReusable();
137 Mockito.verify(execRuntime, Mockito.never()).releaseEndpoint();
138
139 Assertions.assertNull(context.getUserToken());
140 Assertions.assertNotNull(finalResponse);
141 Assertions.assertTrue(finalResponse instanceof CloseableHttpResponse);
142 }
143
144 @Test
145 public void testExecRequestNonPersistentConnectionNoResponseEntity() throws Exception {
146 final HttpRoute route = new HttpRoute(target);
147 final HttpClientContext context = new HttpClientContext();
148 final ClassicHttpRequest request = new HttpGet("http://bar/test");
149 final ClassicHttpResponse response = new BasicClassicHttpResponse(200, "OK");
150 response.setEntity(null);
151
152 Mockito.when(execRuntime.execute(
153 Mockito.anyString(),
154 Mockito.same(request),
155 Mockito.any())).thenReturn(response);
156 Mockito.when(reuseStrategy.keepAlive(
157 Mockito.same(request),
158 Mockito.same(response),
159 Mockito.<HttpClientContext>any())).thenReturn(false);
160
161 final ExecChain.Scope scope = new ExecChain.Scope("test", route, request, execRuntime, context);
162 final ClassicHttpResponse finalResponse = mainClientExec.execute(request, scope, null);
163
164 Mockito.verify(execRuntime).execute("test", request, context);
165 Mockito.verify(execRuntime).markConnectionNonReusable();
166 Mockito.verify(execRuntime).releaseEndpoint();
167
168 Assertions.assertNotNull(finalResponse);
169 Assertions.assertTrue(finalResponse instanceof CloseableHttpResponse);
170 }
171
172 @Test
173 public void testExecRequestPersistentConnection() throws Exception {
174 final HttpRoute route = new HttpRoute(target);
175 final HttpClientContext context = new HttpClientContext();
176 final ClassicHttpRequest request = new HttpGet("http://bar/test");
177 final ClassicHttpResponse response = new BasicClassicHttpResponse(200, "OK");
178
179 response.setEntity(EntityBuilder.create()
180 .setStream(new ByteArrayInputStream(new byte[]{}))
181 .build());
182
183
184 Mockito.when(execRuntime.execute(
185 Mockito.anyString(),
186 Mockito.same(request),
187 Mockito.any())).thenReturn(response);
188 Mockito.when(reuseStrategy.keepAlive(
189 Mockito.same(request),
190 Mockito.same(response),
191 Mockito.<HttpClientContext>any())).thenReturn(true);
192 Mockito.when(keepAliveStrategy.getKeepAliveDuration(
193 Mockito.same(response),
194 Mockito.<HttpClientContext>any())).thenReturn(TimeValue.ofMilliseconds(678L));
195
196 final ExecChain.Scope scope = new ExecChain.Scope("test", route, request, execRuntime, context);
197 final ClassicHttpResponse finalResponse = mainClientExec.execute(request, scope, null);
198
199 Mockito.verify(execRuntime).execute("test", request, context);
200 Mockito.verify(execRuntime).markConnectionReusable(null, TimeValue.ofMilliseconds(678L));
201 Mockito.verify(execRuntime, Mockito.never()).releaseEndpoint();
202
203 Assertions.assertNotNull(finalResponse);
204 Assertions.assertTrue(finalResponse instanceof CloseableHttpResponse);
205 }
206
207 @Test
208 public void testExecRequestPersistentConnectionNoResponseEntity() throws Exception {
209 final HttpRoute route = new HttpRoute(target);
210 final HttpClientContext context = new HttpClientContext();
211 final ClassicHttpRequest request = new HttpGet("http://bar/test");
212 final ClassicHttpResponse response = new BasicClassicHttpResponse(200, "OK");
213
214 Mockito.when(execRuntime.execute(
215 Mockito.anyString(),
216 Mockito.same(request),
217 Mockito.any())).thenReturn(response);
218 Mockito.when(reuseStrategy.keepAlive(
219 Mockito.same(request),
220 Mockito.same(response),
221 Mockito.<HttpClientContext>any())).thenReturn(true);
222 Mockito.when(keepAliveStrategy.getKeepAliveDuration(
223 Mockito.same(response),
224 Mockito.<HttpClientContext>any())).thenReturn(TimeValue.ofMilliseconds(678L));
225
226 final ExecChain.Scope scope = new ExecChain.Scope("test", route, request, execRuntime, context);
227 final ClassicHttpResponse finalResponse = mainClientExec.execute(request, scope, null);
228
229 Mockito.verify(execRuntime).execute("test", request, context);
230 Mockito.verify(execRuntime).releaseEndpoint();
231
232 Assertions.assertNotNull(finalResponse);
233 Assertions.assertTrue(finalResponse instanceof CloseableHttpResponse);
234 }
235
236 @Test
237 public void testExecRequestConnectionRelease() throws Exception {
238 final HttpRoute route = new HttpRoute(target);
239 final HttpClientContext context = new HttpClientContext();
240 final ClassicHttpRequest request = new HttpGet("http://bar/test");
241 final ClassicHttpResponse response = new BasicClassicHttpResponse(200, "OK");
242
243 response.setEntity(EntityBuilder.create()
244 .setStream(new ByteArrayInputStream(new byte[]{}))
245 .build());
246
247 Mockito.when(execRuntime.execute(
248 Mockito.anyString(),
249 Mockito.same(request),
250 Mockito.any())).thenReturn(response);
251 Mockito.when(reuseStrategy.keepAlive(
252 Mockito.same(request),
253 Mockito.same(response),
254 Mockito.<HttpClientContext>any())).thenReturn(Boolean.FALSE);
255
256 final ExecChain.Scope scope = new ExecChain.Scope("test", route, request, execRuntime, context);
257 final ClassicHttpResponse finalResponse = mainClientExec.execute(request, scope, null);
258 Mockito.verify(execRuntime, Mockito.times(1)).execute("test", request, context);
259 Mockito.verify(execRuntime, Mockito.never()).disconnectEndpoint();
260 Mockito.verify(execRuntime, Mockito.never()).releaseEndpoint();
261
262 Assertions.assertNotNull(finalResponse);
263 Assertions.assertTrue(finalResponse instanceof CloseableHttpResponse);
264 finalResponse.close();
265
266 Mockito.verify(execRuntime).disconnectEndpoint();
267 Mockito.verify(execRuntime).discardEndpoint();
268 }
269
270 @Test
271 public void testExecConnectionShutDown() throws Exception {
272 final HttpRoute route = new HttpRoute(target);
273 final HttpClientContext context = new HttpClientContext();
274 final ClassicHttpRequest request = new HttpGet("http://bar/test");
275
276 Mockito.when(execRuntime.execute(
277 Mockito.anyString(),
278 Mockito.same(request),
279 Mockito.any())).thenThrow(new ConnectionShutdownException());
280
281 final ExecChain.Scope scope = new ExecChain.Scope("test", route, request, execRuntime, context);
282 Assertions.assertThrows(InterruptedIOException.class, () ->
283 mainClientExec.execute(request, scope, null));
284 Mockito.verify(execRuntime).discardEndpoint();
285 }
286
287 @Test
288 public void testExecRuntimeException() throws Exception {
289 final HttpRoute route = new HttpRoute(target);
290 final HttpClientContext context = new HttpClientContext();
291 final ClassicHttpRequest request = new HttpGet("http://bar/test");
292
293 Mockito.when(execRuntime.execute(
294 Mockito.anyString(),
295 Mockito.same(request),
296 Mockito.any())).thenThrow(new RuntimeException("Ka-boom"));
297
298 final ExecChain.Scope scope = new ExecChain.Scope("test", route, request, execRuntime, context);
299 Assertions.assertThrows(RuntimeException.class, () ->
300 mainClientExec.execute(request, scope, null));
301 Mockito.verify(execRuntime).discardEndpoint();
302 }
303
304 @Test
305 public void testExecHttpException() throws Exception {
306 final HttpRoute route = new HttpRoute(target);
307 final HttpClientContext context = new HttpClientContext();
308 final ClassicHttpRequest request = new HttpGet("http://bar/test");
309
310 Mockito.when(execRuntime.execute(
311 Mockito.anyString(),
312 Mockito.same(request),
313 Mockito.any())).thenThrow(new HttpException("Ka-boom"));
314
315 final ExecChain.Scope scope = new ExecChain.Scope("test", route, request, execRuntime, context);
316 Assertions.assertThrows(HttpException.class, () ->
317 mainClientExec.execute(request, scope, null));
318 Mockito.verify(execRuntime).discardEndpoint();
319 }
320
321 @Test
322 public void testExecIOException() throws Exception {
323 final HttpRoute route = new HttpRoute(target);
324 final HttpClientContext context = new HttpClientContext();
325 final ClassicHttpRequest request = new HttpGet("http://bar/test");
326
327 Mockito.when(execRuntime.execute(
328 Mockito.anyString(),
329 Mockito.same(request),
330 Mockito.any())).thenThrow(new IOException("Ka-boom"));
331
332 final ExecChain.Scope scope = new ExecChain.Scope("test", route, request, execRuntime, context);
333 Assertions.assertThrows(IOException.class, () ->
334 mainClientExec.execute(request, scope, null));
335 Mockito.verify(execRuntime).discardEndpoint();
336 }
337
338 }