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.routing;
29
30 import java.net.InetAddress;
31 import java.util.HashSet;
32 import java.util.Set;
33
34 import org.apache.hc.client5.http.HttpRoute;
35 import org.apache.hc.client5.http.RouteInfo.LayerType;
36 import org.apache.hc.client5.http.RouteInfo.TunnelType;
37 import org.apache.hc.core5.http.HttpHost;
38 import org.junit.jupiter.api.Assertions;
39 import org.junit.jupiter.api.Test;
40
41
42
43
44 public 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 public 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 public 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 final Set<HttpRoute> routes = new HashSet<>();
177 routes.add(routefff);
178 routes.add(routefft);
179 routes.add(routeftf);
180 routes.add(routeftt);
181 routes.add(routetff);
182 routes.add(routetft);
183 routes.add(routettf);
184 routes.add(routettt);
185 Assertions.assertEquals(8, routes.size(), "some flagged routes are equal");
186
187
188
189 final Set<Integer> routecodes = new HashSet<>();
190 routecodes.add(routefff.hashCode());
191 routecodes.add(routefft.hashCode());
192 routecodes.add(routeftf.hashCode());
193 routecodes.add(routeftt.hashCode());
194 routecodes.add(routetff.hashCode());
195 routecodes.add(routetft.hashCode());
196 routecodes.add(routettf.hashCode());
197 routecodes.add(routettt.hashCode());
198 Assertions.assertEquals(8, routecodes.size(), "some flagged routes have same hashCode");
199
200 final Set<String> routestrings = new HashSet<>();
201 routestrings.add(routefff.toString());
202 routestrings.add(routefft.toString());
203 routestrings.add(routeftf.toString());
204 routestrings.add(routeftt.toString());
205 routestrings.add(routetff.toString());
206 routestrings.add(routetft.toString());
207 routestrings.add(routettf.toString());
208 routestrings.add(routettt.toString());
209 Assertions.assertEquals(8, routestrings.size(), "some flagged route.toString() are equal");
210 }
211
212 @SuppressWarnings("unused")
213 @Test
214 public void testInvalidArguments() {
215 final HttpHost[] chain1 = { PROXY1 };
216
217
218 final HttpRoute route = new HttpRoute(TARGET1, null, chain1, false,
219 TunnelType.TUNNELLED, LayerType.PLAIN);
220 Assertions.assertNotNull(route);
221
222 Assertions.assertThrows(NullPointerException.class, () ->
223 new HttpRoute(null, null, chain1, false,TunnelType.TUNNELLED, LayerType.PLAIN));
224 Assertions.assertThrows(IllegalArgumentException.class, () ->
225 new HttpRoute(TARGET1, null, (HttpHost[]) null, false, TunnelType.TUNNELLED, LayerType.PLAIN));
226 }
227
228 @Test
229 public void testNullEnums() {
230
231
232
233
234 final HttpRoute route = new HttpRoute(TARGET1, null, PROXY1, false,
235 null, null);
236
237 Assertions.assertFalse(route.isTunnelled(), "default tunnelling");
238 Assertions.assertEquals(TunnelType.PLAIN, route.getTunnelType(), "untunnelled");
239
240 Assertions.assertFalse(route.isLayered(), "default layering");
241 Assertions.assertEquals(LayerType.PLAIN, route.getLayerType(), "unlayered");
242 }
243
244 @Test
245 public void testEqualsHashcodeClone() throws CloneNotSupportedException {
246 final HttpHost[] chain0 = { };
247 final HttpHost[] chain1 = { PROXY1 };
248 final HttpHost[] chain3 = { PROXY1, PROXY2, PROXY3 };
249 final HttpHost[] chain4 = { PROXY1, PROXY3, PROXY2 };
250
251
252 final HttpRoute route1a = new HttpRoute(TARGET1, LOCAL41, chain3, false,
253 TunnelType.PLAIN, LayerType.PLAIN);
254 final HttpRoute route1b = new HttpRoute(TARGET1, LOCAL41, chain3, false,
255 TunnelType.PLAIN, LayerType.PLAIN);
256 final HttpRoute route1c = (HttpRoute) route1a.clone();
257
258 Assertions.assertEquals(route1a, route1a, "1a 1a");
259 Assertions.assertEquals(route1a, route1b, "1a 1b");
260 Assertions.assertEquals(route1a, route1c, "1a 1c");
261
262 Assertions.assertEquals(route1a.hashCode(), route1a.hashCode(), "hashcode 1a");
263 Assertions.assertEquals(route1a.hashCode(), route1b.hashCode(), "hashcode 1b");
264 Assertions.assertEquals(route1a.hashCode(), route1c.hashCode(), "hashcode 1c");
265
266 Assertions.assertEquals(route1a.toString(), route1b.toString(), "toString 1b");
267 Assertions.assertEquals(route1a.toString(), route1a.toString(), "toString 1a");
268 Assertions.assertEquals(route1a.toString(), route1c.toString(), "toString 1c");
269
270
271 final HttpRoute route2a = new HttpRoute(TARGET2, LOCAL41, chain3, false,
272 TunnelType.PLAIN, LayerType.PLAIN);
273 final HttpRoute route2b = new HttpRoute(TARGET1, LOCAL42, chain3, false,
274 TunnelType.PLAIN, LayerType.PLAIN);
275 final HttpRoute route2c = new HttpRoute(TARGET1, LOCAL61, chain3, false,
276 TunnelType.PLAIN, LayerType.PLAIN);
277 final HttpRoute route2d = new HttpRoute(TARGET1, null, chain3, false,
278 TunnelType.PLAIN, LayerType.PLAIN);
279 final HttpRoute route2e = new HttpRoute(TARGET1, LOCAL41, (HttpHost[]) null,
280 false,
281 TunnelType.PLAIN, LayerType.PLAIN);
282 final HttpRoute route2f = new HttpRoute(TARGET1, LOCAL41, chain0, false,
283 TunnelType.PLAIN, LayerType.PLAIN);
284 final HttpRoute route2g = new HttpRoute(TARGET1, LOCAL41, chain1, false,
285 TunnelType.PLAIN, LayerType.PLAIN);
286 final HttpRoute route2h = new HttpRoute(TARGET1, LOCAL41, chain4, false,
287 TunnelType.PLAIN, LayerType.PLAIN);
288 final HttpRoute route2i = new HttpRoute(TARGET1, LOCAL41, chain3, true,
289 TunnelType.PLAIN, LayerType.PLAIN);
290 final HttpRoute route2j = new HttpRoute(TARGET1, LOCAL41, chain3, false,
291 TunnelType.TUNNELLED, LayerType.PLAIN);
292 final HttpRoute route2k = new HttpRoute(TARGET1, LOCAL41, chain3, false,
293 TunnelType.PLAIN, LayerType.LAYERED);
294
295
296 Assertions.assertEquals(route2e, route2f, "2e 2f");
297 Assertions.assertEquals(route2e.hashCode(), route2f.hashCode(), "hashcode 2e 2f");
298 Assertions.assertEquals(route2e.toString(), route2f.toString(), "toString 2e 2f");
299
300 Assertions.assertNotEquals(route1a, route2a, "1a 2a");
301 Assertions.assertNotEquals(route1a, route2b, "1a 2b");
302 Assertions.assertNotEquals(route1a, route2c, "1a 2c");
303 Assertions.assertNotEquals(route1a, route2d, "1a 2d");
304 Assertions.assertNotEquals(route1a, route2e, "1a 2e");
305 Assertions.assertNotEquals(route1a, route2f, "1a 2f");
306 Assertions.assertNotEquals(route1a, route2g, "1a 2g");
307 Assertions.assertNotEquals(route1a, route2h, "1a 2h");
308 Assertions.assertNotEquals(route1a, route2i, "1a 2i");
309 Assertions.assertNotEquals(route1a, route2j, "1a 2j");
310 Assertions.assertNotEquals(route1a, route2k, "1a 2k");
311
312
313
314
315 Assertions.assertNotEquals(route2b, route1a, "2b 1a");
316 Assertions.assertNotEquals(route2c, route1a, "2c 1a");
317 Assertions.assertNotEquals(route2d, route1a, "2d 1a");
318 Assertions.assertNotEquals(route2e, route1a, "2e 1a");
319 Assertions.assertNotEquals(route2a, route1a, "2a 1a");
320 Assertions.assertNotEquals(route2f, route1a, "2f 1a");
321 Assertions.assertNotEquals(route2g, route1a, "2g 1a");
322 Assertions.assertNotEquals(route2h, route1a, "2h 1a");
323 Assertions.assertNotEquals(route2i, route1a, "2i 1a");
324 Assertions.assertNotEquals(route2j, route1a, "2j 1a");
325 Assertions.assertNotEquals(route2k, route1a, "2k 1a");
326
327
328
329 Assertions.assertNotEquals(route1a.toString(), route2a.toString(), "toString 1a 2a");
330 Assertions.assertNotEquals(route1a.toString(), route2b.toString(), "toString 1a 2b");
331 Assertions.assertNotEquals(route1a.toString(), route2c.toString(), "toString 1a 2c");
332 Assertions.assertNotEquals(route1a.toString(), route2d.toString(), "toString 1a 2d");
333 Assertions.assertNotEquals(route1a.toString(), route2e.toString(), "toString 1a 2e");
334 Assertions.assertNotEquals(route1a.toString(), route2f.toString(), "toString 1a 2f");
335 Assertions.assertNotEquals(route1a.toString(), route2g.toString(), "toString 1a 2g");
336 Assertions.assertNotEquals(route1a.toString(), route2h.toString(), "toString 1a 2h");
337 Assertions.assertNotEquals(route1a.toString(), route2i.toString(), "toString 1a 2i");
338 Assertions.assertNotEquals(route1a.toString(), route2j.toString(), "toString 1a 2j");
339 Assertions.assertNotEquals(route1a.toString(), route2k.toString(), "toString 1a 2k");
340
341
342
343 final Set<HttpRoute> routes = new HashSet<>();
344 routes.add(route1a);
345 routes.add(route2a);
346 routes.add(route2b);
347 routes.add(route2c);
348 routes.add(route2d);
349 routes.add(route2e);
350
351 routes.add(route2g);
352 routes.add(route2h);
353 routes.add(route2i);
354 routes.add(route2j);
355 routes.add(route2k);
356 Assertions.assertEquals(11, routes.size(), "some routes are equal");
357
358
359 for (final HttpRoute origin : routes) {
360 final HttpRoute cloned = (HttpRoute) origin.clone();
361 Assertions.assertEquals(origin, cloned, "clone of " + origin);
362 Assertions.assertTrue(routes.contains(cloned), "clone of " + origin);
363 }
364
365
366 final Set<String> routestrings = new HashSet<>();
367 routestrings.add(route1a.toString());
368 routestrings.add(route2a.toString());
369 routestrings.add(route2b.toString());
370 routestrings.add(route2c.toString());
371 routestrings.add(route2d.toString());
372 routestrings.add(route2e.toString());
373
374 routestrings.add(route2g.toString());
375 routestrings.add(route2h.toString());
376 routestrings.add(route2i.toString());
377 routestrings.add(route2j.toString());
378 routestrings.add(route2k.toString());
379 Assertions.assertEquals(11, routestrings.size(), "some route.toString() are equal");
380
381
382 Assertions.assertNotEquals(null, route1a, "route equals null");
383 Assertions.assertNotEquals("route1a", route1a, "route equals string");
384 }
385
386 @Test
387 public void testHopping() {
388
389 final HttpHost[] proxies = null;
390 final HttpRoute route = new HttpRoute(TARGET1, null, proxies, true,
391 TunnelType.PLAIN, LayerType.PLAIN);
392 Assertions.assertEquals(1, route.getHopCount(), "A: hop count");
393 Assertions.assertEquals(TARGET1, route.getHopTarget(0), "A: hop 0");
394 Assertions.assertThrows(IllegalArgumentException.class, () -> route.getHopTarget(1));
395 Assertions.assertThrows(IllegalArgumentException.class, () -> route.getHopTarget(-1));
396
397 final HttpHost[] proxies2 = new HttpHost[]{ PROXY3 };
398 final HttpRoute route2 = new HttpRoute(TARGET1, LOCAL62, proxies2, false,
399 TunnelType.TUNNELLED, LayerType.PLAIN);
400 Assertions.assertEquals(2, route2.getHopCount(), "B: hop count");
401 Assertions.assertEquals(PROXY3, route2.getHopTarget(0), "B: hop 0");
402 Assertions.assertEquals(TARGET1, route2.getHopTarget(1), "B: hop 1");
403 Assertions.assertThrows(IllegalArgumentException.class, () -> route2.getHopTarget(2));
404 Assertions.assertThrows(IllegalArgumentException.class, () -> route2.getHopTarget(-2));
405
406 final HttpHost[] proxies3 = new HttpHost[]{ PROXY3, PROXY1, PROXY2 };
407 final HttpRoute route3 = new HttpRoute(TARGET1, LOCAL42, proxies3, false,
408 TunnelType.PLAIN, LayerType.LAYERED);
409 Assertions.assertEquals(route3.getHopCount(), 4, "C: hop count");
410 Assertions.assertEquals(PROXY3 , route3.getHopTarget(0), "C: hop 0");
411 Assertions.assertEquals(PROXY1 , route3.getHopTarget(1), "C: hop 1");
412 Assertions.assertEquals(PROXY2 , route3.getHopTarget(2), "C: hop 2");
413 Assertions.assertEquals(TARGET1, route3.getHopTarget(3), "C: hop 3");
414 Assertions.assertThrows(IllegalArgumentException.class, () -> route3.getHopTarget(4));
415 Assertions.assertThrows(IllegalArgumentException.class, () -> route3.getHopTarget(Integer.MIN_VALUE));
416 }
417
418 @Test
419 public void testCstr1() {
420 final HttpRoute route = new HttpRoute(TARGET2);
421 final HttpRoute should = new HttpRoute
422 (TARGET2, null, (HttpHost[]) null, false,
423 TunnelType.PLAIN, LayerType.PLAIN);
424 Assertions.assertEquals(route, should, "bad convenience route");
425 }
426
427 @Test
428 public void testCstr3() {
429
430 HttpRoute route = new HttpRoute(TARGET2, LOCAL61, false);
431 HttpRoute should = new HttpRoute
432 (TARGET2, LOCAL61, (HttpHost[]) null, false,
433 TunnelType.PLAIN, LayerType.PLAIN);
434 Assertions.assertEquals(route, should, "bad convenience route 3/insecure");
435
436 route = new HttpRoute(TARGET2, null, true);
437 should = new HttpRoute(TARGET2, null, (HttpHost[]) null, true,
438 TunnelType.PLAIN, LayerType.PLAIN);
439 Assertions.assertEquals(route, should, "bad convenience route 3/secure");
440 }
441
442 @SuppressWarnings("unused")
443 @Test
444 public void testCstr4() {
445
446 HttpRoute route = new HttpRoute(TARGET2, null, PROXY2, false);
447 HttpRoute should = new HttpRoute
448 (TARGET2, null, new HttpHost[]{ PROXY2 }, false,
449 TunnelType.PLAIN, LayerType.PLAIN);
450 Assertions.assertEquals(route, should, "bad convenience route 4/insecure");
451
452 route = new HttpRoute(TARGET2, LOCAL42, PROXY1, true);
453 should = new HttpRoute
454 (TARGET2, LOCAL42, new HttpHost[]{ PROXY1 }, true,
455 TunnelType.TUNNELLED, LayerType.LAYERED);
456 Assertions.assertEquals(route, should, "bad convenience route 4/secure");
457
458
459 Assertions.assertThrows(NullPointerException.class, () ->
460 new HttpRoute(TARGET1, LOCAL61, null, false));
461 }
462
463 @Test
464 public void testCstr6() {
465
466 HttpRoute route = new HttpRoute
467 (TARGET2, null, PROXY2, true,
468 TunnelType.TUNNELLED, LayerType.PLAIN);
469 HttpRoute should = new HttpRoute
470 (TARGET2, null, new HttpHost[]{ PROXY2 }, true,
471 TunnelType.TUNNELLED, LayerType.PLAIN);
472 Assertions.assertEquals(route, should, "bad convenience route 6/proxied");
473
474 route = new HttpRoute
475 (TARGET2, null, (HttpHost) null, true,
476 TunnelType.PLAIN, LayerType.LAYERED);
477 should = new HttpRoute
478 (TARGET2, null, (HttpHost[]) null, true,
479 TunnelType.PLAIN, LayerType.LAYERED);
480 Assertions.assertEquals(route, should, "bad convenience route 6/direct");
481
482
483 }
484
485 @Test
486 public void testImmutable() throws CloneNotSupportedException {
487
488 final HttpHost[] proxies = new HttpHost[]{ PROXY1, PROXY2, PROXY3 };
489 final HttpRoute route1 = new HttpRoute(TARGET1, null, proxies, false,
490 TunnelType.PLAIN, LayerType.PLAIN);
491 final HttpRoute route2 = (HttpRoute) route1.clone();
492 final HttpRoute route3 = new HttpRoute(TARGET1, null,
493 proxies.clone(), false,
494 TunnelType.PLAIN, LayerType.PLAIN);
495
496
497 proxies[1] = PROXY3;
498 proxies[2] = PROXY2;
499
500 Assertions.assertEquals(route2, route1, "route differs from clone");
501 Assertions.assertEquals(route3, route1, "route was modified");
502 }
503
504 }