Added new test method SwitchStorageImplTest::testShortestPath()
that computes the shortest path between two vertices.
diff --git a/src/test/java/net/floodlightcontroller/core/internal/SwitchStorageImplTest.java b/src/test/java/net/floodlightcontroller/core/internal/SwitchStorageImplTest.java
index 8f272c5..177769b 100644
--- a/src/test/java/net/floodlightcontroller/core/internal/SwitchStorageImplTest.java
+++ b/src/test/java/net/floodlightcontroller/core/internal/SwitchStorageImplTest.java
@@ -5,7 +5,9 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import java.util.ArrayList;
import java.util.Iterator;
+import java.util.List;
import net.floodlightcontroller.core.ISwitchStorage;
import net.floodlightcontroller.core.ISwitchStorage.SwitchState;
@@ -17,8 +19,22 @@
import org.openflow.protocol.OFPhysicalPort;
import com.thinkaurelius.titan.core.TitanGraph;
+import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Vertex;
+import com.tinkerpop.gremlin.groovy.Gremlin;
import com.tinkerpop.gremlin.java.GremlinPipeline;
+import com.tinkerpop.pipes.Pipe;
+import com.tinkerpop.pipes.PipeFunction;
+import com.tinkerpop.pipes.branch.LoopPipe;
+import com.tinkerpop.pipes.branch.LoopPipe.LoopBundle;
+import com.tinkerpop.pipes.filter.FilterPipe.Filter;
+import com.tinkerpop.pipes.util.PipesFluentPipeline;
+
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+import com.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine;
+
public class SwitchStorageImplTest {
@@ -143,4 +159,107 @@
public void testGetActiveSwitches() {
fail("Not yet implemented");
}
+
+ static class MyLoopFunction implements PipeFunction<LoopBundle<Vertex>, Boolean> {
+ String dpid;
+ public MyLoopFunction(String dpid) {
+ super();
+ this.dpid = dpid;
+ }
+ public Boolean compute(LoopBundle<Vertex> bundle) {
+ Boolean output = false;
+ if ((bundle.getObject().getProperty("dpid") != dpid) &&
+ (bundle.getLoops() < 10)) {
+ output = true;
+ }
+ return output;
+ }
+ }
+
+ @Test
+ public void testShortestPath() {
+ String dpid_src = "00:00:00:00:00:00:0a:01";
+ String dpid_dest = "00:00:00:00:00:00:0a:06";
+
+ //
+ // Implement the Shortest Path between two vertices by using
+ // the following Gremlin code:
+ // results = []; v_src.as('x').out.out.in.has("type", "switch").dedup().loop('x'){it.object.dpid != v_dest.dpid & it.loops < 10}.path().fill(results)
+ //
+
+ String gremlin = "v_src.as(\"x\").out.out.in.has(\"type\", \"switch\").dedup().loop(\"x\"){it.object.dpid != v_dest.dpid & it.loops < 10}.path().fill(results)";
+
+ // Get the source vertex
+ Iterator<Vertex> iter = titanGraph.getVertices("dpid", dpid_src).iterator();
+ if (! iter.hasNext())
+ return; // Source vertex not found
+ Vertex v_src = iter.next();
+
+ // Get the destination vertex
+ iter = titanGraph.getVertices("dpid", dpid_dest).iterator();
+ if (! iter.hasNext())
+ return; // Destination vertex not found
+ Vertex v_dest = iter.next();
+
+ //
+ // Implement the Gremlin script and run it
+ //
+ ScriptEngine engine = new GremlinGroovyScriptEngine();
+
+ ArrayList<ArrayList<Vertex>> results = new ArrayList<ArrayList<Vertex>>();
+ engine.getBindings(ScriptContext.ENGINE_SCOPE).put("g", titanGraph);
+ engine.getBindings(ScriptContext.ENGINE_SCOPE).put("v_src", v_src);
+ engine.getBindings(ScriptContext.ENGINE_SCOPE).put("v_dest", v_dest);
+ engine.getBindings(ScriptContext.ENGINE_SCOPE).put("results", results);
+
+ try {
+ engine.eval(gremlin);
+ } catch (ScriptException e) {
+ System.err.println("Caught ScriptException running Gremlin script: " + e.getMessage());
+ return;
+ }
+
+ //
+ // Extract the result and compose it into a string
+ //
+ String results_str = "";
+ // System.out.println("BEGIN " + results.size());
+ for (ArrayList<Vertex> lv : results) {
+ // System.out.println(lv);
+ for (Vertex v: lv) {
+ // System.out.println(v);
+ String type = v.getProperty("type").toString();
+ results_str += "[type: " + type;
+ // System.out.println("type: " + type);
+ if (type.equals("port")) {
+ String number = v.getProperty("number").toString();
+ // System.out.println("number: " + number);
+ results_str += " number: " + number + "]";
+ }
+ if (type.equals("switch")) {
+ String dpid = v.getProperty("dpid").toString();
+ // System.out.println("dpid: " + dpid);
+ results_str += " dpid: " + dpid + "]";
+ }
+ }
+ }
+ // System.out.println("END\n");
+ System.out.println(results_str);
+
+ String expected_result = "[type: switch dpid: 00:00:00:00:00:00:0a:01][type: port number: 2][type: port number: 1][type: switch dpid: 00:00:00:00:00:00:0a:03][type: port number: 2][type: port number: 2][type: switch dpid: 00:00:00:00:00:00:0a:04][type: port number: 3][type: port number: 1][type: switch dpid: 00:00:00:00:00:00:0a:06]";
+
+
+ // Pipe<Vertex, Vertex> pipe = Gremlin.compile(gremlin);
+ // pipe.setStarts(new SingleIterator<Vertex>(v1));
+
+ //
+ // XXX: An alternative (faster?) solution that fails to compile
+ //
+ MyLoopFunction whileFunction = new MyLoopFunction(dpid_dest);
+ GremlinPipeline<Vertex, Vertex> pipe = new GremlinPipeline<Vertex, Vertex>();
+ // pipe.start(v_src).as("x").out().out().in().has("type", "switch").dedup().loop("x", whileFunction);
+
+ // Check the result
+ assertEquals(results_str, expected_result);
+ }
}