diff --git a/docs/api.rst b/docs/api.rst --- a/docs/api.rst +++ b/docs/api.rst @@ -30,6 +30,16 @@ nodes, or from directories nodes. - ``"*:rel"`` node types allowing all edges to releases. +Timings +~~~~~~~ + +When configured to do so (see the server's README), the server can provide +timings metadata in addition to the result: + +- ``traversal``: time in seconds to do the actual graph traversal. +- ``pid2node``: time in seconds to convert input PID to node id. +- ``node2pid``: time in seconds to convert output node ids to PIDs. + Leaves ------ @@ -54,11 +64,18 @@ HTTP/1.1 200 OK Content-Type: application/json - [ - "swh:1:cnt:669ac7c32292798644b21dbb5a0dc657125f444d", - "swh:1:cnt:da4cb28febe66172a9fdf1a235525ae6c00cde1d", - ... - ] + { + "content": [ + "swh:1:cnt:669ac7c32292798644b21dbb5a0dc657125f444d", + "swh:1:cnt:da4cb28febe66172a9fdf1a235525ae6c00cde1d", + ... + ], + "timings": { + "traversal": 0.002942681, + "pid2node": 0.000178051, + "node2pid": 0.000956569 + } + } Neighbors --------- @@ -83,11 +100,18 @@ HTTP/1.1 200 OK Content-Type: application/json - [ - "swh:1:cnt:94a9ed024d3859793618152ea559a168bbcbb5e2", - "swh:1:dir:d198bc9d7a6bcf6db04f476d29314f157507d505", - ... - ] + { + "content": [ + "swh:1:cnt:94a9ed024d3859793618152ea559a168bbcbb5e2", + "swh:1:dir:d198bc9d7a6bcf6db04f476d29314f157507d505", + ... + ], + "timings": { + "traversal": 0.002942681, + "pid2node": 0.000178051, + "node2pid": 0.000956569 + } + } Walk ---- @@ -118,13 +142,20 @@ HTTP/1.1 200 OK Content-Type: application/json - [ - "swh:1:rev:f39d7d78b70e0f39facb1e4fab77ad3df5c52a35", - "swh:1:rev:52c90f2d32bfa7d6eccd66a56c44ace1f78fbadd", - "swh:1:rev:cea92e843e40452c08ba313abc39f59efbb4c29c", - "swh:1:rev:8d517bdfb57154b8a11d7f1682ecc0f79abf8e02", - ... - ] + { + "content": [ + "swh:1:rev:f39d7d78b70e0f39facb1e4fab77ad3df5c52a35", + "swh:1:rev:52c90f2d32bfa7d6eccd66a56c44ace1f78fbadd", + "swh:1:rev:cea92e843e40452c08ba313abc39f59efbb4c29c", + "swh:1:rev:8d517bdfb57154b8a11d7f1682ecc0f79abf8e02", + ... + ], + "timings": { + "traversal": 0.002942681, + "pid2node": 0.000178051, + "node2pid": 0.000956569 + } + } Visit ----- @@ -152,13 +183,20 @@ HTTP/1.1 200 OK Content-Type: application/json - [ - "swh:1:rev:f39d7d78b70e0f39facb1e4fab77ad3df5c52a35", - "swh:1:rev:52c90f2d32bfa7d6eccd66a56c44ace1f78fbadd", - ... - "swh:1:rev:a31e58e129f73ab5b04016330b13ed51fde7a961", - ... - ] + { + "content": [ + "swh:1:rev:f39d7d78b70e0f39facb1e4fab77ad3df5c52a35", + "swh:1:rev:52c90f2d32bfa7d6eccd66a56c44ace1f78fbadd", + ... + "swh:1:rev:a31e58e129f73ab5b04016330b13ed51fde7a961", + ... + ], + "timings": { + "traversal": 0.002942681, + "pid2node": 0.000178051, + "node2pid": 0.000956569 + } + } .. sourcecode:: http @@ -166,19 +204,26 @@ HTTP/1.1 200 OK Content-Type: application/json - [ - [ - "swh:1:rev:f39d7d78b70e0f39facb1e4fab77ad3df5c52a35", - "swh:1:rev:52c90f2d32bfa7d6eccd66a56c44ace1f78fbadd", - ... - ], - [ - "swh:1:rev:f39d7d78b70e0f39facb1e4fab77ad3df5c52a35", - "swh:1:rev:a31e58e129f73ab5b04016330b13ed51fde7a961", + { + "content": [ + [ + "swh:1:rev:f39d7d78b70e0f39facb1e4fab77ad3df5c52a35", + "swh:1:rev:52c90f2d32bfa7d6eccd66a56c44ace1f78fbadd", + ... + ], + [ + "swh:1:rev:f39d7d78b70e0f39facb1e4fab77ad3df5c52a35", + "swh:1:rev:a31e58e129f73ab5b04016330b13ed51fde7a961", + ... + ], ... ], - ... - ] + "timings" : { + "traversal": 0.002942681, + "pid2node": 0.000178051, + "node2pid": 0.000956569 + } + } Stats ----- diff --git a/java/server/README.md b/java/server/README.md --- a/java/server/README.md +++ b/java/server/README.md @@ -19,7 +19,9 @@ ``` -Default port is 5009. +Default port is 5009 (use the `--port` option to change port number). If you +need timings metadata send back to the client in addition to the result, use the +`--timings` flag. Tests ----- diff --git a/java/server/src/main/java/org/softwareheritage/graph/App.java b/java/server/src/main/java/org/softwareheritage/graph/App.java --- a/java/server/src/main/java/org/softwareheritage/graph/App.java +++ b/java/server/src/main/java/org/softwareheritage/graph/App.java @@ -1,6 +1,7 @@ package org.softwareheritage.graph; import java.io.IOException; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -12,6 +13,7 @@ import com.martiansoftware.jsap.JSAPResult; import com.martiansoftware.jsap.Parameter; import com.martiansoftware.jsap.SimpleJSAP; +import com.martiansoftware.jsap.Switch; import com.martiansoftware.jsap.UnflaggedOption; import io.javalin.Javalin; import io.javalin.http.Context; @@ -45,6 +47,7 @@ "Binding port of the server."), new UnflaggedOption("graphPath", JSAP.STRING_PARSER, JSAP.NO_DEFAULT, JSAP.REQUIRED, JSAP.NOT_GREEDY, "The basename of the compressed graph."), + new Switch("timings", 't', "timings", "Show timings in API result metadata."), } ); @@ -55,8 +58,9 @@ String graphPath = config.getString("graphPath"); int port = config.getInt("port"); + boolean showTimings = config.getBoolean("timings"); - startServer(graphPath, port); + startServer(graphPath, port, showTimings); } /** @@ -64,8 +68,9 @@ * * @param graphPath basename of the compressed graph * @param port binding port of the server + * @param showTimings true if timings should be in results metadata, false otherwise */ - private static void startServer(String graphPath, int port) throws IOException { + private static void startServer(String graphPath, int port, boolean showTimings) throws IOException { Graph graph = new Graph(graphPath); Stats stats = new Stats(graphPath); @@ -104,7 +109,8 @@ String edgesFmt = ctx.queryParam("edges", "*"); Endpoint endpoint = new Endpoint(graph, direction, edgesFmt); - ctx.json(endpoint.leaves(src)); + Endpoint.Output output = endpoint.leaves(src); + ctx.json(formatEndpointOutput(output, showTimings)); }); app.get("/neighbors/:src", ctx -> { @@ -113,7 +119,8 @@ String edgesFmt = ctx.queryParam("edges", "*"); Endpoint endpoint = new Endpoint(graph, direction, edgesFmt); - ctx.json(endpoint.neighbors(src)); + Endpoint.Output output = endpoint.neighbors(src); + ctx.json(formatEndpointOutput(output, showTimings)); }); app.get("/visit/nodes/:src", ctx -> { @@ -122,7 +129,8 @@ String edgesFmt = ctx.queryParam("edges", "*"); Endpoint endpoint = new Endpoint(graph, direction, edgesFmt); - ctx.json(endpoint.visitNodes(src)); + Endpoint.Output output = endpoint.visitNodes(src); + ctx.json(formatEndpointOutput(output, showTimings)); }); app.get("/visit/paths/:src", ctx -> { @@ -131,7 +139,8 @@ String edgesFmt = ctx.queryParam("edges", "*"); Endpoint endpoint = new Endpoint(graph, direction, edgesFmt); - ctx.json(endpoint.visitPaths(src)); + Endpoint.Output output = endpoint.visitPaths(src); + ctx.json(formatEndpointOutput(output, showTimings)); }); app.get("/walk/:src/:dst", ctx -> { @@ -142,7 +151,8 @@ String algorithm = ctx.queryParam("traversal", "dfs"); Endpoint endpoint = new Endpoint(graph, direction, edgesFmt); - ctx.json(endpoint.walk(src, dstFmt, algorithm)); + Endpoint.Output output = endpoint.walk(src, dstFmt, algorithm); + ctx.json(formatEndpointOutput(output, showTimings)); }); app.exception(IllegalArgumentException.class, (e, ctx) -> { @@ -166,4 +176,24 @@ } } } + + /** + * Formats endpoint result into final JSON for the REST API. + *

+ * Removes unwanted information if necessary, such as timings (to prevent use of side channels + * attacks). + * + * @param output endpoint operation output which needs formatting + * @param showTimings true if timings should be in results metadata, false otherwise + * @return final Object with desired JSON format + */ + private static Object formatEndpointOutput(Endpoint.Output output, boolean showTimings) { + if (showTimings) { + return output; + } else { + Map outputNoTimings = new HashMap<>(); + outputNoTimings.put("result", output.result); + return outputNoTimings; + } + } } diff --git a/java/server/src/main/java/org/softwareheritage/graph/Endpoint.java b/java/server/src/main/java/org/softwareheritage/graph/Endpoint.java --- a/java/server/src/main/java/org/softwareheritage/graph/Endpoint.java +++ b/java/server/src/main/java/org/softwareheritage/graph/Endpoint.java @@ -2,9 +2,6 @@ import java.util.ArrayList; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import org.softwareheritage.graph.Graph; import org.softwareheritage.graph.SwhId; import org.softwareheritage.graph.SwhPath; @@ -25,14 +22,50 @@ */ public class Endpoint { + /** + * Wrapper class to return both the endpoint result and metadata (such as timings). + */ + public class Output { + /** The result content itself */ + public T result; + /** Various metadata about the result */ + public Meta meta; + + public Output() { + this.result = null; + this.meta = new Meta(); + } + + /** + * Endpoint result metadata. + */ + public class Meta { + /** Operations timings */ + public Timings timings; + + public Meta() { + this.timings = new Timings(); + } + + /** + * Wrapper class for JSON output format. + */ + public class Timings { + /** Time in seconds to do the traversal */ + public float traversal; + /** Time in seconds to convert input SWH PID to node id */ + public float pid2node; + /** Time in seconds to convert output node ids to SWH PIDs */ + public float node2pid; + } + } + } + /** Graph where traversal endpoint is performed */ Graph graph; /** Internal traversal API */ Traversal traversal; - /** Timings logger */ - private static final Logger logger = LoggerFactory.getLogger(Endpoint.class); - /** * Constructor. * @@ -53,13 +86,10 @@ * @return a list of corresponding SWH PIDs */ private ArrayList convertNodesToSwhIds(ArrayList nodeIds) { - long startTime = Timing.start(); ArrayList swhIds = new ArrayList<>(); for (long nodeId : nodeIds) { swhIds.add(graph.getSwhId(nodeId)); } - float duration = Timing.stop(startTime); - logger.debug("convertNodesToSwhIds() took {} s.", duration); return swhIds; } @@ -71,13 +101,10 @@ * @see org.softwareheritage.graph.SwhPath */ private SwhPath convertNodesToSwhPath(ArrayList nodeIds) { - long startTime = Timing.start(); SwhPath path = new SwhPath(); for (long nodeId : nodeIds) { path.add(graph.getSwhId(nodeId)); } - float duration = Timing.stop(startTime); - logger.debug("convertNodesToSwhPath() took {} s.", duration); return path; } @@ -89,13 +116,10 @@ * @see org.softwareheritage.graph.SwhPath */ private ArrayList convertPathsToSwhIds(ArrayList> pathsNodeId) { - long startTime = Timing.start(); ArrayList paths = new ArrayList<>(); for (ArrayList path : pathsNodeId) { paths.add(convertNodesToSwhPath(path)); } - float duration = Timing.stop(startTime); - logger.debug("convertPathsToSwhIds() took {} s.", duration); return paths; } @@ -103,38 +127,54 @@ * Leaves endpoint wrapper. * * @param src source node of endpoint call specified as a {@link SwhId} - * @return the resulting list of {@link SwhId} from endpoint call + * @return the resulting list of {@link SwhId} from endpoint call and operation metadata * @see org.softwareheritage.graph.SwhId * @see org.softwareheritage.graph.algo.Traversal#leaves(long) */ - public ArrayList leaves(SwhId src) { + public Output leaves(SwhId src) { + Output> output = new Output<>(); + long startTime; + + startTime = Timing.start(); long srcNodeId = graph.getNodeId(src); + output.meta.timings.pid2node = Timing.stop(startTime); - long startTime = Timing.start(); + startTime = Timing.start(); ArrayList nodeIds = traversal.leaves(srcNodeId); - float duration = Timing.stop(startTime); - logger.debug("leaves({}) took {} s.", src, duration); + output.meta.timings.traversal = Timing.stop(startTime); + + startTime = Timing.start(); + output.result = convertNodesToSwhIds(nodeIds); + output.meta.timings.node2pid = Timing.stop(startTime); - return convertNodesToSwhIds(nodeIds); + return output; } /** * Neighbors endpoint wrapper. * * @param src source node of endpoint call specified as a {@link SwhId} - * @return the resulting list of {@link SwhId} from endpoint call + * @return the resulting list of {@link SwhId} from endpoint call and operation metadata * @see org.softwareheritage.graph.SwhId * @see org.softwareheritage.graph.algo.Traversal#neighbors(long) */ - public ArrayList neighbors(SwhId src) { + public Output neighbors(SwhId src) { + Output> output = new Output<>(); + long startTime; + + startTime = Timing.start(); long srcNodeId = graph.getNodeId(src); + output.meta.timings.pid2node = Timing.stop(startTime); - long startTime = Timing.start(); + startTime = Timing.start(); ArrayList nodeIds = traversal.neighbors(srcNodeId); - float duration = Timing.stop(startTime); - logger.debug("neighbors({}) took {} s.", src, duration); + output.meta.timings.traversal = Timing.stop(startTime); - return convertNodesToSwhIds(nodeIds); + startTime = Timing.start(); + output.result = convertNodesToSwhIds(nodeIds); + output.meta.timings.node2pid = Timing.stop(startTime); + + return output; } /** @@ -144,13 +184,19 @@ * @param dstFmt destination formatted string as described in the API * @param algorithm traversal algorithm used in endpoint call (either "dfs" or "bfs") - * @return the resulting {@link SwhPath} from endpoint call + * @return the resulting {@link SwhPath} from endpoint call and operation metadata * @see org.softwareheritage.graph.SwhId * @see org.softwareheritage.graph.SwhPath * @see org.softwareheritage.graph.algo.Traversal#walk */ - public SwhPath walk(SwhId src, String dstFmt, String algorithm) { + public Output walk(SwhId src, String dstFmt, String algorithm) { + Output output = new Output<>(); + long startTime; + + startTime = Timing.start(); long srcNodeId = graph.getNodeId(src); + output.meta.timings.pid2node = Timing.stop(startTime); + ArrayList nodeIds = new ArrayList(); // Destination is either a SWH ID or a node type @@ -158,60 +204,78 @@ SwhId dstSwhId = new SwhId(dstFmt); long dstNodeId = graph.getNodeId(dstSwhId); - long startTime = Timing.start(); + startTime = Timing.start(); nodeIds = traversal.walk(srcNodeId, dstNodeId, algorithm); - float duration = Timing.stop(startTime); - logger.debug("walk({}) took {} s.", src, duration); + output.meta.timings.traversal = Timing.stop(startTime); } catch (IllegalArgumentException ignored1) { try { Node.Type dstType = Node.Type.fromStr(dstFmt); - long startTime = Timing.start(); + startTime = Timing.start(); nodeIds = traversal.walk(srcNodeId, dstType, algorithm); - float duration = Timing.stop(startTime); - logger.debug("walk({}) took {} s.", src, duration); + output.meta.timings.traversal = Timing.stop(startTime); } catch (IllegalArgumentException ignored2) { } } - return convertNodesToSwhPath(nodeIds); + startTime = Timing.start(); + output.result = convertNodesToSwhPath(nodeIds); + output.meta.timings.node2pid = Timing.stop(startTime); + + return output; } /** * VisitNodes endpoint wrapper. * * @param src source node of endpoint call specified as a {@link SwhId} - * @return the resulting list of {@link SwhId} from endpoint call + * @return the resulting list of {@link SwhId} from endpoint call and operation metadata * @see org.softwareheritage.graph.SwhId * @see org.softwareheritage.graph.algo.Traversal#visitNodes(long) */ - public ArrayList visitNodes(SwhId src) { + public Output visitNodes(SwhId src) { + Output> output = new Output<>(); + long startTime; + + startTime = Timing.start(); long srcNodeId = graph.getNodeId(src); + output.meta.timings.pid2node = Timing.stop(startTime); - long startTime = Timing.start(); + startTime = Timing.start(); ArrayList nodeIds = traversal.visitNodes(srcNodeId); - float duration = Timing.stop(startTime); - logger.debug("visitNodes({}) took {} s.", src, duration); + output.meta.timings.traversal = Timing.stop(startTime); + + startTime = Timing.start(); + output.result = convertNodesToSwhIds(nodeIds); + output.meta.timings.node2pid = Timing.stop(startTime); - return convertNodesToSwhIds(nodeIds); + return output; } /** * VisitPaths endpoint wrapper. * * @param src source node of endpoint call specified as a {@link SwhId} - * @return the resulting list of {@link SwhPath} from endpoint call + * @return the resulting list of {@link SwhPath} from endpoint call and operation metadata * @see org.softwareheritage.graph.SwhId * @see org.softwareheritage.graph.SwhPath * @see org.softwareheritage.graph.algo.Traversal#visitPaths(long) */ - public ArrayList visitPaths(SwhId src) { + public Output visitPaths(SwhId src) { + Output> output = new Output<>(); + long startTime; + + startTime = Timing.start(); long srcNodeId = graph.getNodeId(src); + output.meta.timings.pid2node = Timing.stop(startTime); - long startTime = Timing.start(); + startTime = Timing.start(); ArrayList> paths = traversal.visitPaths(srcNodeId); - float duration = Timing.stop(startTime); - logger.debug("visitPaths({}) took {} s.", src, duration); + output.meta.timings.traversal = Timing.stop(startTime); + + startTime = Timing.start(); + output.result = convertPathsToSwhIds(paths); + output.meta.timings.node2pid = Timing.stop(startTime); - return convertPathsToSwhIds(paths); + return output; } } diff --git a/java/server/src/test/java/org/softwareheritage/graph/LeavesTest.java b/java/server/src/test/java/org/softwareheritage/graph/LeavesTest.java --- a/java/server/src/test/java/org/softwareheritage/graph/LeavesTest.java +++ b/java/server/src/test/java/org/softwareheritage/graph/LeavesTest.java @@ -9,6 +9,8 @@ import org.softwareheritage.graph.GraphTest; import org.softwareheritage.graph.SwhId; +// Avoid warnings concerning Endpoint.Output.result manual cast +@SuppressWarnings("unchecked") public class LeavesTest extends GraphTest { @Test public void forwardFromSnp() { @@ -22,7 +24,7 @@ expectedLeaves.add(new SwhId("swh:1:cnt:0000000000000000000000000000000000000005")); expectedLeaves.add(new SwhId("swh:1:cnt:0000000000000000000000000000000000000007")); - GraphTest.assertEqualsAnyOrder(expectedLeaves, endpoint.leaves(src)); + GraphTest.assertEqualsAnyOrder(expectedLeaves, (ArrayList) endpoint.leaves(src).result); } @Test @@ -40,7 +42,7 @@ expectedLeaves.add(new SwhId("swh:1:cnt:0000000000000000000000000000000000000007")); expectedLeaves.add(new SwhId("swh:1:cnt:0000000000000000000000000000000000000011")); - GraphTest.assertEqualsAnyOrder(expectedLeaves, endpoint.leaves(src)); + GraphTest.assertEqualsAnyOrder(expectedLeaves, (ArrayList) endpoint.leaves(src).result); } @Test @@ -51,13 +53,13 @@ SwhId src1 = new SwhId("swh:1:cnt:0000000000000000000000000000000000000015"); ArrayList expectedLeaves1 = new ArrayList<>(); expectedLeaves1.add(new SwhId("swh:1:rel:0000000000000000000000000000000000000019")); - GraphTest.assertEqualsAnyOrder(expectedLeaves1, endpoint.leaves(src1)); + GraphTest.assertEqualsAnyOrder(expectedLeaves1, (ArrayList) endpoint.leaves(src1).result); SwhId src2 = new SwhId("swh:1:cnt:0000000000000000000000000000000000000004"); ArrayList expectedLeaves2 = new ArrayList<>(); expectedLeaves2.add(new SwhId("swh:1:ori:0000000000000000000000000000000000000021")); expectedLeaves2.add(new SwhId("swh:1:rel:0000000000000000000000000000000000000019")); - GraphTest.assertEqualsAnyOrder(expectedLeaves2, endpoint.leaves(src2)); + GraphTest.assertEqualsAnyOrder(expectedLeaves2, (ArrayList) endpoint.leaves(src2).result); } @Test @@ -69,7 +71,7 @@ ArrayList expectedLeaves = new ArrayList<>(); expectedLeaves.add(new SwhId("swh:1:rev:0000000000000000000000000000000000000003")); - GraphTest.assertEqualsAnyOrder(expectedLeaves, endpoint.leaves(src)); + GraphTest.assertEqualsAnyOrder(expectedLeaves, (ArrayList) endpoint.leaves(src).result); } @Test @@ -84,7 +86,7 @@ expectedLeaves.add(new SwhId("swh:1:cnt:0000000000000000000000000000000000000001")); expectedLeaves.add(new SwhId("swh:1:cnt:0000000000000000000000000000000000000007")); - GraphTest.assertEqualsAnyOrder(expectedLeaves, endpoint.leaves(src)); + GraphTest.assertEqualsAnyOrder(expectedLeaves, (ArrayList) endpoint.leaves(src).result); } @Test @@ -96,6 +98,6 @@ ArrayList expectedLeaves = new ArrayList<>(); expectedLeaves.add(new SwhId("swh:1:dir:0000000000000000000000000000000000000012")); - GraphTest.assertEqualsAnyOrder(expectedLeaves, endpoint.leaves(src)); + GraphTest.assertEqualsAnyOrder(expectedLeaves, (ArrayList) endpoint.leaves(src).result); } } diff --git a/java/server/src/test/java/org/softwareheritage/graph/NeighborsTest.java b/java/server/src/test/java/org/softwareheritage/graph/NeighborsTest.java --- a/java/server/src/test/java/org/softwareheritage/graph/NeighborsTest.java +++ b/java/server/src/test/java/org/softwareheritage/graph/NeighborsTest.java @@ -9,6 +9,8 @@ import org.softwareheritage.graph.GraphTest; import org.softwareheritage.graph.SwhId; +// Avoid warnings concerning Endpoint.Output.result manual cast +@SuppressWarnings("unchecked") public class NeighborsTest extends GraphTest { @Test public void zeroNeighbor() { @@ -17,23 +19,23 @@ SwhId src1 = new SwhId("swh:1:ori:0000000000000000000000000000000000000021"); Endpoint endpoint1 = new Endpoint(graph, "backward", "*"); - GraphTest.assertEqualsAnyOrder(expectedNodes, endpoint1.neighbors(src1)); + GraphTest.assertEqualsAnyOrder(expectedNodes, (ArrayList) endpoint1.neighbors(src1).result); SwhId src2 = new SwhId("swh:1:cnt:0000000000000000000000000000000000000004"); Endpoint endpoint2 = new Endpoint(graph, "forward", "*"); - GraphTest.assertEqualsAnyOrder(expectedNodes, endpoint2.neighbors(src2)); + GraphTest.assertEqualsAnyOrder(expectedNodes, (ArrayList) endpoint2.neighbors(src2).result); SwhId src3 = new SwhId("swh:1:cnt:0000000000000000000000000000000000000015"); Endpoint endpoint3 = new Endpoint(graph, "forward", "*"); - GraphTest.assertEqualsAnyOrder(expectedNodes, endpoint3.neighbors(src3)); + GraphTest.assertEqualsAnyOrder(expectedNodes, (ArrayList) endpoint3.neighbors(src3).result); SwhId src4 = new SwhId("swh:1:rel:0000000000000000000000000000000000000019"); Endpoint endpoint4 = new Endpoint(graph, "backward", "*"); - GraphTest.assertEqualsAnyOrder(expectedNodes, endpoint4.neighbors(src4)); + GraphTest.assertEqualsAnyOrder(expectedNodes, (ArrayList) endpoint4.neighbors(src4).result); SwhId src5 = new SwhId("swh:1:dir:0000000000000000000000000000000000000008"); Endpoint endpoint5 = new Endpoint(graph, "forward", "snp:*,rev:*,rel:*"); - GraphTest.assertEqualsAnyOrder(expectedNodes, endpoint5.neighbors(src5)); + GraphTest.assertEqualsAnyOrder(expectedNodes, (ArrayList) endpoint5.neighbors(src5).result); } @Test @@ -44,31 +46,31 @@ Endpoint endpoint1 = new Endpoint(graph, "forward", "*"); ArrayList expectedNodes1 = new ArrayList<>(); expectedNodes1.add(new SwhId("swh:1:dir:0000000000000000000000000000000000000002")); - GraphTest.assertEqualsAnyOrder(expectedNodes1, endpoint1.neighbors(src1)); + GraphTest.assertEqualsAnyOrder(expectedNodes1, (ArrayList) endpoint1.neighbors(src1).result); SwhId src2 = new SwhId("swh:1:dir:0000000000000000000000000000000000000017"); Endpoint endpoint2 = new Endpoint(graph, "forward", "dir:cnt"); ArrayList expectedNodes2 = new ArrayList<>(); expectedNodes2.add(new SwhId("swh:1:cnt:0000000000000000000000000000000000000014")); - GraphTest.assertEqualsAnyOrder(expectedNodes2, endpoint2.neighbors(src2)); + GraphTest.assertEqualsAnyOrder(expectedNodes2, (ArrayList) endpoint2.neighbors(src2).result); SwhId src3 = new SwhId("swh:1:dir:0000000000000000000000000000000000000012"); Endpoint endpoint3 = new Endpoint(graph, "backward", "*"); ArrayList expectedNodes3 = new ArrayList<>(); expectedNodes3.add(new SwhId("swh:1:rev:0000000000000000000000000000000000000013")); - GraphTest.assertEqualsAnyOrder(expectedNodes3, endpoint3.neighbors(src3)); + GraphTest.assertEqualsAnyOrder(expectedNodes3, (ArrayList) endpoint3.neighbors(src3).result); SwhId src4 = new SwhId("swh:1:rev:0000000000000000000000000000000000000009"); Endpoint endpoint4 = new Endpoint(graph, "backward", "rev:rev"); ArrayList expectedNodes4 = new ArrayList<>(); expectedNodes4.add(new SwhId("swh:1:rev:0000000000000000000000000000000000000013")); - GraphTest.assertEqualsAnyOrder(expectedNodes4, endpoint4.neighbors(src4)); + GraphTest.assertEqualsAnyOrder(expectedNodes4, (ArrayList) endpoint4.neighbors(src4).result); SwhId src5 = new SwhId("swh:1:snp:0000000000000000000000000000000000000020"); Endpoint endpoint5 = new Endpoint(graph, "backward", "*"); ArrayList expectedNodes5 = new ArrayList<>(); expectedNodes5.add(new SwhId("swh:1:ori:0000000000000000000000000000000000000021")); - GraphTest.assertEqualsAnyOrder(expectedNodes5, endpoint5.neighbors(src5)); + GraphTest.assertEqualsAnyOrder(expectedNodes5, (ArrayList) endpoint5.neighbors(src5).result); } @Test @@ -80,28 +82,28 @@ ArrayList expectedNodes1 = new ArrayList<>(); expectedNodes1.add(new SwhId("swh:1:rel:0000000000000000000000000000000000000010")); expectedNodes1.add(new SwhId("swh:1:rev:0000000000000000000000000000000000000009")); - GraphTest.assertEqualsAnyOrder(expectedNodes1, endpoint1.neighbors(src1)); + GraphTest.assertEqualsAnyOrder(expectedNodes1, (ArrayList) endpoint1.neighbors(src1).result); SwhId src2 = new SwhId("swh:1:dir:0000000000000000000000000000000000000008"); Endpoint endpoint2 = new Endpoint(graph, "forward", "dir:cnt"); ArrayList expectedNodes2 = new ArrayList<>(); expectedNodes2.add(new SwhId("swh:1:cnt:0000000000000000000000000000000000000001")); expectedNodes2.add(new SwhId("swh:1:cnt:0000000000000000000000000000000000000007")); - GraphTest.assertEqualsAnyOrder(expectedNodes2, endpoint2.neighbors(src2)); + GraphTest.assertEqualsAnyOrder(expectedNodes2, (ArrayList) endpoint2.neighbors(src2).result); SwhId src3 = new SwhId("swh:1:cnt:0000000000000000000000000000000000000001"); Endpoint endpoint3 = new Endpoint(graph, "backward", "*"); ArrayList expectedNodes3 = new ArrayList<>(); expectedNodes3.add(new SwhId("swh:1:dir:0000000000000000000000000000000000000008")); expectedNodes3.add(new SwhId("swh:1:dir:0000000000000000000000000000000000000002")); - GraphTest.assertEqualsAnyOrder(expectedNodes3, endpoint3.neighbors(src3)); + GraphTest.assertEqualsAnyOrder(expectedNodes3, (ArrayList) endpoint3.neighbors(src3).result); SwhId src4 = new SwhId("swh:1:rev:0000000000000000000000000000000000000009"); Endpoint endpoint4 = new Endpoint(graph, "backward", "rev:snp,rev:rel"); ArrayList expectedNodes4 = new ArrayList<>(); expectedNodes4.add(new SwhId("swh:1:snp:0000000000000000000000000000000000000020")); expectedNodes4.add(new SwhId("swh:1:rel:0000000000000000000000000000000000000010")); - GraphTest.assertEqualsAnyOrder(expectedNodes4, endpoint4.neighbors(src4)); + GraphTest.assertEqualsAnyOrder(expectedNodes4, (ArrayList) endpoint4.neighbors(src4).result); } @Test @@ -114,7 +116,7 @@ expectedNodes1.add(new SwhId("swh:1:dir:0000000000000000000000000000000000000006")); expectedNodes1.add(new SwhId("swh:1:cnt:0000000000000000000000000000000000000001")); expectedNodes1.add(new SwhId("swh:1:cnt:0000000000000000000000000000000000000007")); - GraphTest.assertEqualsAnyOrder(expectedNodes1, endpoint1.neighbors(src1)); + GraphTest.assertEqualsAnyOrder(expectedNodes1, (ArrayList) endpoint1.neighbors(src1).result); SwhId src2 = new SwhId("swh:1:rev:0000000000000000000000000000000000000009"); Endpoint endpoint2 = new Endpoint(graph, "backward", "*"); @@ -122,6 +124,6 @@ expectedNodes2.add(new SwhId("swh:1:snp:0000000000000000000000000000000000000020")); expectedNodes2.add(new SwhId("swh:1:rel:0000000000000000000000000000000000000010")); expectedNodes2.add(new SwhId("swh:1:rev:0000000000000000000000000000000000000013")); - GraphTest.assertEqualsAnyOrder(expectedNodes2, endpoint2.neighbors(src2)); + GraphTest.assertEqualsAnyOrder(expectedNodes2, (ArrayList) endpoint2.neighbors(src2).result); } } diff --git a/java/server/src/test/java/org/softwareheritage/graph/VisitTest.java b/java/server/src/test/java/org/softwareheritage/graph/VisitTest.java --- a/java/server/src/test/java/org/softwareheritage/graph/VisitTest.java +++ b/java/server/src/test/java/org/softwareheritage/graph/VisitTest.java @@ -12,6 +12,8 @@ import org.softwareheritage.graph.SwhId; import org.softwareheritage.graph.SwhPath; +// Avoid warnings concerning Endpoint.Output.result manual cast +@SuppressWarnings("unchecked") public class VisitTest extends GraphTest { private void assertSameNodesFromPaths(ArrayList paths, ArrayList nodes) { Set expectedNodes = new HashSet(); @@ -28,8 +30,8 @@ Graph graph = getGraph(); SwhId swhId = new SwhId("swh:1:ori:0000000000000000000000000000000000000021"); Endpoint endpoint = new Endpoint(graph, "forward", "*"); - ArrayList paths = endpoint.visitPaths(swhId); - ArrayList nodes = endpoint.visitNodes(swhId); + ArrayList paths = (ArrayList) endpoint.visitPaths(swhId).result; + ArrayList nodes = (ArrayList) endpoint.visitNodes(swhId).result; ArrayList expectedPaths = new ArrayList(); expectedPaths.add( @@ -133,8 +135,8 @@ Graph graph = getGraph(); SwhId swhId = new SwhId("swh:1:dir:0000000000000000000000000000000000000012"); Endpoint endpoint = new Endpoint(graph, "forward", "*"); - ArrayList paths = endpoint.visitPaths(swhId); - ArrayList nodes = endpoint.visitNodes(swhId); + ArrayList paths = (ArrayList) endpoint.visitPaths(swhId).result; + ArrayList nodes = (ArrayList) endpoint.visitNodes(swhId).result; ArrayList expectedPaths = new ArrayList(); expectedPaths.add( @@ -178,8 +180,8 @@ Graph graph = getGraph(); SwhId swhId = new SwhId("swh:1:cnt:0000000000000000000000000000000000000004"); Endpoint endpoint = new Endpoint(graph, "forward", "*"); - ArrayList paths = endpoint.visitPaths(swhId); - ArrayList nodes = endpoint.visitNodes(swhId); + ArrayList paths = (ArrayList) endpoint.visitPaths(swhId).result; + ArrayList nodes = (ArrayList) endpoint.visitNodes(swhId).result; ArrayList expectedPaths = new ArrayList(); expectedPaths.add( @@ -196,8 +198,8 @@ Graph graph = getGraph(); SwhId swhId = new SwhId("swh:1:ori:0000000000000000000000000000000000000021"); Endpoint endpoint = new Endpoint(graph, "backward", "*"); - ArrayList paths = endpoint.visitPaths(swhId); - ArrayList nodes = endpoint.visitNodes(swhId); + ArrayList paths = (ArrayList) endpoint.visitPaths(swhId).result; + ArrayList nodes = (ArrayList) endpoint.visitNodes(swhId).result; ArrayList expectedPaths = new ArrayList(); expectedPaths.add( @@ -214,8 +216,8 @@ Graph graph = getGraph(); SwhId swhId = new SwhId("swh:1:dir:0000000000000000000000000000000000000012"); Endpoint endpoint = new Endpoint(graph, "backward", "*"); - ArrayList paths = endpoint.visitPaths(swhId); - ArrayList nodes = endpoint.visitNodes(swhId); + ArrayList paths = (ArrayList) endpoint.visitPaths(swhId).result; + ArrayList nodes = (ArrayList) endpoint.visitNodes(swhId).result; ArrayList expectedPaths = new ArrayList(); expectedPaths.add( @@ -235,8 +237,8 @@ Graph graph = getGraph(); SwhId swhId = new SwhId("swh:1:cnt:0000000000000000000000000000000000000004"); Endpoint endpoint = new Endpoint(graph, "backward", "*"); - ArrayList paths = endpoint.visitPaths(swhId); - ArrayList nodes = endpoint.visitNodes(swhId); + ArrayList paths = (ArrayList) endpoint.visitPaths(swhId).result; + ArrayList nodes = (ArrayList) endpoint.visitNodes(swhId).result; ArrayList expectedPaths = new ArrayList(); expectedPaths.add( @@ -288,8 +290,8 @@ Graph graph = getGraph(); SwhId swhId = new SwhId("swh:1:snp:0000000000000000000000000000000000000020"); Endpoint endpoint = new Endpoint(graph, "forward", "snp:rev"); - ArrayList paths = endpoint.visitPaths(swhId); - ArrayList nodes = endpoint.visitNodes(swhId); + ArrayList paths = (ArrayList) endpoint.visitPaths(swhId).result; + ArrayList nodes = (ArrayList) endpoint.visitNodes(swhId).result; ArrayList expectedPaths = new ArrayList(); expectedPaths.add( @@ -307,8 +309,8 @@ Graph graph = getGraph(); SwhId swhId = new SwhId("swh:1:rel:0000000000000000000000000000000000000010"); Endpoint endpoint = new Endpoint(graph, "forward", "rel:rev,rev:rev"); - ArrayList paths = endpoint.visitPaths(swhId); - ArrayList nodes = endpoint.visitNodes(swhId); + ArrayList paths = (ArrayList) endpoint.visitPaths(swhId).result; + ArrayList nodes = (ArrayList) endpoint.visitNodes(swhId).result; ArrayList expectedPaths = new ArrayList(); expectedPaths.add( @@ -327,8 +329,8 @@ Graph graph = getGraph(); SwhId swhId = new SwhId("swh:1:rev:0000000000000000000000000000000000000013"); Endpoint endpoint = new Endpoint(graph, "forward", "rev:*,dir:*"); - ArrayList paths = endpoint.visitPaths(swhId); - ArrayList nodes = endpoint.visitNodes(swhId); + ArrayList paths = (ArrayList) endpoint.visitPaths(swhId).result; + ArrayList nodes = (ArrayList) endpoint.visitNodes(swhId).result; ArrayList expectedPaths = new ArrayList(); expectedPaths.add( @@ -415,8 +417,8 @@ Graph graph = getGraph(); SwhId swhId = new SwhId("swh:1:snp:0000000000000000000000000000000000000020"); Endpoint endpoint = new Endpoint(graph, "forward", "snp:*,rev:*"); - ArrayList paths = endpoint.visitPaths(swhId); - ArrayList nodes = endpoint.visitNodes(swhId); + ArrayList paths = (ArrayList) endpoint.visitPaths(swhId).result; + ArrayList nodes = (ArrayList) endpoint.visitNodes(swhId).result; ArrayList expectedPaths = new ArrayList(); expectedPaths.add( @@ -447,8 +449,8 @@ Graph graph = getGraph(); SwhId swhId = new SwhId("swh:1:snp:0000000000000000000000000000000000000020"); Endpoint endpoint = new Endpoint(graph, "forward", ""); - ArrayList paths = endpoint.visitPaths(swhId); - ArrayList nodes = endpoint.visitNodes(swhId); + ArrayList paths = (ArrayList) endpoint.visitPaths(swhId).result; + ArrayList nodes = (ArrayList) endpoint.visitNodes(swhId).result; ArrayList expectedPaths = new ArrayList(); expectedPaths.add( @@ -465,8 +467,8 @@ Graph graph = getGraph(); SwhId swhId = new SwhId("swh:1:rev:0000000000000000000000000000000000000003"); Endpoint endpoint = new Endpoint(graph, "backward", "rev:rev,rev:rel"); - ArrayList paths = endpoint.visitPaths(swhId); - ArrayList nodes = endpoint.visitNodes(swhId); + ArrayList paths = (ArrayList) endpoint.visitPaths(swhId).result; + ArrayList nodes = (ArrayList) endpoint.visitNodes(swhId).result; ArrayList expectedPaths = new ArrayList(); expectedPaths.add( @@ -493,7 +495,7 @@ Graph graph = getGraph(); SwhId swhId = new SwhId("swh:1:ori:0000000000000000000000000000000000000021"); Endpoint endpoint = new Endpoint(graph, "forward", "*"); - ArrayList nodes = endpoint.visitNodes(swhId); + ArrayList nodes = (ArrayList) endpoint.visitNodes(swhId).result; ArrayList expectedNodes = new ArrayList(); expectedNodes.add(new SwhId("swh:1:ori:0000000000000000000000000000000000000021")); @@ -517,7 +519,7 @@ Graph graph = getGraph(); SwhId swhId = new SwhId("swh:1:rev:0000000000000000000000000000000000000003"); Endpoint endpoint = new Endpoint(graph, "backward", "rev:*"); - ArrayList nodes = endpoint.visitNodes(swhId); + ArrayList nodes = (ArrayList) endpoint.visitNodes(swhId).result; ArrayList expectedNodes = new ArrayList(); expectedNodes.add(new SwhId("swh:1:rev:0000000000000000000000000000000000000003")); diff --git a/java/server/src/test/java/org/softwareheritage/graph/WalkTest.java b/java/server/src/test/java/org/softwareheritage/graph/WalkTest.java --- a/java/server/src/test/java/org/softwareheritage/graph/WalkTest.java +++ b/java/server/src/test/java/org/softwareheritage/graph/WalkTest.java @@ -39,8 +39,8 @@ "swh:1:cnt:0000000000000000000000000000000000000005" ); - SwhPath dfsPath = endpoint.walk(src, dstFmt, "dfs"); - SwhPath bfsPath = endpoint.walk(src, dstFmt, "bfs"); + SwhPath dfsPath = (SwhPath) endpoint.walk(src, dstFmt, "dfs").result; + SwhPath bfsPath = (SwhPath) endpoint.walk(src, dstFmt, "bfs").result; List possibleSolutions = Arrays.asList(solution1, solution2); Assert.assertTrue(possibleSolutions.contains(dfsPath)); @@ -59,8 +59,8 @@ "swh:1:cnt:0000000000000000000000000000000000000007" ); - SwhPath dfsPath = endpoint.walk(src, dstFmt, "dfs"); - SwhPath bfsPath = endpoint.walk(src, dstFmt, "bfs"); + SwhPath dfsPath = (SwhPath) endpoint.walk(src, dstFmt, "dfs").result; + SwhPath bfsPath = (SwhPath) endpoint.walk(src, dstFmt, "bfs").result; Assert.assertEquals(dfsPath, expectedPath); Assert.assertEquals(bfsPath, expectedPath); @@ -81,8 +81,8 @@ "swh:1:rev:0000000000000000000000000000000000000003" ); - SwhPath dfsPath = endpoint.walk(src, dstFmt, "dfs"); - SwhPath bfsPath = endpoint.walk(src, dstFmt, "bfs"); + SwhPath dfsPath = (SwhPath) endpoint.walk(src, dstFmt, "dfs").result; + SwhPath bfsPath = (SwhPath) endpoint.walk(src, dstFmt, "bfs").result; Assert.assertEquals(dfsPath, expectedPath); Assert.assertEquals(bfsPath, expectedPath); @@ -103,8 +103,8 @@ "swh:1:rev:0000000000000000000000000000000000000018" ); - SwhPath dfsPath = endpoint.walk(src, dstFmt, "dfs"); - SwhPath bfsPath = endpoint.walk(src, dstFmt, "bfs"); + SwhPath dfsPath = (SwhPath) endpoint.walk(src, dstFmt, "dfs").result; + SwhPath bfsPath = (SwhPath) endpoint.walk(src, dstFmt, "bfs").result; Assert.assertEquals(dfsPath, expectedPath); Assert.assertEquals(bfsPath, expectedPath); @@ -150,8 +150,8 @@ "swh:1:snp:0000000000000000000000000000000000000020" ); - SwhPath dfsPath = endpoint.walk(src, dstFmt, "dfs"); - SwhPath bfsPath = endpoint.walk(src, dstFmt, "bfs"); + SwhPath dfsPath = (SwhPath) endpoint.walk(src, dstFmt, "dfs").result; + SwhPath bfsPath = (SwhPath) endpoint.walk(src, dstFmt, "bfs").result; List possibleSolutions = Arrays.asList(solution1, solution2, solution3, solution4); Assert.assertTrue(possibleSolutions.contains(dfsPath)); @@ -199,8 +199,8 @@ "swh:1:cnt:0000000000000000000000000000000000000001" ); - SwhPath dfsPath = endpoint.walk(src, dstFmt, "dfs"); - SwhPath bfsPath = endpoint.walk(src, dstFmt, "bfs"); + SwhPath dfsPath = (SwhPath) endpoint.walk(src, dstFmt, "dfs").result; + SwhPath bfsPath = (SwhPath) endpoint.walk(src, dstFmt, "bfs").result; List possibleSolutions = Arrays.asList(solution1, solution2, solution3, solution4, solution5); @@ -223,8 +223,8 @@ "swh:1:rel:0000000000000000000000000000000000000019" ); - SwhPath dfsPath = endpoint.walk(src, dstFmt, "dfs"); - SwhPath bfsPath = endpoint.walk(src, dstFmt, "bfs"); + SwhPath dfsPath = (SwhPath) endpoint.walk(src, dstFmt, "dfs").result; + SwhPath bfsPath = (SwhPath) endpoint.walk(src, dstFmt, "bfs").result; Assert.assertEquals(dfsPath, expectedPath); Assert.assertEquals(bfsPath, expectedPath);