Skip to content

Commit

Permalink
Add ShortestPathApiTest
Browse files Browse the repository at this point in the history
Change-Id: If68f2aa410453c08e85b0f4dbb09ef519be85528
  • Loading branch information
Linary committed Apr 18, 2019
1 parent da8cc0f commit bbae80d
Show file tree
Hide file tree
Showing 6 changed files with 288 additions and 220 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public static class Request {
@JsonProperty("limit")
private long limit = Traverser.DEFAULT_LIMIT;
@JsonProperty("max_depth")
private int maxDepth = Traverser.DEFAULT_MAX_DEPTH;
private int maxDepth = 5;
@JsonProperty("with_label")
private WithLabel withLabel = WithLabel.BOTH_LABEL;
@JsonProperty("sorted")
Expand Down Expand Up @@ -121,9 +121,11 @@ public Builder limit(long limit) {
}

public Builder maxDepth(int maxDepth) {
TraversersAPI.checkPositive(maxDepth,
"max depth of rank request " +
"for personal rank");
E.checkArgument(maxDepth > 0 &&
maxDepth <= Traverser.DEFAULT_MAX_DEPTH,
"The max depth must be in range (0, %s], " +
"but got: %s",
Traverser.DEFAULT_MAX_DEPTH, maxDepth);
this.request.maxDepth = maxDepth;
return this;
}
Expand All @@ -147,9 +149,13 @@ public Request build() {
TraversersAPI.checkAlpha(this.request.alpha);
TraversersAPI.checkDegree(this.request.degree);
TraversersAPI.checkLimit(this.request.limit);
TraversersAPI.checkPositive(this.request.maxDepth,
"max depth of rank request " +
"for personal rank");
E.checkArgument(this.request.maxDepth > 0 &&
this.request.maxDepth <=
Traverser.DEFAULT_MAX_DEPTH,
"The max depth must be in range (0, %s], " +
"but got: %s",
Traverser.DEFAULT_MAX_DEPTH,
this.request.maxDepth);
return this.request;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public static void checkLimit(long limit) {

public static void checkAlpha(double alpha) {
E.checkArgument(alpha > 0 && alpha <= 1.0,
"The alpha of rank request must belong (0, 1], " +
"The alpha of rank request must be in range (0, 1], " +
"but got '%s'", alpha);
}
}
1 change: 1 addition & 0 deletions src/test/java/com/baidu/hugegraph/api/ApiTestSuite.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
JobApiTest.class,
RestoreApiTest.class,
TraverserApiTest.class,
ShortestPathApiTest.class,
CustomizedPathsApiTest.class,
NeighborRankApiTest.class,
PersonalRankApiTest.class
Expand Down
15 changes: 10 additions & 5 deletions src/test/java/com/baidu/hugegraph/api/PersonalRankApiTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -156,14 +156,14 @@ public void testPersonalRankWithLimit() {
public void testPersonalRankWithMaxDepth() {
PersonalRankAPI.Request.Builder builder;
builder = PersonalRankAPI.Request.builder();
builder.source("A").label("like").alpha(0.9).maxDepth(100);
builder.source("A").label("like").alpha(0.9).maxDepth(20);
PersonalRankAPI.Request request = builder.build();

Map<Object, Double> ranks = personalRankAPI.post(request);
Assert.assertEquals(ImmutableMap.of("B", 0.2053607173863809D,
"C", 0.09778790213639266D,
"d", 0.09020474105856267D,
"b", 0.04620317325456084D),
Assert.assertEquals(ImmutableMap.of("B", 0.23414889646372697D,
"C", 0.11218194186115384D,
"d", 0.07581065434649958D,
"b", 0.03900612828909826D),
ranks);
}

Expand Down Expand Up @@ -246,6 +246,11 @@ public void testPersonalRankWithInvalidParams() {
builder = PersonalRankAPI.Request.builder();
builder.maxDepth(0);
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
PersonalRankAPI.Request.Builder builder;
builder = PersonalRankAPI.Request.builder();
builder.maxDepth(51);
});
}

private static void initPersonalRankGraph() {
Expand Down
263 changes: 263 additions & 0 deletions src/test/java/com/baidu/hugegraph/api/ShortestPathApiTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/

package com.baidu.hugegraph.api;

import java.util.List;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.baidu.hugegraph.exception.ServerException;
import com.baidu.hugegraph.structure.constant.Direction;
import com.baidu.hugegraph.structure.constant.T;
import com.baidu.hugegraph.structure.graph.Path;
import com.baidu.hugegraph.structure.graph.Vertex;
import com.baidu.hugegraph.testutil.Assert;
import com.google.common.collect.ImmutableList;

public class ShortestPathApiTest extends BaseApiTest {

@Before
public void setup() {
initShortestPathGraph();
}

@After
public void teardown() {
clearShortestPathGraph();
}

@Test
public void testShortestPath() {
Path path = shortestPathAPI.get(1, 6, Direction.BOTH,
null, 6, -1L, 0L, -1L);
Assert.assertEquals(4, path.size());
Assert.assertEquals(ImmutableList.of(1, 10, 11, 6), path.objects());
}

@Test
public void testShortestPathWithLabel() {
Path path = shortestPathAPI.get(1, 6, Direction.BOTH,
"link", 6, -1L, 0L, -1L);
Assert.assertEquals(4, path.size());
Assert.assertEquals(ImmutableList.of(1, 10, 11, 6), path.objects());
}

@Test
public void testShortestPathWithDegree() {
Path path = shortestPathAPI.get(1, 6, Direction.BOTH,
null, 6, 1L, 0L, -1L);
Assert.assertEquals(6, path.size());
Assert.assertEquals(ImmutableList.of(1, 2, 3, 4, 5, 6), path.objects());
}

@Test
public void testShortestPathWithCapacity() {
Path path = shortestPathAPI.get(14, 6, Direction.BOTH,
null, 6, 5L, 0L, 19L);
Assert.assertEquals(5, path.size());
Assert.assertEquals(ImmutableList.of(14, 7, 8, 9, 6), path.objects());

Assert.assertThrows(ServerException.class, () -> {
shortestPathAPI.get(14, 6, Direction.BOTH, null, 6, 1L, 0L, 2L);
});
}

@Test
public void testShortestPathWithMaxDepth() {
Path path = shortestPathAPI.get(14, 6, Direction.BOTH,
null, 4, 5L, 0L, 19L);
Assert.assertEquals(5, path.size());
Assert.assertEquals(ImmutableList.of(14, 7, 8, 9, 6), path.objects());

path = shortestPathAPI.get(14, 6, Direction.BOTH,
null, 3, 5L, 0L, 19L);
Assert.assertEquals(0, path.size());
}

@Test
public void testShortestPathWithSkipDegree() {
// Path length 5 with min degree 3(v1 degree is 3)
List<Object> path1 = ImmutableList.of(1, 2, 3, 4, 5, 6);
// Path length 4 with middle degree 4(v7 degree is 4)
List<Object> path2 = ImmutableList.of(1, 7, 8, 9, 6);
// Path length 3 with max degree 5(v10 degree is 5)
List<Object> path3 = ImmutableList.of(1, 10, 11, 6);

// (skipped degree == degree) > max degree
Path path = shortestPathAPI.get(1, 6, Direction.OUT,
null, 5, 6L, 6L, -1L);
Assert.assertEquals(4, path.size());
Assert.assertEquals(path3, path.objects());

// (skipped degree == degree) == max degree
path = shortestPathAPI.get(1, 6, Direction.OUT,
null, 5, 5L, 5L, -1L);
Assert.assertEquals(5, path.size());
Assert.assertEquals(path2, path.objects());

// min degree < (skipped degree == degree) == middle degree < max degree
path = shortestPathAPI.get(1, 6, Direction.OUT,
null, 5, 4L, 4L, -1L);
Assert.assertEquals(6, path.size());
Assert.assertEquals(path1, path.objects());

// (skipped degree == degree) <= min degree
path = shortestPathAPI.get(1, 6, Direction.OUT,
null, 5, 3L, 3L, -1L);
Assert.assertEquals(0, path.size());

// Skipped degree > max degree, degree <= min degree
path = shortestPathAPI.get(1, 6, Direction.OUT,
null, 5, 3L, 6L, -1L);
Assert.assertTrue(path.size() == 4 ||
path.size() == 5 ||
path.size() == 6);
List<List<Object>> paths = ImmutableList.of(path1, path2, path3);
Assert.assertTrue(paths.contains(path.objects()));

// Skipped degree > max degree, min degree < degree < max degree
path = shortestPathAPI.get(1, 6, Direction.OUT,
null, 5, 4L, 6L, -1L);
Assert.assertTrue(path.size() == 4 || path.size() == 5);
Assert.assertTrue(path2.equals(path.objects()) ||
path3.equals(path.objects()));

// Skipped degree > max degree, degree >= max degree
path = shortestPathAPI.get(1, 6, Direction.OUT,
null, 5, 5L, 6L, -1L);
Assert.assertEquals(4, path.size());
Assert.assertEquals(path3, path.objects());
}

@Test
public void testShortestPathWithIllegalArgs() {
// The max depth shouldn't be 0 or negative
Assert.assertThrows(IllegalArgumentException.class, () -> {
shortestPathAPI.get("a", "b", Direction.BOTH,
null, -1, 1L, 0L, 2L);
});

Assert.assertThrows(IllegalArgumentException.class, () -> {
shortestPathAPI.get("a", "b", Direction.BOTH,
null, 0, 1L, 0L, 2L);
});

// The degree shouldn't be 0 or negative but NO_LIMIT(-1)
Assert.assertThrows(IllegalArgumentException.class, () -> {
shortestPathAPI.get("a", "b", Direction.BOTH,
null, 5, 0L, 0L, 2L);
});

Assert.assertThrows(IllegalArgumentException.class, () -> {
shortestPathAPI.get("a", "b", Direction.BOTH,
null, 5, -3L, 0L, 2L);
});

// The skipped degree shouldn't be negative
Assert.assertThrows(IllegalArgumentException.class, () -> {
shortestPathAPI.get("a", "b", Direction.BOTH,
null, 5, 1L, -1L, 2L);
});

// The skipped degree shouldn't be >= capacity
Assert.assertThrows(IllegalArgumentException.class, () -> {
shortestPathAPI.get("a", "b", Direction.BOTH,
null, 5, 1L, 2L, 2L);
});

// The skipped degree shouldn't be < degree
Assert.assertThrows(IllegalArgumentException.class, () -> {
shortestPathAPI.get("a", "b", Direction.BOTH,
null, 5, 3L, 2L, 10L);
});

Assert.assertThrows(IllegalArgumentException.class, () -> {
shortestPathAPI.get("a", "b", Direction.BOTH,
null, 5, -1L, 2L, 10L);
});
}

private static void initShortestPathGraph() {
schema().vertexLabel("node")
.useCustomizeNumberId()
.ifNotExist()
.create();

schema().edgeLabel("link")
.sourceLabel("node").targetLabel("node")
.ifNotExist()
.create();

Vertex v1 = graph().addVertex(T.label, "node", T.id, 1);
Vertex v2 = graph().addVertex(T.label, "node", T.id, 2);
Vertex v3 = graph().addVertex(T.label, "node", T.id, 3);
Vertex v4 = graph().addVertex(T.label, "node", T.id, 4);
Vertex v5 = graph().addVertex(T.label, "node", T.id, 5);
Vertex v6 = graph().addVertex(T.label, "node", T.id, 6);
Vertex v7 = graph().addVertex(T.label, "node", T.id, 7);
Vertex v8 = graph().addVertex(T.label, "node", T.id, 8);
Vertex v9 = graph().addVertex(T.label, "node", T.id, 9);
Vertex v10 = graph().addVertex(T.label, "node", T.id, 10);
Vertex v11 = graph().addVertex(T.label, "node", T.id, 11);
Vertex v12 = graph().addVertex(T.label, "node", T.id, 12);
Vertex v13 = graph().addVertex(T.label, "node", T.id, 13);
Vertex v14 = graph().addVertex(T.label, "node", T.id, 14);
Vertex v15 = graph().addVertex(T.label, "node", T.id, 15);
Vertex v16 = graph().addVertex(T.label, "node", T.id, 16);
Vertex v17 = graph().addVertex(T.label, "node", T.id, 17);
Vertex v18 = graph().addVertex(T.label, "node", T.id, 18);

// Path length 5
v1.addEdge("link", v2);
v2.addEdge("link", v3);
v3.addEdge("link", v4);
v4.addEdge("link", v5);
v5.addEdge("link", v6);

// Path length 4
v1.addEdge("link", v7);
v7.addEdge("link", v8);
v8.addEdge("link", v9);
v9.addEdge("link", v6);

// Path length 3
v1.addEdge("link", v10);
v10.addEdge("link", v11);
v11.addEdge("link", v6);

// Add other 3 neighbor for v7
v7.addEdge("link", v12);
v7.addEdge("link", v13);
v7.addEdge("link", v14);

// Add other 4 neighbor for v10
v10.addEdge("link", v15);
v10.addEdge("link", v16);
v10.addEdge("link", v17);
v10.addEdge("link", v18);
}

private static void clearShortestPathGraph() {
waitUntilTaskCompleted(edgeLabelAPI.delete("link"));
waitUntilTaskCompleted(vertexLabelAPI.delete("node"));
}
}
Loading

0 comments on commit bbae80d

Please sign in to comment.