blob: 1310c3315aca356c7960f7f931c309a7e633004b [file] [log] [blame]
Jonathan Hart627f10c2013-01-16 14:20:03 -08001package net.floodlightcontroller.core.internal;
2
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -08003import static org.junit.Assert.assertEquals;
4import static org.junit.Assert.assertFalse;
5import static org.junit.Assert.assertTrue;
6import static org.junit.Assert.fail;
Jonathan Hart627f10c2013-01-16 14:20:03 -08007
Pavlin Radoslavov5185fac2013-01-29 16:40:10 -08008import java.util.ArrayList;
Jonathan Hart627f10c2013-01-16 14:20:03 -08009import java.util.Iterator;
Pavlin Radoslavov5185fac2013-01-29 16:40:10 -080010import java.util.List;
Jonathan Hart627f10c2013-01-16 14:20:03 -080011
Jonathan Hart627f10c2013-01-16 14:20:03 -080012import net.floodlightcontroller.core.ISwitchStorage;
13import net.floodlightcontroller.core.ISwitchStorage.SwitchState;
14
15import org.junit.After;
16import org.junit.Before;
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -080017import org.junit.Ignore;
Jonathan Hart627f10c2013-01-16 14:20:03 -080018import org.junit.Test;
19import org.openflow.protocol.OFPhysicalPort;
20
21import com.thinkaurelius.titan.core.TitanGraph;
Pavlin Radoslavov5185fac2013-01-29 16:40:10 -080022import com.tinkerpop.blueprints.Direction;
Jonathan Hart627f10c2013-01-16 14:20:03 -080023import com.tinkerpop.blueprints.Vertex;
Pavlin Radoslavov5185fac2013-01-29 16:40:10 -080024import com.tinkerpop.gremlin.groovy.Gremlin;
Jonathan Hart627f10c2013-01-16 14:20:03 -080025import com.tinkerpop.gremlin.java.GremlinPipeline;
Pavlin Radoslavov5185fac2013-01-29 16:40:10 -080026import com.tinkerpop.pipes.Pipe;
27import com.tinkerpop.pipes.PipeFunction;
28import com.tinkerpop.pipes.branch.LoopPipe;
29import com.tinkerpop.pipes.branch.LoopPipe.LoopBundle;
30import com.tinkerpop.pipes.filter.FilterPipe.Filter;
31import com.tinkerpop.pipes.util.PipesFluentPipeline;
32
33import javax.script.ScriptContext;
34import javax.script.ScriptEngine;
35import javax.script.ScriptException;
36import com.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine;
37
Jonathan Hart627f10c2013-01-16 14:20:03 -080038
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -080039public class SwitchStorageImplTest {
Jonathan Hart627f10c2013-01-16 14:20:03 -080040
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -080041 private ISwitchStorage switchStorage;
42 private TitanGraph titanGraph;
Jonathan Hart627f10c2013-01-16 14:20:03 -080043
44 @Before
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -080045 public void setUp() throws Exception {
Jonathan Hart627f10c2013-01-16 14:20:03 -080046 titanGraph = TestDatabaseManager.getTestDatabase();
47 TestDatabaseManager.populateTestData(titanGraph);
48
49 switchStorage = new TestableSwitchStorageImpl(titanGraph);
50 }
51
52 @After
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -080053 public void tearDown() throws Exception {
54 titanGraph.shutdown();
Jonathan Hart627f10c2013-01-16 14:20:03 -080055 }
56
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -080057 @Ignore @Test
Jonathan Hart627f10c2013-01-16 14:20:03 -080058 public void testUpdate() {
59 fail("Not yet implemented");
60 }
61
62 @Test
63 public void testAddPort() {
64
65 String dpid = "00:00:00:00:00:00:0a:01";
66 short portNumber = 5;
67
68 OFPhysicalPort portToAdd = new OFPhysicalPort();
69 portToAdd.setName("port 5 at SEA switch");
70 portToAdd.setCurrentFeatures(OFPhysicalPort.OFPortFeatures.OFPPF_100MB_FD.getValue());
71 portToAdd.setPortNumber(portNumber);
72
73 switchStorage.addPort(dpid, portToAdd);
74
75 Vertex sw = titanGraph.getVertices("dpid", dpid).iterator().next();
76
77 GremlinPipeline<Vertex, Vertex> pipe = new GremlinPipeline<Vertex, Vertex>();
78 pipe.start(sw).out("on").has("number", portNumber);
79
80 assertTrue(pipe.hasNext());
81 Vertex addedPort = pipe.next();
82 assertFalse(pipe.hasNext());
83
84 assertEquals(addedPort.getProperty("number"), portNumber);
85 }
86
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -080087 @Ignore @Test
Jonathan Hart627f10c2013-01-16 14:20:03 -080088 public void testGetPorts() {
89 fail("Not yet implemented");
90 }
91
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -080092 @Ignore @Test
Jonathan Hart627f10c2013-01-16 14:20:03 -080093 public void testGetPortStringShort() {
94 fail("Not yet implemented");
95 }
96
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -080097 @Ignore @Test
Jonathan Hart627f10c2013-01-16 14:20:03 -080098 public void testGetPortStringString() {
99 fail("Not yet implemented");
100 }
101
102 @Test
103 public void testAddSwitch() {
104 String dpid = "00:00:00:00:00:00:0a:07";
105
106 switchStorage.addSwitch(dpid);
107
108 Iterator<Vertex> it = titanGraph.getVertices("dpid", dpid).iterator();
109 assertTrue(it.hasNext());
110 Vertex addedSwitch = it.next();
111 assertFalse(it.hasNext());
112
113 assertEquals(addedSwitch.getProperty("type"), "switch");
114 assertEquals(addedSwitch.getProperty("dpid"), dpid);
115 assertEquals(addedSwitch.getProperty("state"), SwitchState.ACTIVE.toString());
116 }
117
118
Jonathan Hart627f10c2013-01-16 14:20:03 -0800119 @Test
120 public void testDeleteSwitch() {
121 String dpid = "00:00:00:00:00:00:0a:01";
122
123 switchStorage.deleteSwitch(dpid);
124
125 Iterator<Vertex> it = titanGraph.getVertices("dpid", dpid).iterator();
126 assertFalse(it.hasNext());
127 }
128
Jonathan Hart627f10c2013-01-16 14:20:03 -0800129 @Test
130 public void testDeletePortByPortNum() {
131 //FIXME fails because query for the port is wrong in SwitchStorageImpl
132
133 String dpid = "00:00:00:00:00:00:0a:01";
134 short portNum = 3;
135
136 switchStorage.deletePort(dpid, portNum);
137
138 Vertex sw = titanGraph.getVertices("dpid", dpid).iterator().next();
139
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -0800140 /*
Jonathan Hart627f10c2013-01-16 14:20:03 -0800141 Iterator<Vertex> it = sw.getVertices(Direction.OUT, "on").iterator();
142
143 while (it.hasNext()){
144 System.out.println(it.next());
145 }
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -0800146 */
Jonathan Hart627f10c2013-01-16 14:20:03 -0800147
148 GremlinPipeline<Vertex, Vertex> pipe = new GremlinPipeline<Vertex, Vertex>();
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -0800149 pipe.start(sw).out("on").has("number", portNum);
Jonathan Hart627f10c2013-01-16 14:20:03 -0800150 assertFalse(pipe.hasNext());
151 }
152
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -0800153 @Ignore @Test
Jonathan Hart627f10c2013-01-16 14:20:03 -0800154 public void testDeletePortStringString() {
155 fail("Not yet implemented");
156 }
157
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -0800158 @Ignore @Test
Jonathan Hart627f10c2013-01-16 14:20:03 -0800159 public void testGetActiveSwitches() {
160 fail("Not yet implemented");
161 }
Pavlin Radoslavov5185fac2013-01-29 16:40:10 -0800162
163 static class MyLoopFunction implements PipeFunction<LoopBundle<Vertex>, Boolean> {
164 String dpid;
165 public MyLoopFunction(String dpid) {
166 super();
167 this.dpid = dpid;
168 }
169 public Boolean compute(LoopBundle<Vertex> bundle) {
170 Boolean output = false;
Pavlin Radoslavov544d3132013-02-13 10:16:52 -0800171 if (bundle.getObject().getProperty("dpid") != dpid) {
Pavlin Radoslavov5185fac2013-01-29 16:40:10 -0800172 output = true;
173 }
174 return output;
175 }
176 }
177
178 @Test
179 public void testShortestPath() {
180 String dpid_src = "00:00:00:00:00:00:0a:01";
181 String dpid_dest = "00:00:00:00:00:00:0a:06";
182
183 //
184 // Implement the Shortest Path between two vertices by using
Pavlin Radoslavov544d3132013-02-13 10:16:52 -0800185 // the following Gremlin CLI code:
186 // v_src.as("x").out("on").out("link").in("on").dedup().loop("x"){it.object.dpid != v_dest.dpid}.path(){it.dpid}{it.number}{it.number}
187 // The equivalent code used here is:
188 // results = []; v_src.as("x").out("on").out("link").in("on").dedup().loop("x"){it.object.dpid != v_dest.dpid}.path().fill(results)
Pavlin Radoslavov5185fac2013-01-29 16:40:10 -0800189 //
190
Pavlin Radoslavov544d3132013-02-13 10:16:52 -0800191 String gremlin = "v_src.as(\"x\").out(\"on\").out(\"link\").in(\"on\").dedup().loop(\"x\"){it.object.dpid != v_dest.dpid}.path().fill(results)";
192
193 String gremlin_nopath = "v_src.as(\"x\").out(\"on\").out(\"link\").in(\"on\").dedup().loop(\"x\"){it.object.dpid != \"NO-SUCH-DPID\"}.path().fill(results)";
Pavlin Radoslavov5185fac2013-01-29 16:40:10 -0800194
195 // Get the source vertex
196 Iterator<Vertex> iter = titanGraph.getVertices("dpid", dpid_src).iterator();
197 if (! iter.hasNext())
198 return; // Source vertex not found
199 Vertex v_src = iter.next();
200
201 // Get the destination vertex
202 iter = titanGraph.getVertices("dpid", dpid_dest).iterator();
203 if (! iter.hasNext())
204 return; // Destination vertex not found
205 Vertex v_dest = iter.next();
206
207 //
208 // Implement the Gremlin script and run it
209 //
210 ScriptEngine engine = new GremlinGroovyScriptEngine();
211
212 ArrayList<ArrayList<Vertex>> results = new ArrayList<ArrayList<Vertex>>();
213 engine.getBindings(ScriptContext.ENGINE_SCOPE).put("g", titanGraph);
214 engine.getBindings(ScriptContext.ENGINE_SCOPE).put("v_src", v_src);
215 engine.getBindings(ScriptContext.ENGINE_SCOPE).put("v_dest", v_dest);
216 engine.getBindings(ScriptContext.ENGINE_SCOPE).put("results", results);
217
218 try {
219 engine.eval(gremlin);
220 } catch (ScriptException e) {
221 System.err.println("Caught ScriptException running Gremlin script: " + e.getMessage());
222 return;
223 }
224
225 //
226 // Extract the result and compose it into a string
227 //
228 String results_str = "";
229 // System.out.println("BEGIN " + results.size());
230 for (ArrayList<Vertex> lv : results) {
231 // System.out.println(lv);
232 for (Vertex v: lv) {
233 // System.out.println(v);
234 String type = v.getProperty("type").toString();
235 results_str += "[type: " + type;
236 // System.out.println("type: " + type);
237 if (type.equals("port")) {
238 String number = v.getProperty("number").toString();
239 // System.out.println("number: " + number);
240 results_str += " number: " + number + "]";
241 }
242 if (type.equals("switch")) {
243 String dpid = v.getProperty("dpid").toString();
244 // System.out.println("dpid: " + dpid);
245 results_str += " dpid: " + dpid + "]";
246 }
247 }
248 }
249 // System.out.println("END\n");
250 System.out.println(results_str);
251
252 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]";
253
254
255 // Pipe<Vertex, Vertex> pipe = Gremlin.compile(gremlin);
256 // pipe.setStarts(new SingleIterator<Vertex>(v1));
257
258 //
259 // XXX: An alternative (faster?) solution that fails to compile
260 //
261 MyLoopFunction whileFunction = new MyLoopFunction(dpid_dest);
262 GremlinPipeline<Vertex, Vertex> pipe = new GremlinPipeline<Vertex, Vertex>();
Pavlin Radoslavov544d3132013-02-13 10:16:52 -0800263 ArrayList<ArrayList<Vertex>> results2 = new ArrayList<ArrayList<Vertex>>();
264 // TODO: The statement below doesn't compile
265 // pipe.start(v_src).as("x").out("on").out("link").in("on").dedup().loop("x", whileFunction).path().fill(results2);
Pavlin Radoslavov5185fac2013-01-29 16:40:10 -0800266
267 // Check the result
268 assertEquals(results_str, expected_result);
Pavlin Radoslavov544d3132013-02-13 10:16:52 -0800269
270 //
271 // Test Shortest-Path computation to non-existing destination
272 //
273 results.clear();
274 try {
275 engine.eval(gremlin_nopath);
276 } catch (ScriptException e) {
277 System.err.println("Caught ScriptException running Gremlin script: " + e.getMessage());
278 return;
279 }
280 assertTrue(results.size() == 0);
Pavlin Radoslavov5185fac2013-01-29 16:40:10 -0800281 }
Jonathan Hart627f10c2013-01-16 14:20:03 -0800282}