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
28 package org.apache.hc.client5.http;
29
30 import java.net.InetAddress;
31 import java.util.HashSet;
32 import java.util.Set;
33
34 import org.apache.hc.client5.http.RouteInfo.LayerType;
35 import org.apache.hc.client5.http.RouteInfo.TunnelType;
36 import org.apache.hc.core5.http.HttpHost;
37 import org.apache.hc.core5.net.URIAuthority;
38 import org.junit.jupiter.api.Assertions;
39 import org.junit.jupiter.api.Test;
40
41
42
43
44 class TestHttpRoute {
45
46
47 public final static
48 HttpHost TARGET1 = new HttpHost("target1.test.invalid", 80);
49 public final static
50 HttpHost TARGET2 = new HttpHost("target2.test.invalid", 8080);
51
52
53
54
55 public final static
56 HttpHost PROXY1 = new HttpHost("proxy1.test.invalid");
57 public final static
58 HttpHost PROXY2 = new HttpHost("proxy2.test.invalid", 1080);
59 public final static
60 HttpHost PROXY3 = new HttpHost("proxy3.test.invalid", 88);
61
62 public final static InetAddress LOCAL41;
63 public final static InetAddress LOCAL42;
64 public final static InetAddress LOCAL61;
65 public final static InetAddress LOCAL62;
66
67
68 static {
69 try {
70 LOCAL41 = InetAddress.getByAddress(new byte[]{ 127, 0, 0, 1 });
71 LOCAL42 = InetAddress.getByAddress(new byte[]{ 127, 0, 0, 2 });
72
73 LOCAL61 = InetAddress.getByAddress(new byte[]{
74 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
75 });
76 LOCAL62 = InetAddress.getByAddress(new byte[]{
77 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2
78 });
79
80 } catch (final Exception x) {
81 throw new ExceptionInInitializerError(x);
82 }
83 }
84
85 @Test
86 void testCstrFullRoute() {
87
88 final HttpHost[] chain3 = { PROXY1, PROXY2, PROXY3 };
89
90 final HttpRoute route = new HttpRoute(TARGET1, LOCAL41, chain3, false,
91 TunnelType.PLAIN, LayerType.PLAIN);
92 Assertions.assertEquals(TARGET1, route.getTargetHost(), "wrong target");
93 Assertions.assertEquals(LOCAL41, route.getLocalAddress(), "wrong local address");
94 Assertions.assertEquals(PROXY1, route.getProxyHost(), "wrong proxy host");
95 Assertions.assertEquals(4, route.getHopCount(), "wrong hop count");
96 Assertions.assertEquals(PROXY1, route.getHopTarget(0), "wrong hop 0");
97 Assertions.assertEquals(PROXY2, route.getHopTarget(1), "wrong hop 1");
98 Assertions.assertEquals(PROXY3, route.getHopTarget(2), "wrong hop 2");
99 Assertions.assertEquals(TARGET1, route.getHopTarget(3), "wrong hop 3");
100 Assertions.assertFalse(route.isSecure(), "wrong flag: secured");
101 Assertions.assertFalse(route.isTunnelled(), "wrong flag: tunnelled");
102 Assertions.assertFalse(route.isLayered(), "wrong flag: layered");
103
104 final String routestr = route.toString();
105 Assertions.assertTrue(routestr.contains(TARGET1.getHostName()), "missing target in toString");
106 Assertions.assertTrue(routestr.contains(LOCAL41.toString()), "missing local address in toString");
107 Assertions.assertTrue(routestr.contains(PROXY1.getHostName()), "missing proxy 1 in toString");
108 Assertions.assertTrue(routestr.contains(PROXY2.getHostName()), "missing proxy 2 in toString");
109 Assertions.assertTrue(routestr.contains(PROXY3.getHostName()), "missing proxy 3 in toString");
110 }
111
112 @Test
113 void testCstrFullFlags() {
114
115
116 final HttpHost[] chain3 = { PROXY1, PROXY2, PROXY3 };
117
118 final HttpRoute routefff = new HttpRoute
119 (TARGET1, LOCAL41, chain3, false,
120 TunnelType.PLAIN, LayerType.PLAIN);
121 final HttpRoute routefft = new HttpRoute
122 (TARGET1, LOCAL41, chain3, false,
123 TunnelType.PLAIN, LayerType.LAYERED);
124 final HttpRoute routeftf = new HttpRoute
125 (TARGET1, LOCAL41, chain3, false,
126 TunnelType.TUNNELLED, LayerType.PLAIN);
127 final HttpRoute routeftt = new HttpRoute
128 (TARGET1, LOCAL41, chain3, false,
129 TunnelType.TUNNELLED, LayerType.LAYERED);
130 final HttpRoute routetff = new HttpRoute
131 (TARGET1, LOCAL41, chain3, true,
132 TunnelType.PLAIN, LayerType.PLAIN);
133 final HttpRoute routetft = new HttpRoute
134 (TARGET1, LOCAL41, chain3, true,
135 TunnelType.PLAIN, LayerType.LAYERED);
136 final HttpRoute routettf = new HttpRoute
137 (TARGET1, LOCAL41, chain3, true,
138 TunnelType.TUNNELLED, LayerType.PLAIN);
139 final HttpRoute routettt = new HttpRoute
140 (TARGET1, LOCAL41, chain3, true,
141 TunnelType.TUNNELLED, LayerType.LAYERED);
142
143 Assertions.assertFalse(routefff.isSecure(), "routefff.secure");
144 Assertions.assertFalse(routefff.isTunnelled(), "routefff.tunnel");
145 Assertions.assertFalse(routefff.isLayered(), "routefff.layer");
146
147 Assertions.assertFalse(routefft.isSecure(), "routefft.secure");
148 Assertions.assertFalse(routefft.isTunnelled(), "routefft.tunnel");
149 Assertions.assertTrue (routefft.isLayered(), "routefft.layer");
150
151 Assertions.assertFalse(routeftf.isSecure(), "routeftf.secure");
152 Assertions.assertTrue (routeftf.isTunnelled(), "routeftf.tunnel");
153 Assertions.assertFalse(routeftf.isLayered(), "routeftf.layer");
154
155 Assertions.assertFalse(routeftt.isSecure(), "routeftt.secure");
156 Assertions.assertTrue (routeftt.isTunnelled(), "routeftt.tunnel");
157 Assertions.assertTrue (routeftt.isLayered(), "routeftt.layer");
158
159 Assertions.assertTrue (routetff.isSecure(), "routetff.secure");
160 Assertions.assertFalse(routetff.isTunnelled(), "routetff.tunnel");
161 Assertions.assertFalse(routetff.isLayered(), "routetff.layer");
162
163 Assertions.assertTrue (routetft.isSecure(), "routetft.secure");
164 Assertions.assertFalse(routetft.isTunnelled(), "routetft.tunnel");
165 Assertions.assertTrue (routetft.isLayered(), "routetft.layer");
166
167 Assertions.assertTrue (routettf.isSecure(), "routettf.secure");
168 Assertions.assertTrue (routettf.isTunnelled(), "routettf.tunnel");
169 Assertions.assertFalse(routettf.isLayered(), "routettf.layer");
170
171 Assertions.assertTrue (routettt.isSecure(), "routettt.secure");
172 Assertions.assertTrue (routettt.isTunnelled(), "routettt.tunnel");
173 Assertions.assertTrue (routettt.isLayered(), "routettt.layer");
174 }
175
176 @Test
177 void testInvalidArguments() {
178 final HttpHost[] chain1 = { PROXY1 };
179
180
181 final HttpRoute route = new HttpRoute(TARGET1, null, chain1, false,
182 TunnelType.TUNNELLED, LayerType.PLAIN);
183 Assertions.assertNotNull(route);
184
185 Assertions.assertThrows(NullPointerException.class, () ->
186 new HttpRoute(null, null, chain1, false,TunnelType.TUNNELLED, LayerType.PLAIN));
187 Assertions.assertThrows(IllegalArgumentException.class, () ->
188 new HttpRoute(TARGET1, null, (HttpHost[]) null, false, TunnelType.TUNNELLED, LayerType.PLAIN));
189 }
190
191 @Test
192 void testNullEnums() {
193
194
195
196
197 final HttpRoute route = new HttpRoute(TARGET1, null, PROXY1, false,
198 null, null);
199
200 Assertions.assertFalse(route.isTunnelled(), "default tunnelling");
201 Assertions.assertEquals(TunnelType.PLAIN, route.getTunnelType(), "untunnelled");
202
203 Assertions.assertFalse(route.isLayered(), "default layering");
204 Assertions.assertEquals(LayerType.PLAIN, route.getLayerType(), "unlayered");
205 }
206
207 @Test
208 void testEqualsHashcodeClone() throws CloneNotSupportedException {
209 final HttpHost[] chain0 = { };
210 final HttpHost[] chain1 = { PROXY1 };
211 final HttpHost[] chain3 = { PROXY1, PROXY2, PROXY3 };
212 final HttpHost[] chain4 = { PROXY1, PROXY3, PROXY2 };
213
214
215 final HttpRoute route1a = new HttpRoute(TARGET1, LOCAL41, chain3, false,
216 TunnelType.PLAIN, LayerType.PLAIN);
217 final HttpRoute route1b = new HttpRoute(TARGET1, LOCAL41, chain3, false,
218 TunnelType.PLAIN, LayerType.PLAIN);
219 final HttpRoute route1c = (HttpRoute) route1a.clone();
220
221 Assertions.assertEquals(route1a, route1a, "1a 1a");
222 Assertions.assertEquals(route1a, route1b, "1a 1b");
223 Assertions.assertEquals(route1a, route1c, "1a 1c");
224
225 Assertions.assertEquals(route1a.hashCode(), route1a.hashCode(), "hashcode 1a");
226 Assertions.assertEquals(route1a.hashCode(), route1b.hashCode(), "hashcode 1b");
227 Assertions.assertEquals(route1a.hashCode(), route1c.hashCode(), "hashcode 1c");
228
229 Assertions.assertEquals(route1a.toString(), route1b.toString(), "toString 1b");
230 Assertions.assertEquals(route1a.toString(), route1a.toString(), "toString 1a");
231 Assertions.assertEquals(route1a.toString(), route1c.toString(), "toString 1c");
232
233
234 final HttpRoute route2a = new HttpRoute(TARGET2, LOCAL41, chain3, false,
235 TunnelType.PLAIN, LayerType.PLAIN);
236 final HttpRoute route2b = new HttpRoute(TARGET1, LOCAL42, chain3, false,
237 TunnelType.PLAIN, LayerType.PLAIN);
238 final HttpRoute route2c = new HttpRoute(TARGET1, LOCAL61, chain3, false,
239 TunnelType.PLAIN, LayerType.PLAIN);
240 final HttpRoute route2d = new HttpRoute(TARGET1, null, chain3, false,
241 TunnelType.PLAIN, LayerType.PLAIN);
242 final HttpRoute route2e = new HttpRoute(TARGET1, LOCAL41, (HttpHost[]) null,
243 false,
244 TunnelType.PLAIN, LayerType.PLAIN);
245 final HttpRoute route2f = new HttpRoute(TARGET1, LOCAL41, chain0, false,
246 TunnelType.PLAIN, LayerType.PLAIN);
247 final HttpRoute route2g = new HttpRoute(TARGET1, LOCAL41, chain1, false,
248 TunnelType.PLAIN, LayerType.PLAIN);
249 final HttpRoute route2h = new HttpRoute(TARGET1, LOCAL41, chain4, false,
250 TunnelType.PLAIN, LayerType.PLAIN);
251 final HttpRoute route2i = new HttpRoute(TARGET1, LOCAL41, chain3, true,
252 TunnelType.PLAIN, LayerType.PLAIN);
253 final HttpRoute route2j = new HttpRoute(TARGET1, LOCAL41, chain3, false,
254 TunnelType.TUNNELLED, LayerType.PLAIN);
255 final HttpRoute route2k = new HttpRoute(TARGET1, LOCAL41, chain3, false,
256 TunnelType.PLAIN, LayerType.LAYERED);
257 final HttpRoute route2m = new HttpRoute(TARGET2,
258 new URIAuthority(TARGET2.getHostName(), TARGET2.getPort()), LOCAL41, chain3, false,
259 TunnelType.PLAIN, LayerType.PLAIN);
260
261
262 Assertions.assertEquals(route2e, route2f, "2e 2f");
263 Assertions.assertEquals(route2e.hashCode(), route2f.hashCode(), "hashcode 2e 2f");
264 Assertions.assertEquals(route2e.toString(), route2f.toString(), "toString 2e 2f");
265
266 Assertions.assertNotEquals(route1a, route2a, "1a 2a");
267 Assertions.assertNotEquals(route1a, route2b, "1a 2b");
268 Assertions.assertNotEquals(route1a, route2c, "1a 2c");
269 Assertions.assertNotEquals(route1a, route2d, "1a 2d");
270 Assertions.assertNotEquals(route1a, route2e, "1a 2e");
271 Assertions.assertNotEquals(route1a, route2f, "1a 2f");
272 Assertions.assertNotEquals(route1a, route2g, "1a 2g");
273 Assertions.assertNotEquals(route1a, route2h, "1a 2h");
274 Assertions.assertNotEquals(route1a, route2i, "1a 2i");
275 Assertions.assertNotEquals(route1a, route2j, "1a 2j");
276 Assertions.assertNotEquals(route1a, route2k, "1a 2k");
277 Assertions.assertNotEquals(route1a, route2m, "1a 2k");
278
279
280
281
282 Assertions.assertNotEquals(route2b, route1a, "2b 1a");
283 Assertions.assertNotEquals(route2c, route1a, "2c 1a");
284 Assertions.assertNotEquals(route2d, route1a, "2d 1a");
285 Assertions.assertNotEquals(route2e, route1a, "2e 1a");
286 Assertions.assertNotEquals(route2a, route1a, "2a 1a");
287 Assertions.assertNotEquals(route2f, route1a, "2f 1a");
288 Assertions.assertNotEquals(route2g, route1a, "2g 1a");
289 Assertions.assertNotEquals(route2h, route1a, "2h 1a");
290 Assertions.assertNotEquals(route2i, route1a, "2i 1a");
291 Assertions.assertNotEquals(route2j, route1a, "2j 1a");
292 Assertions.assertNotEquals(route2k, route1a, "2k 1a");
293 Assertions.assertNotEquals(route2m, route1a, "2k 1a");
294
295
296
297 Assertions.assertNotEquals(route1a.toString(), route2a.toString(), "toString 1a 2a");
298 Assertions.assertNotEquals(route1a.toString(), route2b.toString(), "toString 1a 2b");
299 Assertions.assertNotEquals(route1a.toString(), route2c.toString(), "toString 1a 2c");
300 Assertions.assertNotEquals(route1a.toString(), route2d.toString(), "toString 1a 2d");
301 Assertions.assertNotEquals(route1a.toString(), route2e.toString(), "toString 1a 2e");
302 Assertions.assertNotEquals(route1a.toString(), route2f.toString(), "toString 1a 2f");
303 Assertions.assertNotEquals(route1a.toString(), route2g.toString(), "toString 1a 2g");
304 Assertions.assertNotEquals(route1a.toString(), route2h.toString(), "toString 1a 2h");
305 Assertions.assertNotEquals(route1a.toString(), route2i.toString(), "toString 1a 2i");
306 Assertions.assertNotEquals(route1a.toString(), route2j.toString(), "toString 1a 2j");
307 Assertions.assertNotEquals(route1a.toString(), route2k.toString(), "toString 1a 2k");
308 Assertions.assertNotEquals(route1a.toString(), route2m.toString(), "toString 1a 2k");
309
310
311
312 final Set<HttpRoute> routes = new HashSet<>();
313 routes.add(route1a);
314 routes.add(route2a);
315 routes.add(route2b);
316 routes.add(route2c);
317 routes.add(route2d);
318 routes.add(route2e);
319
320 routes.add(route2g);
321 routes.add(route2h);
322 routes.add(route2i);
323 routes.add(route2j);
324 routes.add(route2k);
325 routes.add(route2m);
326
327
328 for (final HttpRoute origin : routes) {
329 final HttpRoute cloned = (HttpRoute) origin.clone();
330 Assertions.assertEquals(origin, cloned, "clone of " + origin);
331 Assertions.assertTrue(routes.contains(cloned), "clone of " + origin);
332 }
333
334
335 Assertions.assertNotEquals(null, route1a, "route equals null");
336 Assertions.assertNotEquals("route1a", route1a, "route equals string");
337 }
338
339 @Test
340 void testHopping() {
341
342 final HttpHost[] proxies = null;
343 final HttpRoute route = new HttpRoute(TARGET1, null, proxies, true,
344 TunnelType.PLAIN, LayerType.PLAIN);
345 Assertions.assertEquals(1, route.getHopCount(), "A: hop count");
346 Assertions.assertEquals(TARGET1, route.getHopTarget(0), "A: hop 0");
347 Assertions.assertThrows(IllegalArgumentException.class, () -> route.getHopTarget(1));
348 Assertions.assertThrows(IllegalArgumentException.class, () -> route.getHopTarget(-1));
349
350 final HttpHost[] proxies2 = new HttpHost[]{ PROXY3 };
351 final HttpRoute route2 = new HttpRoute(TARGET1, LOCAL62, proxies2, false,
352 TunnelType.TUNNELLED, LayerType.PLAIN);
353 Assertions.assertEquals(2, route2.getHopCount(), "B: hop count");
354 Assertions.assertEquals(PROXY3, route2.getHopTarget(0), "B: hop 0");
355 Assertions.assertEquals(TARGET1, route2.getHopTarget(1), "B: hop 1");
356 Assertions.assertThrows(IllegalArgumentException.class, () -> route2.getHopTarget(2));
357 Assertions.assertThrows(IllegalArgumentException.class, () -> route2.getHopTarget(-2));
358
359 final HttpHost[] proxies3 = new HttpHost[]{ PROXY3, PROXY1, PROXY2 };
360 final HttpRoute route3 = new HttpRoute(TARGET1, LOCAL42, proxies3, false,
361 TunnelType.PLAIN, LayerType.LAYERED);
362 Assertions.assertEquals(4, route3.getHopCount(), "C: hop count");
363 Assertions.assertEquals(PROXY3 , route3.getHopTarget(0), "C: hop 0");
364 Assertions.assertEquals(PROXY1 , route3.getHopTarget(1), "C: hop 1");
365 Assertions.assertEquals(PROXY2 , route3.getHopTarget(2), "C: hop 2");
366 Assertions.assertEquals(TARGET1, route3.getHopTarget(3), "C: hop 3");
367 Assertions.assertThrows(IllegalArgumentException.class, () -> route3.getHopTarget(4));
368 Assertions.assertThrows(IllegalArgumentException.class, () -> route3.getHopTarget(Integer.MIN_VALUE));
369 }
370
371 @Test
372 void testCstr1() {
373 final HttpRoute route = new HttpRoute(TARGET2);
374 final HttpRoute should = new HttpRoute
375 (TARGET2, null, (HttpHost[]) null, false,
376 TunnelType.PLAIN, LayerType.PLAIN);
377 Assertions.assertEquals(route, should, "bad convenience route");
378 }
379
380 @Test
381 void testCstr3() {
382
383 HttpRoute route = new HttpRoute(TARGET2, LOCAL61, false);
384 HttpRoute should = new HttpRoute
385 (TARGET2, LOCAL61, (HttpHost[]) null, false,
386 TunnelType.PLAIN, LayerType.PLAIN);
387 Assertions.assertEquals(route, should, "bad convenience route 3/insecure");
388
389 route = new HttpRoute(TARGET2, null, true);
390 should = new HttpRoute(TARGET2, null, (HttpHost[]) null, true,
391 TunnelType.PLAIN, LayerType.PLAIN);
392 Assertions.assertEquals(route, should, "bad convenience route 3/secure");
393 }
394
395 @SuppressWarnings("unused")
396 @Test
397 void testCstr4() {
398
399 HttpRoute route = new HttpRoute(TARGET2, null, PROXY2, false);
400 HttpRoute should = new HttpRoute
401 (TARGET2, null, new HttpHost[]{ PROXY2 }, false,
402 TunnelType.PLAIN, LayerType.PLAIN);
403 Assertions.assertEquals(route, should, "bad convenience route 4/insecure");
404
405 route = new HttpRoute(TARGET2, LOCAL42, PROXY1, true);
406 should = new HttpRoute
407 (TARGET2, LOCAL42, new HttpHost[]{ PROXY1 }, true,
408 TunnelType.TUNNELLED, LayerType.LAYERED);
409 Assertions.assertEquals(route, should, "bad convenience route 4/secure");
410
411
412 Assertions.assertThrows(NullPointerException.class, () ->
413 new HttpRoute(TARGET1, LOCAL61, null, false));
414 }
415
416 @Test
417 void testCstr6() {
418
419 HttpRoute route = new HttpRoute
420 (TARGET2, null, PROXY2, true,
421 TunnelType.TUNNELLED, LayerType.PLAIN);
422 HttpRoute should = new HttpRoute
423 (TARGET2, null, new HttpHost[]{ PROXY2 }, true,
424 TunnelType.TUNNELLED, LayerType.PLAIN);
425 Assertions.assertEquals(route, should, "bad convenience route 6/proxied");
426
427 route = new HttpRoute
428 (TARGET2, null, (HttpHost) null, true,
429 TunnelType.PLAIN, LayerType.LAYERED);
430 should = new HttpRoute
431 (TARGET2, null, (HttpHost[]) null, true,
432 TunnelType.PLAIN, LayerType.LAYERED);
433 Assertions.assertEquals(route, should, "bad convenience route 6/direct");
434
435
436 }
437
438 @Test
439 void testImmutable() throws CloneNotSupportedException {
440
441 final HttpHost[] proxies = new HttpHost[]{ PROXY1, PROXY2, PROXY3 };
442 final HttpRoute route1 = new HttpRoute(TARGET1, null, proxies, false,
443 TunnelType.PLAIN, LayerType.PLAIN);
444 final HttpRoute route2 = (HttpRoute) route1.clone();
445 final HttpRoute route3 = new HttpRoute(TARGET1, null,
446 proxies.clone(), false,
447 TunnelType.PLAIN, LayerType.PLAIN);
448
449
450 proxies[1] = PROXY3;
451 proxies[2] = PROXY2;
452
453 Assertions.assertEquals(route2, route1, "route differs from clone");
454 Assertions.assertEquals(route3, route1, "route was modified");
455 }
456
457 }