1
2
3
4
5
6 package com.jcabi.http;
7
8 import com.jcabi.http.request.BaseRequest;
9 import java.io.IOException;
10 import java.io.InputStream;
11 import java.net.URI;
12 import java.util.Collection;
13 import java.util.Map;
14 import java.util.concurrent.Callable;
15 import java.util.function.Supplier;
16 import org.hamcrest.MatcherAssert;
17 import org.hamcrest.Matchers;
18 import org.junit.jupiter.api.Test;
19 import org.junit.jupiter.params.ParameterizedTest;
20 import org.mockito.ArgumentCaptor;
21 import org.mockito.ArgumentMatchers;
22 import org.mockito.Mockito;
23
24
25
26
27
28 @SuppressWarnings("PMD.TooManyMethods")
29 final class RequestTimeoutLossTest extends RequestTestTemplate {
30
31
32
33 private static final String LOCALHOST_URL = "http://localhost";
34
35
36
37
38 private static final String CONTENT_TYPE = "Content-Type";
39
40
41
42
43 private static final int CONNECT_TIMEOUT = 1234;
44
45
46
47
48 private static final int READ_TIMEOUT = 2345;
49
50
51
52
53
54
55
56
57 @ParameterizedTest
58 @Values
59 void testTimeoutOrderDoesntMatterBeforeBody(
60 final Class<? extends Request> type
61 )
62 throws Exception {
63 final Callable<Response> execution = () -> RequestTimeoutLossTest.request(type)
64 .through(MockWire.class)
65 .method(Request.GET)
66 .timeout(
67 RequestTimeoutLossTest.CONNECT_TIMEOUT,
68 RequestTimeoutLossTest.READ_TIMEOUT
69 )
70 .body()
71 .back()
72 .fetch();
73 this.testTimeoutOrderDoesntMatter(execution);
74 }
75
76
77
78
79
80
81
82
83 @ParameterizedTest
84 @Values
85 void testTimeoutOrderDoesntMatterBeforeFetch(
86 final Class<? extends Request> type
87 )
88 throws Exception {
89 final Callable<Response> execution = () -> RequestTimeoutLossTest.request(type)
90 .through(MockWire.class)
91 .method(Request.GET)
92 .timeout(
93 RequestTimeoutLossTest.CONNECT_TIMEOUT,
94 RequestTimeoutLossTest.READ_TIMEOUT
95 )
96 .fetch();
97 this.testTimeoutOrderDoesntMatter(execution);
98 }
99
100
101
102
103
104
105
106
107 @ParameterizedTest
108 @Values
109 void testTimeoutOrderDoesntMatterBeforeHeader(
110 final Class<? extends Request> type
111 )
112 throws Exception {
113 final Callable<Response> execution = () -> RequestTimeoutLossTest.request(type)
114 .through(MockWire.class)
115 .method(Request.GET)
116 .timeout(
117 RequestTimeoutLossTest.CONNECT_TIMEOUT,
118 RequestTimeoutLossTest.READ_TIMEOUT
119 )
120 .header(
121 RequestTimeoutLossTest.CONTENT_TYPE,
122 "text/plain"
123 )
124 .fetch();
125 this.testTimeoutOrderDoesntMatter(execution);
126 }
127
128
129
130
131
132
133
134
135 @ParameterizedTest
136 @Values
137 void testTimeoutOrderDoesntMatterBeforeMethod(
138 final Class<? extends Request> type
139 )
140 throws Exception {
141 final Callable<Response> execution = () -> RequestTimeoutLossTest.request(type)
142 .through(MockWire.class)
143 .timeout(
144 RequestTimeoutLossTest.CONNECT_TIMEOUT,
145 RequestTimeoutLossTest.READ_TIMEOUT
146 )
147 .method(Request.GET)
148 .fetch();
149 this.testTimeoutOrderDoesntMatter(execution);
150 }
151
152
153
154
155
156
157
158
159 @ParameterizedTest
160 @Values
161 void testTimeoutOrderDoesntMatterBeforeMultipartBody(
162 final Class<? extends Request> type
163 )
164 throws Exception {
165 final Callable<Response> execution = () -> RequestTimeoutLossTest.request(type)
166 .through(MockWire.class)
167 .method(Request.GET)
168 .timeout(
169 RequestTimeoutLossTest.CONNECT_TIMEOUT,
170 RequestTimeoutLossTest.READ_TIMEOUT
171 )
172 .multipartBody()
173 .back()
174 .fetch();
175 this.testTimeoutOrderDoesntMatter(execution);
176 }
177
178
179
180
181
182
183
184
185 @ParameterizedTest
186 @Values
187 void testTimeoutOrderDoesntMatterBeforeReset(
188 final Class<? extends Request> type
189 )
190 throws Exception {
191 final Callable<Response> execution = () -> RequestTimeoutLossTest.request(type)
192 .through(MockWire.class)
193 .method(Request.GET)
194 .timeout(
195 RequestTimeoutLossTest.CONNECT_TIMEOUT,
196 RequestTimeoutLossTest.READ_TIMEOUT
197 )
198 .reset(RequestTimeoutLossTest.CONTENT_TYPE)
199 .fetch();
200 this.testTimeoutOrderDoesntMatter(execution);
201 }
202
203
204
205
206
207
208
209
210 @ParameterizedTest
211 @Values
212 void testTimeoutOrderDoesntMatterBeforeUriBack(
213 final Class<? extends Request> type
214 )
215 throws Exception {
216 this.testTimeoutOrderDoesntMatter(
217 () -> RequestTimeoutLossTest.request(type)
218 .through(MockWire.class)
219 .method(Request.GET)
220 .timeout(
221 RequestTimeoutLossTest.CONNECT_TIMEOUT,
222 RequestTimeoutLossTest.READ_TIMEOUT
223 )
224 .uri()
225 .path("/api")
226 .back()
227 .fetch()
228 );
229 }
230
231
232
233
234
235
236 @Test
237 void passesThroughWire() throws IOException {
238 final Wire original = Mockito.mock(Wire.class);
239 final Wire wire = Mockito.mock(Wire.class);
240 final Response response = Mockito.mock(Response.class);
241 final Supplier<Collection<Map.Entry<String, String>>> hdrs =
242 () -> ArgumentMatchers.anyCollection();
243 final String url = "fake-url";
244 Mockito.when(
245 wire.send(
246 ArgumentMatchers.any(Request.class),
247 ArgumentMatchers.eq(url),
248 ArgumentMatchers.anyString(),
249 hdrs.get(),
250 ArgumentMatchers.any(InputStream.class),
251 ArgumentMatchers.anyInt(),
252 ArgumentMatchers.anyInt()
253 )
254 ).thenReturn(response);
255 new BaseRequest(original, url).through(wire).fetch();
256 Mockito.verify(original, Mockito.never()).send(
257 ArgumentMatchers.any(Request.class),
258 ArgumentMatchers.anyString(),
259 ArgumentMatchers.anyString(),
260 hdrs.get(),
261 ArgumentMatchers.any(InputStream.class),
262 ArgumentMatchers.anyInt(),
263 ArgumentMatchers.anyInt()
264 );
265 Mockito.verify(wire).send(
266 ArgumentMatchers.any(Request.class),
267 ArgumentMatchers.anyString(),
268 ArgumentMatchers.anyString(),
269 hdrs.get(),
270 ArgumentMatchers.any(InputStream.class),
271 ArgumentMatchers.anyInt(),
272 ArgumentMatchers.anyInt()
273 );
274 }
275
276
277
278
279
280
281
282
283 @SuppressWarnings("unchecked")
284 private void testTimeoutOrderDoesntMatter(final Callable<Response> exec)
285 throws Exception {
286 synchronized (MockWire.class) {
287 final Wire wire = Mockito.mock(Wire.class);
288 final ArgumentCaptor<Integer> cnc = ArgumentCaptor
289 .forClass(Integer.class);
290 final ArgumentCaptor<Integer> rdc = ArgumentCaptor
291 .forClass(Integer.class);
292 MockWire.setMockDelegate(wire);
293 final Response response = Mockito.mock(Response.class);
294 Mockito.when(
295 wire.send(
296 Mockito.any(Request.class),
297 Mockito.anyString(),
298 Mockito.anyString(),
299 Mockito.<Map.Entry<String, String>>anyCollection(),
300 Mockito.any(InputStream.class),
301 Mockito.anyInt(),
302 Mockito.anyInt()
303 )
304 ).thenReturn(response);
305 exec.call();
306 Mockito.verify(wire).send(
307 Mockito.any(Request.class),
308 Mockito.anyString(),
309 Mockito.anyString(),
310 Mockito.<Map.Entry<String, String>>anyCollection(),
311 Mockito.any(InputStream.class),
312 cnc.capture(),
313 rdc.capture()
314 );
315 MatcherAssert.assertThat(
316 "should be connect timeout",
317 cnc.getValue().intValue(),
318 Matchers.is(RequestTimeoutLossTest.CONNECT_TIMEOUT)
319 );
320 MatcherAssert.assertThat(
321 "should be read timeout",
322 rdc.getValue().intValue(),
323 Matchers.is(RequestTimeoutLossTest.READ_TIMEOUT)
324 );
325 }
326 }
327
328
329
330
331
332
333
334 private static Request request(final Class<? extends Request> type)
335 throws Exception {
336 return RequestTestTemplate.request(
337 new URI(RequestTimeoutLossTest.LOCALHOST_URL),
338 type
339 );
340 }
341
342 }