diff --git a/api/server/src/main/java/org/softwareheritage/graph/App.java b/api/server/src/main/java/org/softwareheritage/graph/App.java index a4541db..a127d75 100644 --- a/api/server/src/main/java/org/softwareheritage/graph/App.java +++ b/api/server/src/main/java/org/softwareheritage/graph/App.java @@ -1,70 +1,88 @@ package org.softwareheritage.graph; import java.io.IOException; import java.util.List; import java.util.Map; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.PropertyNamingStrategy; import io.javalin.Javalin; import io.javalin.plugin.json.JavalinJackson; import org.softwareheritage.graph.Graph; import org.softwareheritage.graph.SwhId; import org.softwareheritage.graph.algo.Stats; import org.softwareheritage.graph.algo.Visit; public class App { public static void main(String[] args) throws IOException { String path = args[0]; Graph graph = new Graph(path); Stats stats = new Stats(path); // Clean up on exit Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { try { graph.cleanUp(); } catch (IOException e) { System.out.println("Could not clean up graph on exit: " + e); } } }); // Configure Jackson JSON to use snake case naming style ObjectMapper objectMapper = JavalinJackson.getObjectMapper(); objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); JavalinJackson.configure(objectMapper); Javalin app = Javalin.create().start(5009); - app.get("/stats", ctx -> { - ctx.json(stats); + // Check query strings on API endpoints + app.before("/visit/*", ctx -> { + Map> queryParamMap = ctx.queryParamMap(); + for (String key : queryParamMap.keySet()) { + if (!key.matches("direction|edges")) { + throw new IllegalArgumentException("Unknown query string: " + key); + } + } }); - app.get("/visit/:swh_id", ctx -> { - try { - Map> queryParamMap = ctx.queryParamMap(); - for (String key : queryParamMap.keySet()) { - if (!key.matches("direction|edges|traversal")) { - throw new IllegalArgumentException("Unknown query string: " + key); - } - } + app.get("/stats/", ctx -> { ctx.json(stats); }); - SwhId swhId = new SwhId(ctx.pathParam("swh_id")); + // Graph traversal endpoints + // By default the traversal is a forward DFS using all edges - // By default, traversal is a forward DFS using all edges - String traversal = ctx.queryParam("traversal", "dfs"); - String direction = ctx.queryParam("direction", "forward"); - String edges = ctx.queryParam("edges", "*"); + app.get("/visit/:src", ctx -> { + SwhId src = new SwhId(ctx.pathParam("src")); + String direction = ctx.queryParam("direction", "forward"); + String edges = ctx.queryParam("edges", "*"); - ctx.json(new Visit(graph, swhId, edges, traversal, direction)); - } catch (IllegalArgumentException e) { - ctx.status(400); - ctx.result(e.getMessage()); - } + Visit visit = new Visit(graph, src, edges, direction, Visit.OutputFmt.NODES_AND_PATHS); + ctx.json(visit); }); - app.error(404, ctx -> { ctx.result("Not found"); }); + app.get("/visit/nodes/:src", ctx -> { + SwhId src = new SwhId(ctx.pathParam("src")); + String direction = ctx.queryParam("direction", "forward"); + String edges = ctx.queryParam("edges", "*"); + + Visit visit = new Visit(graph, src, edges, direction, Visit.OutputFmt.ONLY_NODES); + ctx.json(visit.getNodes()); + }); + + app.get("/visit/paths/:src", ctx -> { + SwhId src = new SwhId(ctx.pathParam("src")); + String direction = ctx.queryParam("direction", "forward"); + String edges = ctx.queryParam("edges", "*"); + + Visit visit = new Visit(graph, src, edges, direction, Visit.OutputFmt.ONLY_PATHS); + ctx.json(visit.getPaths()); + }); + + app.exception(IllegalArgumentException.class, (e, ctx) -> { + ctx.status(400); + ctx.result(e.getMessage()); + }); } } diff --git a/api/server/src/main/java/org/softwareheritage/graph/SwhId.java b/api/server/src/main/java/org/softwareheritage/graph/SwhId.java index eeb6584..a5ad7c1 100644 --- a/api/server/src/main/java/org/softwareheritage/graph/SwhId.java +++ b/api/server/src/main/java/org/softwareheritage/graph/SwhId.java @@ -1,62 +1,67 @@ package org.softwareheritage.graph; import com.fasterxml.jackson.annotation.JsonValue; import org.softwareheritage.graph.Node; public class SwhId { public static final int HASH_LENGTH = 40; String swhId; Node.Type type; String hash; // SWH ID format: 'swh:1:type:hash' // https://docs.softwareheritage.org/devel/swh-model/persistent-identifiers.html public SwhId(String swhId) { this.swhId = swhId; String[] parts = swhId.split(":"); if (parts.length != 4 || !parts[0].equals("swh") || !parts[1].equals("1")) { throw new IllegalArgumentException("Expected SWH ID format to be 'swh:1:type:hash', got: " + swhId); } String type = parts[2]; if (!type.matches("cnt|dir|rel|rev|snp")) { throw new IllegalArgumentException("Unknown SWH ID type in: " + swhId); } this.type = Node.Type.fromStr(type); this.hash = parts[3]; if (!hash.matches("[0-9a-f]{" + HASH_LENGTH + "}")) { throw new IllegalArgumentException("Wrong SWH ID hash format in: " + swhId); } } @Override public boolean equals(Object otherObj) { if (otherObj == this) return true; if (!(otherObj instanceof SwhId)) return false; SwhId other = (SwhId) otherObj; return swhId.equals(other.getSwhId()); } + @Override + public int hashCode() { + return swhId.hashCode(); + } + @Override public String toString() { return swhId; } @JsonValue public String getSwhId() { return swhId; } public Node.Type getType() { return type; } public String getHash() { return hash; } } diff --git a/api/server/src/main/java/org/softwareheritage/graph/algo/Visit.java b/api/server/src/main/java/org/softwareheritage/graph/algo/Visit.java index 23e4e5f..817f4a9 100644 --- a/api/server/src/main/java/org/softwareheritage/graph/algo/Visit.java +++ b/api/server/src/main/java/org/softwareheritage/graph/algo/Visit.java @@ -1,72 +1,97 @@ package org.softwareheritage.graph.algo; import java.util.ArrayList; +import java.util.LinkedHashSet; import java.util.Stack; import it.unimi.dsi.big.webgraph.LazyLongIterator; import org.softwareheritage.graph.Edges; import org.softwareheritage.graph.Graph; import org.softwareheritage.graph.Node; import org.softwareheritage.graph.SwhId; import org.softwareheritage.graph.SwhPath; public class Visit { + public enum OutputFmt { ONLY_NODES, ONLY_PATHS, NODES_AND_PATHS } + Graph graph; boolean useTransposed; Edges edges; - Stack currentPath; + // LinkedHashSet is necessary to preserve insertion order + LinkedHashSet nodes; ArrayList paths; + Stack currentPath; - public Visit(Graph graph, SwhId swhId, String allowedEdges, String algorithm, String direction) { - if (!algorithm.matches("dfs|bfs")) { - throw new IllegalArgumentException("Unknown traversal algorithm: " + algorithm); - } + public Visit(Graph graph, SwhId src, String edges, String direction, OutputFmt output) { if (!direction.matches("forward|backward")) { throw new IllegalArgumentException("Unknown traversal direction: " + direction); } this.graph = graph; this.useTransposed = (direction.equals("backward")); - this.edges = new Edges(allowedEdges); + this.edges = new Edges(edges); + this.nodes = new LinkedHashSet(); this.paths = new ArrayList(); this.currentPath = new Stack(); - if (algorithm.equals("dfs")) { - dfs(graph.getNodeId(swhId)); + long nodeId = graph.getNodeId(src); + if (output == OutputFmt.ONLY_NODES) { + dfsOutputOnlyNodes(nodeId); + } else { + dfs(nodeId); } } - // Allow Jackson JSON to only serialize the 'paths' field + public LinkedHashSet getNodes() { + return nodes; + } + public ArrayList getPaths() { return paths; } private void dfs(long currentNodeId) { + nodes.add(graph.getSwhId(currentNodeId)); currentPath.push(currentNodeId); long degree = graph.degree(currentNodeId, useTransposed); LazyLongIterator neighbors = graph.neighbors(currentNodeId, useTransposed); long visitedNeighbors = 0; while (degree-- > 0) { long neighborNodeId = neighbors.nextLong(); Node.Type currentNodeType = graph.getSwhId(currentNodeId).getType(); Node.Type neighborNodeType = graph.getSwhId(neighborNodeId).getType(); if (edges.isAllowed(currentNodeType, neighborNodeType)) { dfs(neighborNodeId); visitedNeighbors++; } } if (visitedNeighbors == 0) { SwhPath path = new SwhPath(); for (long nodeId : currentPath) { path.add(graph.getSwhId(nodeId)); } paths.add(path); } currentPath.pop(); } + + private void dfsOutputOnlyNodes(long currentNodeId) { + nodes.add(graph.getSwhId(currentNodeId)); + long degree = graph.degree(currentNodeId, useTransposed); + LazyLongIterator neighbors = graph.neighbors(currentNodeId, useTransposed); + + while (degree-- > 0) { + long neighborNodeId = neighbors.nextLong(); + Node.Type currentNodeType = graph.getSwhId(currentNodeId).getType(); + Node.Type neighborNodeType = graph.getSwhId(neighborNodeId).getType(); + if (edges.isAllowed(currentNodeType, neighborNodeType)) { + dfsOutputOnlyNodes(neighborNodeId); + } + } + } } diff --git a/api/server/src/test/java/org/softwareheritage/graph/VisitTest.java b/api/server/src/test/java/org/softwareheritage/graph/VisitTest.java index 4170c31..80c968f 100644 --- a/api/server/src/test/java/org/softwareheritage/graph/VisitTest.java +++ b/api/server/src/test/java/org/softwareheritage/graph/VisitTest.java @@ -1,448 +1,450 @@ package org.softwareheritage.graph; import java.util.ArrayList; import org.junit.Assert; import org.junit.Test; import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; import org.softwareheritage.graph.Graph; import org.softwareheritage.graph.GraphTest; import org.softwareheritage.graph.SwhId; import org.softwareheritage.graph.SwhPath; import org.softwareheritage.graph.algo.Visit; public class VisitTest extends GraphTest { void assertEqualSwhPaths(ArrayList expecteds, ArrayList actuals) { Assert.assertThat(expecteds, containsInAnyOrder(actuals.toArray())); } + Visit.OutputFmt outputFmt = Visit.OutputFmt.NODES_AND_PATHS; + @Test public void dfsForwardFromRoot() { Graph graph = getGraph(); SwhId swhId = new SwhId("swh:1:snp:0000000000000000000000000000000000000020"); - Visit visit = new Visit(graph, swhId, "*", "dfs", "forward"); + Visit visit = new Visit(graph, swhId, "*", "forward", outputFmt); ArrayList paths = visit.getPaths(); ArrayList expectedPaths = new ArrayList(); expectedPaths.add( new SwhPath( "swh:1:snp:0000000000000000000000000000000000000020", "swh:1:rev:0000000000000000000000000000000000000009", "swh:1:dir:0000000000000000000000000000000000000008", "swh:1:cnt:0000000000000000000000000000000000000007" )); expectedPaths.add( new SwhPath( "swh:1:snp:0000000000000000000000000000000000000020", "swh:1:rev:0000000000000000000000000000000000000009", "swh:1:dir:0000000000000000000000000000000000000008", "swh:1:cnt:0000000000000000000000000000000000000001" )); expectedPaths.add( new SwhPath( "swh:1:snp:0000000000000000000000000000000000000020", "swh:1:rev:0000000000000000000000000000000000000009", "swh:1:dir:0000000000000000000000000000000000000008", "swh:1:dir:0000000000000000000000000000000000000006", "swh:1:cnt:0000000000000000000000000000000000000004" )); expectedPaths.add( new SwhPath( "swh:1:snp:0000000000000000000000000000000000000020", "swh:1:rev:0000000000000000000000000000000000000009", "swh:1:dir:0000000000000000000000000000000000000008", "swh:1:dir:0000000000000000000000000000000000000006", "swh:1:cnt:0000000000000000000000000000000000000005" )); expectedPaths.add( new SwhPath( "swh:1:snp:0000000000000000000000000000000000000020", "swh:1:rev:0000000000000000000000000000000000000009", "swh:1:rev:0000000000000000000000000000000000000003", "swh:1:dir:0000000000000000000000000000000000000002", "swh:1:cnt:0000000000000000000000000000000000000001" )); expectedPaths.add( new SwhPath( "swh:1:snp:0000000000000000000000000000000000000020", "swh:1:rel:0000000000000000000000000000000000000010", "swh:1:rev:0000000000000000000000000000000000000009", "swh:1:dir:0000000000000000000000000000000000000008", "swh:1:cnt:0000000000000000000000000000000000000007" )); expectedPaths.add( new SwhPath( "swh:1:snp:0000000000000000000000000000000000000020", "swh:1:rel:0000000000000000000000000000000000000010", "swh:1:rev:0000000000000000000000000000000000000009", "swh:1:dir:0000000000000000000000000000000000000008", "swh:1:cnt:0000000000000000000000000000000000000001" )); expectedPaths.add( new SwhPath( "swh:1:snp:0000000000000000000000000000000000000020", "swh:1:rel:0000000000000000000000000000000000000010", "swh:1:rev:0000000000000000000000000000000000000009", "swh:1:dir:0000000000000000000000000000000000000008", "swh:1:dir:0000000000000000000000000000000000000006", "swh:1:cnt:0000000000000000000000000000000000000004" )); expectedPaths.add( new SwhPath( "swh:1:snp:0000000000000000000000000000000000000020", "swh:1:rel:0000000000000000000000000000000000000010", "swh:1:rev:0000000000000000000000000000000000000009", "swh:1:dir:0000000000000000000000000000000000000008", "swh:1:dir:0000000000000000000000000000000000000006", "swh:1:cnt:0000000000000000000000000000000000000005" )); expectedPaths.add( new SwhPath( "swh:1:snp:0000000000000000000000000000000000000020", "swh:1:rel:0000000000000000000000000000000000000010", "swh:1:rev:0000000000000000000000000000000000000009", "swh:1:rev:0000000000000000000000000000000000000003", "swh:1:dir:0000000000000000000000000000000000000002", "swh:1:cnt:0000000000000000000000000000000000000001" )); assertEqualSwhPaths(expectedPaths, paths); } @Test public void dfsForwardFromMiddle() { Graph graph = getGraph(); SwhId swhId = new SwhId("swh:1:dir:0000000000000000000000000000000000000012"); - Visit visit = new Visit(graph, swhId, "*", "dfs", "forward"); + Visit visit = new Visit(graph, swhId, "*", "forward", outputFmt); ArrayList paths = visit.getPaths(); ArrayList expectedPaths = new ArrayList(); expectedPaths.add( new SwhPath( "swh:1:dir:0000000000000000000000000000000000000012", "swh:1:dir:0000000000000000000000000000000000000008", "swh:1:cnt:0000000000000000000000000000000000000007" )); expectedPaths.add( new SwhPath( "swh:1:dir:0000000000000000000000000000000000000012", "swh:1:dir:0000000000000000000000000000000000000008", "swh:1:cnt:0000000000000000000000000000000000000001" )); expectedPaths.add( new SwhPath( "swh:1:dir:0000000000000000000000000000000000000012", "swh:1:dir:0000000000000000000000000000000000000008", "swh:1:dir:0000000000000000000000000000000000000006", "swh:1:cnt:0000000000000000000000000000000000000004" )); expectedPaths.add( new SwhPath( "swh:1:dir:0000000000000000000000000000000000000012", "swh:1:dir:0000000000000000000000000000000000000008", "swh:1:dir:0000000000000000000000000000000000000006", "swh:1:cnt:0000000000000000000000000000000000000005" )); expectedPaths.add( new SwhPath( "swh:1:dir:0000000000000000000000000000000000000012", "swh:1:cnt:0000000000000000000000000000000000000011" )); assertEqualSwhPaths(expectedPaths, paths); } @Test public void dfsForwardFromLeaf() { Graph graph = getGraph(); SwhId swhId = new SwhId("swh:1:cnt:0000000000000000000000000000000000000004"); - Visit visit = new Visit(graph, swhId, "*", "dfs", "forward"); + Visit visit = new Visit(graph, swhId, "*", "forward", outputFmt); ArrayList paths = visit.getPaths(); ArrayList expectedPaths = new ArrayList(); expectedPaths.add( new SwhPath( "swh:1:cnt:0000000000000000000000000000000000000004" )); assertEqualSwhPaths(expectedPaths, paths); } @Test public void dfsBackwardFromRoot() { Graph graph = getGraph(); SwhId swhId = new SwhId("swh:1:snp:0000000000000000000000000000000000000020"); - Visit visit = new Visit(graph, swhId, "*", "dfs", "backward"); + Visit visit = new Visit(graph, swhId, "*", "backward", outputFmt); ArrayList paths = visit.getPaths(); ArrayList expectedPaths = new ArrayList(); expectedPaths.add( new SwhPath( "swh:1:snp:0000000000000000000000000000000000000020" )); assertEqualSwhPaths(expectedPaths, paths); } @Test public void dfsBackwardFromMiddle() { Graph graph = getGraph(); SwhId swhId = new SwhId("swh:1:dir:0000000000000000000000000000000000000012"); - Visit visit = new Visit(graph, swhId, "*", "dfs", "backward"); + Visit visit = new Visit(graph, swhId, "*", "backward", outputFmt); ArrayList paths = visit.getPaths(); ArrayList expectedPaths = new ArrayList(); expectedPaths.add( new SwhPath( "swh:1:dir:0000000000000000000000000000000000000012", "swh:1:rev:0000000000000000000000000000000000000013", "swh:1:rev:0000000000000000000000000000000000000018", "swh:1:rel:0000000000000000000000000000000000000019" )); assertEqualSwhPaths(expectedPaths, paths); } @Test public void dfsBackwardFromLeaf() { Graph graph = getGraph(); SwhId swhId = new SwhId("swh:1:cnt:0000000000000000000000000000000000000004"); - Visit visit = new Visit(graph, swhId, "*", "dfs", "backward"); + Visit visit = new Visit(graph, swhId, "*", "backward", outputFmt); ArrayList paths = visit.getPaths(); ArrayList expectedPaths = new ArrayList(); expectedPaths.add( new SwhPath( "swh:1:cnt:0000000000000000000000000000000000000004", "swh:1:dir:0000000000000000000000000000000000000006", "swh:1:dir:0000000000000000000000000000000000000008", "swh:1:dir:0000000000000000000000000000000000000012", "swh:1:rev:0000000000000000000000000000000000000013", "swh:1:rev:0000000000000000000000000000000000000018", "swh:1:rel:0000000000000000000000000000000000000019" )); expectedPaths.add( new SwhPath( "swh:1:cnt:0000000000000000000000000000000000000004", "swh:1:dir:0000000000000000000000000000000000000006", "swh:1:dir:0000000000000000000000000000000000000008", "swh:1:rev:0000000000000000000000000000000000000009", "swh:1:rev:0000000000000000000000000000000000000013", "swh:1:rev:0000000000000000000000000000000000000018", "swh:1:rel:0000000000000000000000000000000000000019" )); expectedPaths.add( new SwhPath( "swh:1:cnt:0000000000000000000000000000000000000004", "swh:1:dir:0000000000000000000000000000000000000006", "swh:1:dir:0000000000000000000000000000000000000008", "swh:1:rev:0000000000000000000000000000000000000009", "swh:1:snp:0000000000000000000000000000000000000020" )); expectedPaths.add( new SwhPath( "swh:1:cnt:0000000000000000000000000000000000000004", "swh:1:dir:0000000000000000000000000000000000000006", "swh:1:dir:0000000000000000000000000000000000000008", "swh:1:rev:0000000000000000000000000000000000000009", "swh:1:rel:0000000000000000000000000000000000000010", "swh:1:snp:0000000000000000000000000000000000000020" )); assertEqualSwhPaths(expectedPaths, paths); } @Test public void dfsForwardSnpToRev() { Graph graph = getGraph(); SwhId swhId = new SwhId("swh:1:snp:0000000000000000000000000000000000000020"); - Visit visit = new Visit(graph, swhId, "snp:rev", "dfs", "forward"); + Visit visit = new Visit(graph, swhId, "snp:rev", "forward", outputFmt); ArrayList paths = visit.getPaths(); ArrayList expectedPaths = new ArrayList(); expectedPaths.add( new SwhPath( "swh:1:snp:0000000000000000000000000000000000000020", "swh:1:rev:0000000000000000000000000000000000000009" )); assertEqualSwhPaths(expectedPaths, paths); } @Test public void dfsForwardRelToRevRevToRev() { Graph graph = getGraph(); SwhId swhId = new SwhId("swh:1:rel:0000000000000000000000000000000000000010"); - Visit visit = new Visit(graph, swhId, "rel:rev,rev:rev", "dfs", "forward"); + Visit visit = new Visit(graph, swhId, "rel:rev,rev:rev", "forward", outputFmt); ArrayList paths = visit.getPaths(); ArrayList expectedPaths = new ArrayList(); expectedPaths.add( new SwhPath( "swh:1:rel:0000000000000000000000000000000000000010", "swh:1:rev:0000000000000000000000000000000000000009", "swh:1:rev:0000000000000000000000000000000000000003" )); assertEqualSwhPaths(expectedPaths, paths); } @Test public void dfsForwardRevToAllDirToAll() { Graph graph = getGraph(); SwhId swhId = new SwhId("swh:1:rev:0000000000000000000000000000000000000013"); - Visit visit = new Visit(graph, swhId, "rev:*,dir:*", "dfs", "forward"); + Visit visit = new Visit(graph, swhId, "rev:*,dir:*", "forward", outputFmt); ArrayList paths = visit.getPaths(); ArrayList expectedPaths = new ArrayList(); expectedPaths.add( new SwhPath( "swh:1:rev:0000000000000000000000000000000000000013", "swh:1:rev:0000000000000000000000000000000000000009", "swh:1:dir:0000000000000000000000000000000000000008", "swh:1:dir:0000000000000000000000000000000000000006", "swh:1:cnt:0000000000000000000000000000000000000005" )); expectedPaths.add( new SwhPath( "swh:1:rev:0000000000000000000000000000000000000013", "swh:1:dir:0000000000000000000000000000000000000012", "swh:1:dir:0000000000000000000000000000000000000008", "swh:1:dir:0000000000000000000000000000000000000006", "swh:1:cnt:0000000000000000000000000000000000000005" )); expectedPaths.add( new SwhPath( "swh:1:rev:0000000000000000000000000000000000000013", "swh:1:rev:0000000000000000000000000000000000000009", "swh:1:dir:0000000000000000000000000000000000000008", "swh:1:dir:0000000000000000000000000000000000000006", "swh:1:cnt:0000000000000000000000000000000000000004" )); expectedPaths.add( new SwhPath( "swh:1:rev:0000000000000000000000000000000000000013", "swh:1:dir:0000000000000000000000000000000000000012", "swh:1:dir:0000000000000000000000000000000000000008", "swh:1:dir:0000000000000000000000000000000000000006", "swh:1:cnt:0000000000000000000000000000000000000004" )); expectedPaths.add( new SwhPath( "swh:1:rev:0000000000000000000000000000000000000013", "swh:1:rev:0000000000000000000000000000000000000009", "swh:1:dir:0000000000000000000000000000000000000008", "swh:1:cnt:0000000000000000000000000000000000000007" )); expectedPaths.add( new SwhPath( "swh:1:rev:0000000000000000000000000000000000000013", "swh:1:dir:0000000000000000000000000000000000000012", "swh:1:dir:0000000000000000000000000000000000000008", "swh:1:cnt:0000000000000000000000000000000000000007" )); expectedPaths.add( new SwhPath( "swh:1:rev:0000000000000000000000000000000000000013", "swh:1:dir:0000000000000000000000000000000000000012", "swh:1:cnt:0000000000000000000000000000000000000011" )); expectedPaths.add( new SwhPath( "swh:1:rev:0000000000000000000000000000000000000013", "swh:1:rev:0000000000000000000000000000000000000009", "swh:1:rev:0000000000000000000000000000000000000003", "swh:1:dir:0000000000000000000000000000000000000002", "swh:1:cnt:0000000000000000000000000000000000000001" )); expectedPaths.add( new SwhPath( "swh:1:rev:0000000000000000000000000000000000000013", "swh:1:rev:0000000000000000000000000000000000000009", "swh:1:dir:0000000000000000000000000000000000000008", "swh:1:cnt:0000000000000000000000000000000000000001" )); expectedPaths.add( new SwhPath( "swh:1:rev:0000000000000000000000000000000000000013", "swh:1:dir:0000000000000000000000000000000000000012", "swh:1:dir:0000000000000000000000000000000000000008", "swh:1:cnt:0000000000000000000000000000000000000001" )); assertEqualSwhPaths(expectedPaths, paths); } @Test public void dfsForwardSnpToAllRevToAll() { Graph graph = getGraph(); SwhId swhId = new SwhId("swh:1:snp:0000000000000000000000000000000000000020"); - Visit visit = new Visit(graph, swhId, "snp:*,rev:*", "dfs", "forward"); + Visit visit = new Visit(graph, swhId, "snp:*,rev:*", "forward", outputFmt); ArrayList paths = visit.getPaths(); ArrayList expectedPaths = new ArrayList(); expectedPaths.add( new SwhPath( "swh:1:snp:0000000000000000000000000000000000000020", "swh:1:rev:0000000000000000000000000000000000000009", "swh:1:rev:0000000000000000000000000000000000000003", "swh:1:dir:0000000000000000000000000000000000000002" )); expectedPaths.add( new SwhPath( "swh:1:snp:0000000000000000000000000000000000000020", "swh:1:rev:0000000000000000000000000000000000000009", "swh:1:dir:0000000000000000000000000000000000000008" )); expectedPaths.add( new SwhPath( "swh:1:snp:0000000000000000000000000000000000000020", "swh:1:rel:0000000000000000000000000000000000000010" )); assertEqualSwhPaths(expectedPaths, paths); } @Test public void dfsForwardNoEdges() { Graph graph = getGraph(); SwhId swhId = new SwhId("swh:1:snp:0000000000000000000000000000000000000020"); - Visit visit = new Visit(graph, swhId, "", "dfs", "forward"); + Visit visit = new Visit(graph, swhId, "", "forward", outputFmt); ArrayList paths = visit.getPaths(); ArrayList expectedPaths = new ArrayList(); expectedPaths.add( new SwhPath( "swh:1:snp:0000000000000000000000000000000000000020" )); assertEqualSwhPaths(expectedPaths, paths); } @Test public void dfsBackwardRevToRevRevToRel() { Graph graph = getGraph(); SwhId swhId = new SwhId("swh:1:rev:0000000000000000000000000000000000000003"); - Visit visit = new Visit(graph, swhId, "rev:rev,rev:rel", "dfs", "backward"); + Visit visit = new Visit(graph, swhId, "rev:rev,rev:rel", "backward", outputFmt); ArrayList paths = visit.getPaths(); ArrayList expectedPaths = new ArrayList(); expectedPaths.add( new SwhPath( "swh:1:rev:0000000000000000000000000000000000000003", "swh:1:rev:0000000000000000000000000000000000000009", "swh:1:rev:0000000000000000000000000000000000000013", "swh:1:rev:0000000000000000000000000000000000000018", "swh:1:rel:0000000000000000000000000000000000000019" )); expectedPaths.add( new SwhPath( "swh:1:rev:0000000000000000000000000000000000000003", "swh:1:rev:0000000000000000000000000000000000000009", "swh:1:rel:0000000000000000000000000000000000000010" )); assertEqualSwhPaths(expectedPaths, paths); } }