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.util.concurrent.ExecutionException;
30 import java.util.concurrent.TimeUnit;
31 import java.util.concurrent.TimeoutException;
32
33 import org.apache.hc.client5.http.HttpRoute;
34 import org.apache.hc.client5.http.config.RequestConfig;
35 import org.apache.hc.client5.http.io.ConnectionEndpoint;
36 import org.apache.hc.client5.http.io.HttpClientConnectionManager;
37 import org.apache.hc.client5.http.io.LeaseRequest;
38 import org.apache.hc.client5.http.protocol.HttpClientContext;
39 import org.apache.hc.core5.concurrent.CancellableDependency;
40 import org.apache.hc.core5.http.ConnectionRequestTimeoutException;
41 import org.apache.hc.core5.http.HttpHost;
42 import org.apache.hc.core5.http.impl.io.HttpRequestExecutor;
43 import org.apache.hc.core5.io.CloseMode;
44 import org.apache.hc.core5.util.TimeValue;
45 import org.apache.hc.core5.util.Timeout;
46 import org.junit.jupiter.api.Assertions;
47 import org.junit.jupiter.api.BeforeEach;
48 import org.junit.jupiter.api.Test;
49 import org.mockito.Mock;
50 import org.mockito.Mockito;
51 import org.mockito.MockitoAnnotations;
52 import org.slf4j.Logger;
53
54 @SuppressWarnings({"static-access"})
55 public class TestInternalExecRuntime {
56
57 @Mock
58 private Logger log;
59 @Mock
60 private HttpClientConnectionManager mgr;
61 @Mock
62 private LeaseRequest leaseRequest;
63 @Mock
64 private HttpRequestExecutor requestExecutor;
65 @Mock
66 private CancellableDependency cancellableDependency;
67 @Mock
68 private ConnectionEndpoint connectionEndpoint;
69
70 private HttpRoute route;
71 private InternalExecRuntime execRuntime;
72
73 @BeforeEach
74 public void setup() {
75 MockitoAnnotations.openMocks(this);
76 route = new HttpRoute(new HttpHost("host", 80));
77 execRuntime = new InternalExecRuntime(log, mgr, requestExecutor, cancellableDependency);
78 }
79
80 @Test
81 public void testAcquireEndpoint() throws Exception {
82 final HttpClientContext context = HttpClientContext.create();
83 @SuppressWarnings("deprecation")
84 final RequestConfig config = RequestConfig.custom()
85 .setConnectionRequestTimeout(345, TimeUnit.MILLISECONDS)
86 .setConnectTimeout(123, TimeUnit.MILLISECONDS)
87 .build();
88 context.setRequestConfig(config);
89 final HttpRoute route = new HttpRoute(new HttpHost("host", 80));
90
91 Mockito.when(mgr.lease(Mockito.eq("some-id"), Mockito.eq(route), Mockito.any(), Mockito.any()))
92 .thenReturn(leaseRequest);
93 Mockito.when(leaseRequest.get(Mockito.any())).thenReturn(connectionEndpoint);
94
95 execRuntime.acquireEndpoint("some-id", route, null, context);
96
97 Assertions.assertTrue(execRuntime.isEndpointAcquired());
98 Assertions.assertSame(connectionEndpoint, execRuntime.ensureValid());
99 Assertions.assertFalse(execRuntime.isEndpointConnected());
100 Assertions.assertFalse(execRuntime.isConnectionReusable());
101
102 Mockito.verify(leaseRequest).get(Timeout.ofMilliseconds(345));
103 Mockito.verify(cancellableDependency, Mockito.times(1)).setDependency(leaseRequest);
104 Mockito.verify(cancellableDependency, Mockito.times(1)).setDependency(execRuntime);
105 Mockito.verify(cancellableDependency, Mockito.times(2)).setDependency(Mockito.any());
106 }
107
108 @Test
109 public void testAcquireEndpointAlreadyAcquired() throws Exception {
110 final HttpClientContext context = HttpClientContext.create();
111
112 Mockito.when(mgr.lease(Mockito.eq("some-id"), Mockito.eq(route), Mockito.any(), Mockito.any()))
113 .thenReturn(leaseRequest);
114 Mockito.when(leaseRequest.get(Mockito.any())).thenReturn(connectionEndpoint);
115
116 execRuntime.acquireEndpoint("some-id", route, null, context);
117
118 Assertions.assertTrue(execRuntime.isEndpointAcquired());
119 Assertions.assertSame(connectionEndpoint, execRuntime.ensureValid());
120
121 Assertions.assertThrows(IllegalStateException.class, () ->
122 execRuntime.acquireEndpoint("some-id", route, null, context));
123 }
124
125 @Test
126 public void testAcquireEndpointLeaseRequestTimeout() throws Exception {
127 final HttpClientContext context = HttpClientContext.create();
128
129 Mockito.when(mgr.lease(Mockito.eq("some-id"), Mockito.eq(route), Mockito.any(), Mockito.any()))
130 .thenReturn(leaseRequest);
131 Mockito.when(leaseRequest.get(Mockito.any())).thenThrow(new TimeoutException("timeout"));
132
133 Assertions.assertThrows(ConnectionRequestTimeoutException.class, () ->
134 execRuntime.acquireEndpoint("some-id", route, null, context));
135 }
136
137 @Test
138 public void testAcquireEndpointLeaseRequestFailure() throws Exception {
139 final HttpClientContext context = HttpClientContext.create();
140
141 Mockito.when(mgr.lease(Mockito.eq("some-id"), Mockito.eq(route), Mockito.any(), Mockito.any()))
142 .thenReturn(leaseRequest);
143 Mockito.when(leaseRequest.get(Mockito.any())).thenThrow(new ExecutionException(new IllegalStateException()));
144
145 Assertions.assertThrows(RequestFailedException.class, () ->
146 execRuntime.acquireEndpoint("some-id", route, null, context));
147 }
148
149 @Test
150 public void testAbortEndpoint() throws Exception {
151 final HttpClientContext context = HttpClientContext.create();
152 Mockito.when(mgr.lease(Mockito.eq("some-id"), Mockito.eq(route), Mockito.any(), Mockito.any()))
153 .thenReturn(leaseRequest);
154 Mockito.when(leaseRequest.get(Mockito.any())).thenReturn(connectionEndpoint);
155
156 execRuntime.acquireEndpoint("some-id", new HttpRoute(new HttpHost("host", 80)), null, context);
157 Assertions.assertTrue(execRuntime.isEndpointAcquired());
158 execRuntime.discardEndpoint();
159
160 Assertions.assertFalse(execRuntime.isEndpointAcquired());
161
162 Mockito.verify(connectionEndpoint).close(CloseMode.IMMEDIATE);
163 Mockito.verify(mgr).release(connectionEndpoint, null, TimeValue.ZERO_MILLISECONDS);
164
165 execRuntime.discardEndpoint();
166
167 Mockito.verify(connectionEndpoint, Mockito.times(1)).close(CloseMode.IMMEDIATE);
168 Mockito.verify(mgr, Mockito.times(1)).release(
169 Mockito.any(),
170 Mockito.any(),
171 Mockito.any());
172 }
173
174 @Test
175 public void testCancell() throws Exception {
176 final HttpClientContext context = HttpClientContext.create();
177
178 Mockito.when(mgr.lease(Mockito.eq("some-id"), Mockito.eq(route), Mockito.any(), Mockito.any()))
179 .thenReturn(leaseRequest);
180 Mockito.when(leaseRequest.get(Mockito.any())).thenReturn(connectionEndpoint);
181
182 execRuntime.acquireEndpoint("some-id", route, null, context);
183 Assertions.assertTrue(execRuntime.isEndpointAcquired());
184
185 Assertions.assertTrue(execRuntime.cancel());
186
187 Assertions.assertFalse(execRuntime.isEndpointAcquired());
188
189 Mockito.verify(connectionEndpoint).close(CloseMode.IMMEDIATE);
190 Mockito.verify(mgr).release(connectionEndpoint, null, TimeValue.ZERO_MILLISECONDS);
191
192 Assertions.assertFalse(execRuntime.cancel());
193
194 Mockito.verify(connectionEndpoint, Mockito.times(1)).close(CloseMode.IMMEDIATE);
195 Mockito.verify(mgr, Mockito.times(1)).release(
196 Mockito.any(),
197 Mockito.any(),
198 Mockito.any());
199 }
200
201 @Test
202 public void testReleaseEndpointReusable() throws Exception {
203 final HttpClientContext context = HttpClientContext.create();
204
205 Mockito.when(mgr.lease(Mockito.eq("some-id"), Mockito.eq(route), Mockito.any(), Mockito.any()))
206 .thenReturn(leaseRequest);
207 Mockito.when(leaseRequest.get(Mockito.any())).thenReturn(connectionEndpoint);
208
209 execRuntime.acquireEndpoint("some-id", route, null, context);
210 Assertions.assertTrue(execRuntime.isEndpointAcquired());
211
212 execRuntime.markConnectionReusable("some state", TimeValue.ofMilliseconds(100000));
213
214 execRuntime.releaseEndpoint();
215
216 Assertions.assertFalse(execRuntime.isEndpointAcquired());
217
218 Mockito.verify(connectionEndpoint, Mockito.never()).close();
219 Mockito.verify(mgr).release(connectionEndpoint, "some state", TimeValue.ofMilliseconds(100000));
220
221 execRuntime.releaseEndpoint();
222
223 Mockito.verify(mgr, Mockito.times(1)).release(
224 Mockito.any(),
225 Mockito.any(),
226 Mockito.any());
227 }
228
229 @Test
230 public void testReleaseEndpointNonReusable() throws Exception {
231 final HttpClientContext context = HttpClientContext.create();
232
233 Mockito.when(mgr.lease(Mockito.eq("some-id"), Mockito.eq(route), Mockito.any(), Mockito.any()))
234 .thenReturn(leaseRequest);
235 Mockito.when(leaseRequest.get(Mockito.any())).thenReturn(connectionEndpoint);
236
237 execRuntime.acquireEndpoint("some-id", route, null, context);
238 Assertions.assertTrue(execRuntime.isEndpointAcquired());
239
240 execRuntime.markConnectionReusable("some state", TimeValue.ofMilliseconds(100000));
241 execRuntime.markConnectionNonReusable();
242
243 execRuntime.releaseEndpoint();
244
245 Assertions.assertFalse(execRuntime.isEndpointAcquired());
246
247 Mockito.verify(connectionEndpoint, Mockito.times(1)).close(CloseMode.IMMEDIATE);
248 Mockito.verify(mgr).release(connectionEndpoint, null, TimeValue.ZERO_MILLISECONDS);
249
250 execRuntime.releaseEndpoint();
251
252 Mockito.verify(mgr, Mockito.times(1)).release(
253 Mockito.any(),
254 Mockito.any(),
255 Mockito.any());
256 }
257
258 @Test
259 public void testConnectEndpoint() throws Exception {
260 final HttpClientContext context = HttpClientContext.create();
261 @SuppressWarnings("deprecation")
262 final RequestConfig config = RequestConfig.custom()
263 .setConnectionRequestTimeout(345, TimeUnit.MILLISECONDS)
264 .setConnectTimeout(123, TimeUnit.MILLISECONDS)
265 .build();
266 context.setRequestConfig(config);
267
268 Mockito.when(mgr.lease(Mockito.eq("some-id"), Mockito.eq(route), Mockito.any(), Mockito.any()))
269 .thenReturn(leaseRequest);
270 Mockito.when(leaseRequest.get(Mockito.any())).thenReturn(connectionEndpoint);
271
272 execRuntime.acquireEndpoint("some-id", route, null, context);
273 Assertions.assertTrue(execRuntime.isEndpointAcquired());
274
275 Mockito.when(connectionEndpoint.isConnected()).thenReturn(false);
276 Assertions.assertFalse(execRuntime.isEndpointConnected());
277
278 execRuntime.connectEndpoint(context);
279
280 Mockito.verify(mgr).connect(connectionEndpoint, Timeout.ofMilliseconds(123), context);
281 }
282
283 @Test
284 public void testDisonnectEndpoint() throws Exception {
285 final HttpClientContext context = HttpClientContext.create();
286
287 Mockito.when(mgr.lease(Mockito.eq("some-id"), Mockito.eq(route), Mockito.any(), Mockito.any()))
288 .thenReturn(leaseRequest);
289 Mockito.when(leaseRequest.get(Mockito.any())).thenReturn(connectionEndpoint);
290
291 execRuntime.acquireEndpoint("some-id", route, null, context);
292 Assertions.assertTrue(execRuntime.isEndpointAcquired());
293
294 Mockito.when(connectionEndpoint.isConnected()).thenReturn(true);
295 Assertions.assertTrue(execRuntime.isEndpointConnected());
296
297 execRuntime.connectEndpoint(context);
298
299 Mockito.verify(mgr, Mockito.never()).connect(
300 Mockito.same(connectionEndpoint), Mockito.any(), Mockito.<HttpClientContext>any());
301
302 execRuntime.disconnectEndpoint();
303
304 Mockito.verify(connectionEndpoint).close();
305 }
306
307 }