/*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.ogt.http.conn.routing;
import java.net.InetAddress;
import java.util.HashSet;
import java.util.Set;
import org.apache.ogt.http.HttpHost;
import org.apache.ogt.http.conn.routing.BasicRouteDirector;
import org.apache.ogt.http.conn.routing.HttpRoute;
import org.apache.ogt.http.conn.routing.HttpRouteDirector;
import org.apache.ogt.http.conn.routing.RouteTracker;
import org.apache.ogt.http.conn.routing.RouteInfo.LayerType;
import org.apache.ogt.http.conn.routing.RouteInfo.TunnelType;
import org.junit.Assert;
import org.junit.Test;
/**
* Tests for {@link RouteTracker}.
*/
public class TestRouteTracker {
// a selection of constants for generating routes
public final static
HttpHost TARGET1 = new HttpHost("target1.test.invalid");
public final static
HttpHost TARGET2 = new HttpHost("target2.test.invalid", 8080);
// It is not necessary to have extra targets for https.
// The 'layered' and 'secure' flags are specified explicitly
// for routes, they will not be determined from the scheme.
public final static
HttpHost PROXY1 = new HttpHost("proxy1.test.invalid");
public final static
HttpHost PROXY2 = new HttpHost("proxy2.test.invalid", 1080);
public final static
HttpHost PROXY3 = new HttpHost("proxy3.test.invalid", 88);
public final static InetAddress LOCAL41;
public final static InetAddress LOCAL42;
public final static InetAddress LOCAL61;
public final static InetAddress LOCAL62;
// need static initializer to deal with exceptions
static {
try {
LOCAL41 = InetAddress.getByAddress(new byte[]{ 127, 0, 0, 1 });
LOCAL42 = InetAddress.getByAddress(new byte[]{ 127, 0, 0, 2 });
LOCAL61 = InetAddress.getByAddress(new byte[]{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
});
LOCAL62 = InetAddress.getByAddress(new byte[]{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2
});
} catch (Exception x) {
throw new ExceptionInInitializerError(x);
}
}
@Test
public void testCstrTargetLocal() {
RouteTracker rt = new RouteTracker(TARGET1, null);
Assert.assertEquals("wrong target (target,null)",
TARGET1, rt.getTargetHost());
Assert.assertEquals("wrong local address (target,null)",
null, rt.getLocalAddress());
Assert.assertEquals("wrong hop count (target,null)",
0, rt.getHopCount());
Assert.assertEquals("wrong proxy (target,null)",
null, rt.getProxyHost());
Assert.assertEquals("wrong route (target,null)",
null, rt.toRoute());
checkCTLS(rt, false, false, false, false);
rt = new RouteTracker(TARGET2, LOCAL61);
Assert.assertEquals("wrong target (target,local)",
TARGET2, rt.getTargetHost());
Assert.assertEquals("wrong local address (target,local)",
LOCAL61, rt.getLocalAddress());
Assert.assertEquals("wrong hop count (target,local)",
0, rt.getHopCount());
Assert.assertEquals("wrong proxy (target,local)",
null, rt.getProxyHost());
Assert.assertEquals("wrong route (target,local)",
null, rt.toRoute());
checkCTLS(rt, false, false, false, false);
rt = null;
try {
new RouteTracker(null, LOCAL41);
Assert.fail("null target not detected");
} catch (IllegalArgumentException iax) {
// expected
}
}
@Test
public void testCstrRoute() {
HttpRoute r = new HttpRoute(TARGET1);
RouteTracker rt = new RouteTracker(r);
Assert.assertEquals("wrong target (r1)",
TARGET1, rt.getTargetHost());
Assert.assertEquals("wrong local address (r1)",
null, rt.getLocalAddress());
Assert.assertEquals("wrong hop count (r1)",
0, rt.getHopCount());
Assert.assertEquals("wrong proxy (r1)",
null, rt.getProxyHost());
Assert.assertEquals("wrong route (r1)",
null, rt.toRoute());
checkCTLS(rt, false, false, false, false);
r = new HttpRoute(TARGET2, LOCAL61, true);
rt = new RouteTracker(r);
Assert.assertEquals("wrong target (r2)",
TARGET2, rt.getTargetHost());
Assert.assertEquals("wrong local address (r2)",
LOCAL61, rt.getLocalAddress());
Assert.assertEquals("wrong hop count (r2)",
0, rt.getHopCount());
Assert.assertEquals("wrong proxy (r2)",
null, rt.getProxyHost());
Assert.assertEquals("wrong route (r2)",
null, rt.toRoute());
checkCTLS(rt, false, false, false, false);
r = new HttpRoute(TARGET1, LOCAL42, PROXY3, true);
rt = new RouteTracker(r);
Assert.assertEquals("wrong target (r3)",
TARGET1, rt.getTargetHost());
Assert.assertEquals("wrong local address (r3)",
LOCAL42, rt.getLocalAddress());
Assert.assertEquals("wrong hop count (r3)",
0, rt.getHopCount());
Assert.assertEquals("wrong proxy (r3)",
null, rt.getProxyHost());
Assert.assertEquals("wrong route (r3)",
null, rt.toRoute());
checkCTLS(rt, false, false, false, false);
rt = null;
try {
new RouteTracker(null);
Assert.fail("null route not detected");
} catch (NullPointerException npx) {
// expected
}
}
@Test
public void testIllegalArgs() {
RouteTracker rt = new RouteTracker(TARGET2, null);
try {
rt.connectProxy(null, true);
Assert.fail("missing proxy argument not detected (connect/false)");
} catch (IllegalArgumentException iax) {
// expected
}
try {
rt.connectProxy(null, false);
Assert.fail("missing proxy argument not detected (connect/true)");
} catch (IllegalArgumentException iax) {
// expected
}
rt.connectProxy(PROXY1, false);
try {
rt.tunnelProxy(null, false);
Assert.fail("missing proxy argument not detected (tunnel/false)");
} catch (IllegalArgumentException iax) {
// expected
}
try {
rt.tunnelProxy(null, true);
Assert.fail("missing proxy argument not detected (tunnel/true)");
} catch (IllegalArgumentException iax) {
// expected
}
try {
rt.getHopTarget(-1);
Assert.fail("negative hop index not detected");
} catch (IllegalArgumentException iax) {
// expected
}
try {
rt.getHopTarget(2);
Assert.fail("excessive hop index not detected");
} catch (IllegalArgumentException iax) {
// expected
}
}
@Test
public void testIllegalStates() {
RouteTracker rt = new RouteTracker(TARGET1, null);
try {
rt.tunnelTarget(false);
Assert.fail("unconnectedness not detected (tunnelTarget)");
} catch (IllegalStateException isx) {
// expected
}
try {
rt.tunnelProxy(PROXY1, false);
Assert.fail("unconnectedness not detected (tunnelProxy)");
} catch (IllegalStateException isx) {
// expected
}
try {
rt.layerProtocol(true);
Assert.fail("unconnectedness not detected (layerProtocol)");
} catch (IllegalStateException isx) {
// expected
}
// connect directly
rt.connectTarget(false);
try {
rt.connectTarget(false);
Assert.fail("connectedness not detected (connectTarget)");
} catch (IllegalStateException isx) {
// expected
}
try {
rt.connectProxy(PROXY2, false);
Assert.fail("connectedness not detected (connectProxy)");
} catch (IllegalStateException isx) {
// expected
}
try {
rt.tunnelTarget(false);
Assert.fail("unproxiedness not detected (tunnelTarget)");
} catch (IllegalStateException isx) {
// expected
}
try {
rt.tunnelProxy(PROXY1, false);
Assert.fail("unproxiedness not detected (tunnelProxy)");
} catch (IllegalStateException isx) {
// expected
}
}
@Test
public void testDirectRoutes() {
final HttpRouteDirector rd = new BasicRouteDirector();
HttpRoute r = new HttpRoute(TARGET1, LOCAL41, false);
RouteTracker rt = new RouteTracker(r);
boolean complete = checkVia(rt, r, rd, 2);
Assert.assertTrue("incomplete route 1", complete);
r = new HttpRoute(TARGET2, LOCAL62, true);
rt = new RouteTracker(r);
complete = checkVia(rt, r, rd, 2);
Assert.assertTrue("incomplete route 2", complete);
}
@Test
public void testProxyRoutes() {
final HttpRouteDirector rd = new BasicRouteDirector();
HttpRoute r = new HttpRoute(TARGET2, null, PROXY1, false);
RouteTracker rt = new RouteTracker(r);
boolean complete = checkVia(rt, r, rd, 2);
Assert.assertTrue("incomplete route 1", complete);
// tunnelled, but neither secure nor layered
r = new HttpRoute(TARGET1, LOCAL61, PROXY3, false,
TunnelType.TUNNELLED, LayerType.PLAIN);
rt = new RouteTracker(r);
complete = checkVia(rt, r, rd, 3);
Assert.assertTrue("incomplete route 2", complete);
// tunnelled, layered, but not secure
r = new HttpRoute(TARGET1, LOCAL61, PROXY3, false,
TunnelType.TUNNELLED, LayerType.LAYERED);
rt = new RouteTracker(r);
complete = checkVia(rt, r, rd, 4);
Assert.assertTrue("incomplete route 3", complete);
// tunnelled, layered, secure
r = new HttpRoute(TARGET1, LOCAL61, PROXY3, true);
rt = new RouteTracker(r);
complete = checkVia(rt, r, rd, 4);
Assert.assertTrue("incomplete route 4", complete);
}
@Test
public void testProxyChainRoutes() {
final HttpRouteDirector rd = new BasicRouteDirector();
HttpHost[] proxies = { PROXY1, PROXY2 };
HttpRoute r = new HttpRoute(TARGET2, LOCAL42, proxies, false,
TunnelType.PLAIN, LayerType.PLAIN);
RouteTracker rt = new RouteTracker(r);
boolean complete = checkVia(rt, r, rd, 3);
Assert.assertTrue("incomplete route 1", complete);
// tunnelled, but neither secure nor layered
proxies = new HttpHost[]{ PROXY3, PROXY2 };
r = new HttpRoute(TARGET1, null, proxies, false,
TunnelType.TUNNELLED, LayerType.PLAIN);
rt = new RouteTracker(r);
complete = checkVia(rt, r, rd, 4);
Assert.assertTrue("incomplete route 2", complete);
// tunnelled, layered, but not secure
proxies = new HttpHost[]{ PROXY3, PROXY2, PROXY1 };
r = new HttpRoute(TARGET2, LOCAL61, proxies, false,
TunnelType.TUNNELLED, LayerType.LAYERED);
rt = new RouteTracker(r);
complete = checkVia(rt, r, rd, 6);
Assert.assertTrue("incomplete route 3", complete);
// tunnelled, layered, secure
proxies = new HttpHost[]{ PROXY1, PROXY3 };
r = new HttpRoute(TARGET1, LOCAL61, proxies, true,
TunnelType.TUNNELLED, LayerType.LAYERED);
rt = new RouteTracker(r);
complete = checkVia(rt, r, rd, 5);
Assert.assertTrue("incomplete route 4", complete);
}
@Test
public void testEqualsHashcodeCloneToString()
throws CloneNotSupportedException {
RouteTracker rt0 = new RouteTracker(TARGET1, null);
RouteTracker rt1 = new RouteTracker(TARGET2, null);
RouteTracker rt2 = new RouteTracker(TARGET1, null);
RouteTracker rt3 = new RouteTracker(TARGET1, null);
RouteTracker rt4 = new RouteTracker(TARGET1, LOCAL41);
RouteTracker rt6 = new RouteTracker(TARGET1, LOCAL62);
Assert.assertFalse("rt0", rt0.equals(null));
Assert.assertTrue("rt0", rt0.equals(rt0));
Assert.assertFalse("rt0", rt0.equals(rt0.toString()));
Assert.assertFalse("rt0 == rt4", rt0.equals(rt4));
Assert.assertFalse("rt0 == rt1", rt0.equals(rt1)); // Check host takes part in equals
// Check that connection takes part in equals
Assert.assertTrue("rt0 != rt2", rt0.equals(rt2));
rt2.connectTarget(false);
Assert.assertFalse("rt0 == rt2", rt0.equals(rt2));
Assert.assertTrue("rt0 != rt3", rt0.equals(rt3));
rt3.connectTarget(true);
Assert.assertFalse("rt0 == rt3", rt0.equals(rt3));
Assert.assertFalse("rt2 == rt3", rt2.equals(rt3)); // Test secure takes part
// TODO needs tests for tunnel and layered
Assert.assertFalse("rt4 == rt0", rt4.equals(rt0));
Assert.assertFalse("rt0 == rt6", rt0.equals(rt6));
Assert.assertFalse("rt6 == rt0", rt6.equals(rt0));
Assert.assertFalse("rt4 == rt6", rt4.equals(rt6));
Assert.assertFalse("rt6 == rt4", rt6.equals(rt4));
// it is likely but not guaranteed that the hashcodes are different
Assert.assertFalse("rt0 == rt4 (hashcode)", rt0.hashCode() == rt4.hashCode());
Assert.assertFalse("rt0 == rt6 (hashcode)", rt0.hashCode() == rt6.hashCode());
Assert.assertFalse("rt6 == rt4 (hashcode)", rt6.hashCode() == rt4.hashCode());
Assert.assertEquals("rt0 (clone)", rt0, rt0.clone());
Assert.assertEquals("rt4 (clone)", rt4, rt4.clone());
Assert.assertEquals("rt6 (clone)", rt6, rt6.clone());
// we collect (clones of) the different tracked routes along the way
// rt0 -> direct connection
// rt1 -> via single proxy
// rt2 -> via proxy chain
Set<RouteTracker> hs = new HashSet<RouteTracker>();
// we also collect hashcodes for the different paths
// since we can't guarantee what influence the HttpHost hashcodes have,
// we keep separate sets here
Set<Integer> hc0 = new HashSet<Integer>();
Set<Integer> hc4 = new HashSet<Integer>();
Set<Integer> hc6 = new HashSet<Integer>();
RouteTracker rt = null;
Assert.assertTrue(hs.add(rt0));
Assert.assertTrue(hs.add(rt4));
Assert.assertTrue(hs.add(rt6));
Assert.assertTrue(hc0.add(Integer.valueOf(rt0.hashCode())));
Assert.assertTrue(hc4.add(Integer.valueOf(rt4.hashCode())));
Assert.assertTrue(hc6.add(Integer.valueOf(rt6.hashCode())));
rt = (RouteTracker) rt0.clone();
rt.connectTarget(false);
Assert.assertTrue(hs.add(rt));
Assert.assertTrue(hc0.add(Integer.valueOf(rt.hashCode())));
rt = (RouteTracker) rt0.clone();
rt.connectTarget(true);
Assert.assertTrue(hs.add(rt));
Assert.assertTrue(hc0.add(Integer.valueOf(rt.hashCode())));
// proxy (insecure) -> tunnel (insecure) -> layer (secure)
rt = (RouteTracker) rt4.clone();
rt.connectProxy(PROXY1, false);
Assert.assertTrue(hs.add((RouteTracker) rt.clone()));
// this is not guaranteed to be unique...
Assert.assertTrue(hc4.add(Integer.valueOf(rt.hashCode())));
rt.tunnelTarget(false);
Assert.assertTrue(hs.add((RouteTracker) rt.clone()));
Assert.assertTrue(hc4.add(Integer.valueOf(rt.hashCode())));
rt.layerProtocol(true);
Assert.assertTrue(hs.add((RouteTracker) rt.clone()));
Assert.assertTrue(hc4.add(Integer.valueOf(rt.hashCode())));
// proxy (secure) -> tunnel (secure) -> layer (insecure)
rt = (RouteTracker) rt4.clone();
rt.connectProxy(PROXY1, true);
Assert.assertTrue(hs.add((RouteTracker) rt.clone()));
// this is not guaranteed to be unique...
Assert.assertTrue(hc4.add(Integer.valueOf(rt.hashCode())));
rt.tunnelTarget(true);
Assert.assertTrue(hs.add((RouteTracker) rt.clone()));
Assert.assertTrue(hc4.add(Integer.valueOf(rt.hashCode())));
rt.layerProtocol(false);
Assert.assertTrue(hs.add((RouteTracker) rt.clone()));
Assert.assertTrue(hc4.add(Integer.valueOf(rt.hashCode())));
// PROXY1/i -> PROXY2/i -> tunnel/i -> layer/s
rt = (RouteTracker) rt6.clone();
rt.connectProxy(PROXY1, false);
Assert.assertTrue(hs.add((RouteTracker) rt.clone()));
// this is not guaranteed to be unique...
Assert.assertTrue(hc6.add(Integer.valueOf(rt.hashCode())));
rt.tunnelProxy(PROXY2, false);
Assert.assertTrue(hs.add((RouteTracker) rt.clone()));
// this is not guaranteed to be unique...
Assert.assertTrue(hc6.add(Integer.valueOf(rt.hashCode())));
rt.tunnelTarget(false);
Assert.assertTrue(hs.add((RouteTracker) rt.clone()));
Assert.assertTrue(hc6.add(Integer.valueOf(rt.hashCode())));
rt.layerProtocol(true);
Assert.assertTrue(hs.add((RouteTracker) rt.clone()));
Assert.assertTrue(hc6.add(Integer.valueOf(rt.hashCode())));
// PROXY1/s -> PROXY2/s -> tunnel/s -> layer/i
rt = (RouteTracker) rt6.clone();
rt.connectProxy(PROXY1, true);
Assert.assertTrue(hs.add((RouteTracker) rt.clone()));
// this is not guaranteed to be unique...
Assert.assertTrue(hc6.add(Integer.valueOf(rt.hashCode())));
rt.tunnelProxy(PROXY2, true);
Assert.assertTrue(hs.add((RouteTracker) rt.clone()));
// this is not guaranteed to be unique...
Assert.assertTrue(hc6.add(Integer.valueOf(rt.hashCode())));
rt.tunnelTarget(true);
Assert.assertTrue(hs.add((RouteTracker) rt.clone()));
Assert.assertTrue(hc6.add(Integer.valueOf(rt.hashCode())));
rt.layerProtocol(false);
Assert.assertTrue(hs.add((RouteTracker) rt.clone()));
Assert.assertTrue(hc6.add(Integer.valueOf(rt.hashCode())));
// PROXY2/i -> PROXY1/i -> tunnel/i -> layer/s
rt = (RouteTracker) rt6.clone();
rt.connectProxy(PROXY2, false);
Assert.assertTrue(hs.add((RouteTracker) rt.clone()));
// this is not guaranteed to be unique...
Assert.assertTrue(hc6.add(Integer.valueOf(rt.hashCode())));
rt.tunnelProxy(PROXY1, false);
Assert.assertTrue(hs.add((RouteTracker) rt.clone()));
// proxy chain sequence does not affect hashcode, so duplicate:
// Assert.assertTrue(hc6.add(Integer.valueOf(rt.hashCode())));
rt.tunnelTarget(false);
Assert.assertTrue(hs.add((RouteTracker) rt.clone()));
// proxy chain sequence does not affect hashcode, so duplicate:
// Assert.assertTrue(hc6.add(Integer.valueOf(rt.hashCode())));
rt.layerProtocol(true);
Assert.assertTrue(hs.add((RouteTracker) rt.clone()));
// proxy chain sequence does not affect hashcode, so duplicate:
// Assert.assertTrue(hc6.add(Integer.valueOf(rt.hashCode())));
// check that all toString are OK and different
Set<String> rtstrings = new HashSet<String>();
for (RouteTracker current: hs) {
final String rts = checkToString(current);
Assert.assertTrue("duplicate toString: " + rts, rtstrings.add(rts));
}
}
/** Helper to check the status of the four flags. */
public final static void checkCTLS(RouteTracker rt,
boolean c, boolean t,
boolean l, boolean s) {
String rts = rt.toString();
Assert.assertEquals("wrong flag connected: " + rts, c, rt.isConnected());
Assert.assertEquals("wrong flag tunnelled: " + rts, t, rt.isTunnelled());
Assert.assertEquals("wrong enum tunnelled: " + rts,
t ? TunnelType.TUNNELLED : TunnelType.PLAIN,
rt.getTunnelType());
Assert.assertEquals("wrong flag layered: " + rts, l, rt.isLayered());
Assert.assertEquals("wrong enum layered: " + rts,
l ? LayerType.LAYERED : LayerType.PLAIN,
rt.getLayerType());
Assert.assertEquals("wrong flag secure: " + rts, s, rt.isSecure());
}
/**
* Helper to check tracking of a route.
* This uses a {@link HttpRouteDirector} to fake establishing the route,
* checking the intermediate steps.
*
* @param rt the tracker to check with
* @param r the route to establish
* @param rd the director to check with
* @param steps the step count for this invocation
*
* @return <code>true</code> iff the route is complete
*/
public final static boolean checkVia(RouteTracker rt, HttpRoute r,
HttpRouteDirector rd, int steps) {
final String msg = r.toString() + " @ " + rt.toString();
boolean complete = false;
while (!complete && (steps > 0)) {
int action = rd.nextStep(r, rt.toRoute());
switch (action) {
case HttpRouteDirector.COMPLETE:
complete = true;
Assert.assertEquals(r, rt.toRoute());
break;
case HttpRouteDirector.CONNECT_TARGET: {
final boolean sec = r.isSecure();
rt.connectTarget(sec);
checkCTLS(rt, true, false, false, sec);
Assert.assertEquals("wrong hop count "+msg,
1, rt.getHopCount());
Assert.assertEquals("wrong hop0 "+msg,
r.getTargetHost(), rt.getHopTarget(0));
} break;
case HttpRouteDirector.CONNECT_PROXY: {
// we assume an insecure proxy connection
final boolean sec = false;
rt.connectProxy(r.getProxyHost(), sec);
checkCTLS(rt, true, false, false, sec);
Assert.assertEquals("wrong hop count "+msg,
2, rt.getHopCount());
Assert.assertEquals("wrong hop0 "+msg,
r.getProxyHost(), rt.getHopTarget(0));
Assert.assertEquals("wrong hop1 "+msg,
r.getTargetHost(), rt.getHopTarget(1));
} break;
case HttpRouteDirector.TUNNEL_TARGET: {
final int hops = rt.getHopCount();
// we assume an insecure tunnel
final boolean sec = false;
rt.tunnelTarget(sec);
checkCTLS(rt, true, true, false, sec);
Assert.assertEquals("wrong hop count "+msg,
hops, rt.getHopCount());
Assert.assertEquals("wrong hop0 "+msg,
r.getProxyHost(), rt.getHopTarget(0));
Assert.assertEquals("wrong hopN "+msg,
r.getTargetHost(), rt.getHopTarget(hops-1));
} break;
case HttpRouteDirector.TUNNEL_PROXY: {
final int hops = rt.getHopCount(); // before tunnelling
// we assume an insecure tunnel
final boolean sec = false;
final HttpHost pxy = r.getHopTarget(hops-1);
rt.tunnelProxy(pxy, sec);
// Since we're tunnelling to a proxy and not the target,
// the 'tunelling' flag is false: no end-to-end tunnel.
checkCTLS(rt, true, false, false, sec);
Assert.assertEquals("wrong hop count "+msg,
hops+1, rt.getHopCount());
Assert.assertEquals("wrong hop0 "+msg,
r.getProxyHost(), rt.getHopTarget(0));
Assert.assertEquals("wrong hop"+hops+" "+msg,
pxy, rt.getHopTarget(hops-1));
Assert.assertEquals("wrong hopN "+msg,
r.getTargetHost(), rt.getHopTarget(hops));
} break;
case HttpRouteDirector.LAYER_PROTOCOL: {
final int hops = rt.getHopCount();
final boolean tun = rt.isTunnelled();
final boolean sec = r.isSecure();
rt.layerProtocol(sec);
checkCTLS(rt, true, tun, true, sec);
Assert.assertEquals("wrong hop count "+msg,
hops, rt.getHopCount());
Assert.assertEquals("wrong proxy "+msg,
r.getProxyHost(), rt.getProxyHost());
Assert.assertEquals("wrong target "+msg,
r.getTargetHost(), rt.getTargetHost());
} break;
// UNREACHABLE
default:
Assert.fail("unexpected action " + action + " from director, "+msg);
break;
} // switch
steps--;
}
return complete;
} // checkVia
/**
* Checks the output of <code>toString</code>.
*
* @param rt the tracker for which to check the output
*
* @return the result of <code>rt.toString()</code>
*/
public final static String checkToString(RouteTracker rt) {
if (rt == null)
return null;
final String rts = rt.toString();
if (rt.getLocalAddress() != null) {
final String las = rt.getLocalAddress().toString();
Assert.assertFalse("no local address in toString(): " + rts,
rts.indexOf(las) < 0);
}
for (int i=0; i<rt.getHopCount(); i++) {
final String hts = rt.getHopTarget(i).toString();
Assert.assertFalse("hop "+i+" ("+hts+") missing in toString(): " + rts,
rts.indexOf(hts) < 0);
}
return rts;
}
}