Skip to content

Commit

Permalink
Scenario builder for unit tests (#112)
Browse files Browse the repository at this point in the history
Co-authored-by: Tilmann Zäschke <tilmann.zaeschke@inf.ethz.ch>
  • Loading branch information
tzaeschke and Tilmann Zäschke authored Aug 12, 2024
1 parent 5cf921d commit 0908252
Show file tree
Hide file tree
Showing 24 changed files with 502 additions and 249 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Added
- Support for bootstrapper TRC metadata. [#110](https://github.com/scionproto-contrib/jpan/pull/110)
- Added `copy(...)` method for paths. [#111](https://github.com/scionproto-contrib/jpan/pull/111)
- Added Scenario builder for unit tests. [#112](https://github.com/scionproto-contrib/jpan/pull/112)

### Changed
- Clean up TODO and deprecation info. [#100](https://github.com/scionproto-contrib/jpan/pull/100)
Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -330,12 +330,12 @@ attempt to get network information in the following order until it succeeds:
The reason that the daemon is checked last is that it has a default setting (`localhost:30255`)
while the other options are skipped if no property or environment variable is defined.

| Option | Java property | Environment variable | Default value |
|-------------------------------------|----------------------------------|-------------------------------|-----------------|
| Daemon port | `org.scion.daemon.port` | `SCION_DAEMON` | localhost:30255 |
| Bootstrap topology file path | `org.scion.bootstrap.topoFile` | `SCION_BOOTSTRAP_TOPO_FILE` | |
| Bootstrap server host | `org.scion.bootstrap.host` | `SCION_BOOTSTRAP_HOST` | |
| Bootstrap DNS NAPTR entry host name | `org.scion.bootstrap.naptr.name` | `SCION_BOOTSTRAP_NAPTR_NAME` | |
| Option | Java property | Environment variable | Default value |
|-------------------------------------|-------------------------------------|-------------------------------|-----------------|
| Daemon port | `org.scion.daemon.port` | `SCION_DAEMON` | localhost:30255 |
| Bootstrap topology file path | `org.scion.bootstrap.topoFile` | `SCION_BOOTSTRAP_TOPO_FILE` | |
| Bootstrap server host | `org.scion.bootstrap.host` | `SCION_BOOTSTRAP_HOST` | |
| Bootstrap DNS NAPTR entry host name | `org.scion.bootstrap.naptr.name` | `SCION_BOOTSTRAP_NAPTR_NAME` | |
| Bootstrap DNS NAPTR entry host name | `org.scion.test.useOsSearchDomains` | `SCION_USE_OS_SEARCH_DOMAINS` | true |

### DNS
Expand Down
9 changes: 6 additions & 3 deletions src/main/java/org/scion/jpan/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,19 @@ public final class Constants {

/** Address of bootstrap server (http), e.g. 192.168.42.42 */
public static final String PROPERTY_BOOTSTRAP_HOST = "org.scion.bootstrap.host";

/** Address of bootstrap server (http), e.g. 192.168.42.42 */
public static final String ENV_BOOTSTRAP_HOST = "SCION_BOOTSTRAP_HOST";

/** Host name of DNS entry with NAPTR record for bootstrap service. */
public static final String PROPERTY_BOOTSTRAP_NAPTR_NAME = "org.scion.bootstrap.naptr.name";

/** Host name of DNS entry with NAPTR record for bootstrap service. */
public static final String ENV_BOOTSTRAP_NAPTR_NAME = "SCION_BOOTSTRAP_NAPTR_NAME";

/** path/file name for topology file. */
public static final String PROPERTY_BOOTSTRAP_TOPO_FILE = "org.scion.bootstrap.topoFile";

/** path/file name for topology file. */
public static final String ENV_BOOTSTRAP_TOPO_FILE = "SCION_BOOTSTRAP_TOPO_FILE";

Expand All @@ -62,12 +65,12 @@ public final class Constants {
public static final int DEFAULT_PATH_EXPIRY_MARGIN = 10;

/**
* Disable usage of OS search domains for DNS lookup, e.g from /etc/resolv.conf. This needs to be
* Disable usage of OS search domains for DNS lookup, e.g. from /etc/resolv.conf. This needs to be
* disabled for JUnit testing.
*/
public static final String PROPERTY_USE_OS_SEARCH_DOMAINS = "SCION_USE_OS_SEARCH_DOMAINS";
public static final String PROPERTY_USE_OS_SEARCH_DOMAINS = "org.scion.test.useOsSearchDomains";

public static final String ENV_USE_OS_SEARCH_DOMAINS = "org.scion.test.useOsSearchDomains";
public static final String ENV_USE_OS_SEARCH_DOMAINS = "SCION_USE_OS_SEARCH_DOMAINS";
public static final boolean DEFAULT_USE_OS_SEARCH_DOMAINS = true;

/**
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/scion/jpan/ScionService.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ protected ScionService(String addressOrHost, Mode mode) {
}
String csHost = bootstrapper.getLocalTopology().getControlServerAddress();
LOG.info("Bootstrapping with control service: {}", csHost);
localIsdAs.set(bootstrapper.getLocalTopology().getLocalIsdAs());
localIsdAs.set(bootstrapper.getLocalTopology().getIsdAs());
// TODO InsecureChannelCredentials: Implement authentication!
channel = Grpc.newChannelBuilder(csHost, InsecureChannelCredentials.create()).build();
daemonStub = null;
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/org/scion/jpan/ScionUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -203,5 +203,13 @@ static InetSocketAddress parseInetSocketAddress(String addrStr) {
}
}

public static boolean isWildcard(long isdAs) {
return isdAs == toWildcard(isdAs);
}

public static long toWildcard(long isdAs) {
return (isdAs >>> 48) << 48;
}

private ScionUtil() {}
}
66 changes: 56 additions & 10 deletions src/main/java/org/scion/jpan/internal/LocalTopology.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.scion.jpan.ScionRuntimeException;
Expand Down Expand Up @@ -51,11 +52,11 @@ public String getControlServerAddress() {
return controlServices.get(0).ipString;
}

public boolean isLocalAsCore() {
public boolean isCoreAs() {
return isCoreAs;
}

public long getLocalIsdAs() {
public long getIsdAs() {
return ScionUtil.parseIA(localIsdAs);
}

Expand All @@ -78,7 +79,7 @@ public List<String> getBorderRouterAddresses() {
return result;
}

public int getLocalMtu() {
public int getMtu() {
return this.localMtu;
}

Expand All @@ -101,9 +102,12 @@ private void parseTopologyFile(String topologyFile) {
JsonElement local =
underlay.has(("local")) ? underlay.get(("local")) : underlay.get(("public"));
JsonElement remote = underlay.get(("remote"));
long isdAs = ScionUtil.parseIA(ife.get("isd_as").getAsString());
int mtu = ife.get("mtu").getAsInt();
String linkTo = ife.get("link_to").getAsString();
interfaces.add(
new BorderRouterInterface(
ifEntry.getKey(), local.getAsString(), remote.getAsString()));
ifEntry.getKey(), local.getAsString(), remote.getAsString(), isdAs, mtu, linkTo));
}
borderRouters.add(new BorderRouter(e.getKey(), addr, interfaces));
}
Expand Down Expand Up @@ -142,34 +146,76 @@ public String toString() {
}

public List<ServiceNode> getControlServices() {
return controlServices;
return Collections.unmodifiableList(controlServices);
}

private static class BorderRouter {
public List<BorderRouter> getBorderRouters() {
return Collections.unmodifiableList(borderRouters);
}

public static class BorderRouter {
private final String name;
private final String internalAddress;
private final List<BorderRouterInterface> interfaces;

public BorderRouter(String name, String addr, List<BorderRouterInterface> interfaces) {
BorderRouter(String name, String addr, List<BorderRouterInterface> interfaces) {
this.name = name;
this.internalAddress = addr;
this.interfaces = interfaces;
}

public Iterable<BorderRouterInterface> getInterfaces() {
return interfaces;
}
}

private static class BorderRouterInterface {
public static class BorderRouterInterface {
public static final String PARENT = "parent";
public static final String CHILD = "child";
public static final String CORE = "core";
final int id;
final String publicUnderlay;
final String remoteUnderlay;
final long isdAs;
final int mtu;
final String linkTo;

public BorderRouterInterface(String id, String publicU, String remoteU) {
BorderRouterInterface(
String id, String publicU, String remoteU, long isdAs, int mtu, String linkTo) {
this.id = Integer.parseInt(id);
this.publicUnderlay = publicU;
this.remoteUnderlay = remoteU;
this.isdAs = isdAs;
this.mtu = mtu;
this.linkTo = linkTo;
}

public long getIsdAs() {
return isdAs;
}

public int getMtu() {
return mtu;
}

public int getId() {
return id;
}

public String getLinkTo() {
return linkTo;
}

public String getRemoteUnderlay() {
return remoteUnderlay;
}

public String getPublicUnderlay() {
return publicUnderlay;
}
}

static class ServiceNode {
public static class ServiceNode {
final String name;
final String ipString;

Expand Down
8 changes: 8 additions & 0 deletions src/main/java/org/scion/jpan/internal/MultiMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,12 @@ public boolean isEmpty() {
public void clear() {
map.clear();
}

public List<V> values() {
ArrayList<V> values = new ArrayList<>(map.size());
for (Map.Entry<K, ArrayList<V>> e : map.entrySet()) {
values.addAll(e.getValue());
}
return values;
}
}
20 changes: 7 additions & 13 deletions src/main/java/org/scion/jpan/internal/ScionBootstrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,21 @@
public class ScionBootstrapper {

private static final Logger LOG = LoggerFactory.getLogger(ScionBootstrapper.class.getName());
private static final String BASE_URL = "";
private static final String TOPOLOGY_ENDPOINT = "topology";
private static final Duration httpRequestTimeout = Duration.of(2, ChronoUnit.SECONDS);
private final String topologyResource;
private final LocalTopology topology;
private final LocalTopology localAS;
private final GlobalTopology world;

protected ScionBootstrapper(String topologyServiceAddress) {
this.topologyResource = topologyServiceAddress;
this.topology = initLocal();
this.localAS = initLocal();
this.world = initGlobal();
}

protected ScionBootstrapper(java.nio.file.Path file) {
this.topologyResource = file.toString();
this.topology = this.init(file);
this.localAS = this.init(file);
this.world = GlobalTopology.createEmpty();
}

Expand All @@ -75,7 +74,7 @@ public static synchronized ScionBootstrapper createViaTopoFile(java.nio.file.Pat
}

public LocalTopology getLocalTopology() {
return topology;
return localAS;
}

public GlobalTopology getGlobalTopology() {
Expand All @@ -95,12 +94,7 @@ private static String bootstrapViaDNS(String hostName) {
}

private LocalTopology initLocal() {
LocalTopology topo = LocalTopology.create(fetchFile(TOPOLOGY_ENDPOINT));
if (topo.getControlServices().isEmpty()) {
throw new ScionRuntimeException(
"No control servers found in topology provided by " + topologyResource);
}
return topo;
return LocalTopology.create(fetchFile(TOPOLOGY_ENDPOINT));
}

private GlobalTopology initGlobal() {
Expand Down Expand Up @@ -129,7 +123,7 @@ private LocalTopology init(java.nio.file.Path file) {
}
LocalTopology topo = LocalTopology.create(contentBuilder.toString());
if (topo.getControlServices().isEmpty()) {
throw new ScionRuntimeException("No control service found in topology filet: " + file);
throw new ScionRuntimeException("No control service found in topology file: " + file);
}
return topo;
}
Expand All @@ -144,7 +138,7 @@ public void refreshTopology() {
public String fetchFile(String resource) {
try {
LOG.info("Fetching resource from bootstrap server: {} {}", topologyResource, resource);
URL url = new URL("http://" + topologyResource + "/" + BASE_URL + resource);
URL url = new URL("http://" + topologyResource + "/" + resource);
return fetchFile(url);
} catch (IOException e) {
throw new ScionRuntimeException(
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/org/scion/jpan/internal/Segments.java
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ public static List<Daemon.Path> getPaths(
if (srcIsdAs == dstIsdAs) {
// case A: same AS, return empty path
Daemon.Path.Builder path = Daemon.Path.newBuilder();
path.setMtu(localAS.getLocalMtu());
path.setMtu(localAS.getMtu());
path.setExpiration(Timestamp.newBuilder().setSeconds(Instant.now().getEpochSecond()).build());
return Collections.singletonList(path.build());
}
Expand All @@ -189,7 +189,7 @@ public static List<Daemon.Path> getPaths(
long to = dstIsdAs;
List<List<Seg.PathSegment>> segments = new ArrayList<>();
// First, if necessary, try to get UP segments
if (!localAS.isLocalAsCore()) {
if (!localAS.isCoreAs()) {
// get UP segments
// TODO find out if dstIsAs is core and directly ask for it.
List<Seg.PathSegment> segmentsUp = getSegments(segmentStub, srcIsdAs, srcWildcard);
Expand Down Expand Up @@ -421,7 +421,7 @@ private static Daemon.Path buildPath(LocalTopology localAS, Seg.PathSegment... s

// info fields
boolean[] reversed = new boolean[segments.length];
long startIA = localAS.getLocalIsdAs();
long startIA = localAS.getIsdAs();
final ByteUtil.MutLong endingIA = new ByteUtil.MutLong(-1);
for (int i = 0; i < infos.length; i++) {
reversed[i] = isReversed(segments[i], startIA, endingIA);
Expand All @@ -430,7 +430,7 @@ private static Daemon.Path buildPath(LocalTopology localAS, Seg.PathSegment... s
}

// hop fields
path.setMtu(localAS.getLocalMtu());
path.setMtu(localAS.getMtu());
for (int i = 0; i < segments.length; i++) {
// bytePosSegID: 6 = 4 bytes path head + 2 byte flag in first info field
writeHopFields(path, raw, 6 + i * 8, segments[i], reversed[i], infos[i]);
Expand Down
4 changes: 2 additions & 2 deletions src/test/java/org/scion/jpan/ProtobufPathDemo.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ public class ProtobufPathDemo {

public static void main(String[] args) {
try (Scion.CloseableService daemon =
Scion.newServiceWithDaemon(DemoConstants.daemon110_minimal)) {
Scion.newServiceWithDaemon(DemoConstants.daemon1111_minimal)) {
ProtobufPathDemo demo = new ProtobufPathDemo(daemon);
demo.testAsInfo();
demo.testInterfaces();
demo.testServices();
demo.testPathsDaemon(DemoConstants.ia110, DemoConstants.ia211);
demo.testPathsDaemon(DemoConstants.ia1111, DemoConstants.ia1112);
// demo.testPathsControlService(srcIA, dstIA);
} catch (IOException e) {
throw new RuntimeException(e);
Expand Down
4 changes: 0 additions & 4 deletions src/test/java/org/scion/jpan/ProtobufSegmentDemo.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,6 @@ public static void main(String[] args) throws ScionException {
// demo.getSegments(toWildcard(ia120), toWildcard(ia210));
}

private static long toWildcard(long ia) {
return (ia >>> 48) << 48;
}

public ProtobufSegmentDemo(String csAddress) {
channel = Grpc.newChannelBuilder(csAddress, InsecureChannelCredentials.create()).build();
segmentStub = SegmentLookupServiceGrpc.newBlockingStub(channel);
Expand Down
4 changes: 2 additions & 2 deletions src/test/java/org/scion/jpan/ScionBootstrapperTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ void testTiny110() {
ScionBootstrapper sb = ScionBootstrapper.createViaTopoFile(topoFile);
LocalTopology topo = sb.getLocalTopology();

assertEquals(ScionUtil.parseIA("1-ff00:0:110"), topo.getLocalIsdAs());
assertEquals(ScionUtil.parseIA("1-ff00:0:110"), topo.getIsdAs());
assertEquals("127.0.0.11:31000", topo.getControlServerAddress());
assertTrue(topo.isLocalAsCore());
assertTrue(topo.isCoreAs());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,11 @@ void test() {
PingPongChannelHelper.Client clientFn = this::client;
PingPongChannelHelper pph = new PingPongChannelHelper(1, 2, 10);
pph.runPingPong(serverFn, clientFn, false);
assertEquals(2 * 10, MockNetwork.getForwardCount(0));
// TODO: This sometimes reports 22 i.o. 20.
assertEquals(
2 * 10,
MockNetwork.getForwardCount(0),
"Actual: " + MockNetwork.getForwardCount(0) + "/" + MockNetwork.getForwardCount(1));
assertEquals(2 * 10, MockNetwork.getForwardCount(1));
assertEquals(2 * 2 * 10, MockNetwork.getAndResetForwardCount());
}
Expand Down
2 changes: 0 additions & 2 deletions src/test/java/org/scion/jpan/api/ScionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,6 @@ void newServiceWithDNS() throws IOException {
assertNotNull(paths);
assertFalse(paths.isEmpty());
assertEquals(1, MockNetwork.getTopoServer().getAndResetCallCount());
assertEquals(1, MockNetwork.getControlServer().getAndResetCallCount());
assertNotEquals(Scion.defaultService(), ss);
} finally {
MockNetwork.stopTiny();
Expand All @@ -319,7 +318,6 @@ void newServiceWithBootstrapServer() throws IOException {
assertNotNull(paths);
assertFalse(paths.isEmpty());
assertEquals(1, MockNetwork.getTopoServer().getAndResetCallCount());
assertEquals(1, MockNetwork.getControlServer().getAndResetCallCount());
// No DNS, no daemon, no ENV variables -> fail.
assertThrows(ScionRuntimeException.class, Scion::defaultService);
} finally {
Expand Down
Loading

0 comments on commit 0908252

Please sign in to comment.