blob: b4a044fb3f14a47e58d0323224747252f620436c [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;
10
Jonathan Hart627f10c2013-01-16 14:20:03 -080011import net.floodlightcontroller.core.ISwitchStorage;
12import net.floodlightcontroller.core.ISwitchStorage.SwitchState;
13
14import org.junit.After;
15import org.junit.Before;
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -080016import org.junit.Ignore;
Jonathan Hart627f10c2013-01-16 14:20:03 -080017import org.junit.Test;
18import org.openflow.protocol.OFPhysicalPort;
19
20import com.thinkaurelius.titan.core.TitanGraph;
Jonathan Hart627f10c2013-01-16 14:20:03 -080021import com.tinkerpop.blueprints.Vertex;
22import com.tinkerpop.gremlin.java.GremlinPipeline;
Pavlin Radoslavov5185fac2013-01-29 16:40:10 -080023import com.tinkerpop.pipes.PipeFunction;
Pavlin Radoslavov5185fac2013-01-29 16:40:10 -080024import com.tinkerpop.pipes.branch.LoopPipe.LoopBundle;
Pavlin Radoslavov5185fac2013-01-29 16:40:10 -080025
26import javax.script.ScriptContext;
27import javax.script.ScriptEngine;
28import javax.script.ScriptException;
29import com.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine;
30
Jonathan Hart627f10c2013-01-16 14:20:03 -080031
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -080032public class SwitchStorageImplTest {
Jonathan Hart627f10c2013-01-16 14:20:03 -080033
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -080034 private ISwitchStorage switchStorage;
35 private TitanGraph titanGraph;
Jonathan Hart627f10c2013-01-16 14:20:03 -080036
37 @Before
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -080038 public void setUp() throws Exception {
Jonathan Hart627f10c2013-01-16 14:20:03 -080039 titanGraph = TestDatabaseManager.getTestDatabase();
40 TestDatabaseManager.populateTestData(titanGraph);
41
42 switchStorage = new TestableSwitchStorageImpl(titanGraph);
43 }
44
45 @After
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -080046 public void tearDown() throws Exception {
47 titanGraph.shutdown();
Jonathan Hart627f10c2013-01-16 14:20:03 -080048 }
49
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -080050 @Ignore @Test
Jonathan Hart627f10c2013-01-16 14:20:03 -080051 public void testUpdate() {
52 fail("Not yet implemented");
53 }
54
55 @Test
56 public void testAddPort() {
57
58 String dpid = "00:00:00:00:00:00:0a:01";
59 short portNumber = 5;
60
61 OFPhysicalPort portToAdd = new OFPhysicalPort();
62 portToAdd.setName("port 5 at SEA switch");
63 portToAdd.setCurrentFeatures(OFPhysicalPort.OFPortFeatures.OFPPF_100MB_FD.getValue());
64 portToAdd.setPortNumber(portNumber);
65
66 switchStorage.addPort(dpid, portToAdd);
67
68 Vertex sw = titanGraph.getVertices("dpid", dpid).iterator().next();
69
70 GremlinPipeline<Vertex, Vertex> pipe = new GremlinPipeline<Vertex, Vertex>();
71 pipe.start(sw).out("on").has("number", portNumber);
72
73 assertTrue(pipe.hasNext());
74 Vertex addedPort = pipe.next();
75 assertFalse(pipe.hasNext());
76
77 assertEquals(addedPort.getProperty("number"), portNumber);
78 }
79
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -080080 @Ignore @Test
Jonathan Hart627f10c2013-01-16 14:20:03 -080081 public void testGetPorts() {
82 fail("Not yet implemented");
83 }
84
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -080085 @Ignore @Test
Jonathan Hart627f10c2013-01-16 14:20:03 -080086 public void testGetPortStringShort() {
87 fail("Not yet implemented");
88 }
89
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -080090 @Ignore @Test
Jonathan Hart627f10c2013-01-16 14:20:03 -080091 public void testGetPortStringString() {
92 fail("Not yet implemented");
93 }
94
95 @Test
96 public void testAddSwitch() {
97 String dpid = "00:00:00:00:00:00:0a:07";
98
99 switchStorage.addSwitch(dpid);
100
101 Iterator<Vertex> it = titanGraph.getVertices("dpid", dpid).iterator();
102 assertTrue(it.hasNext());
103 Vertex addedSwitch = it.next();
104 assertFalse(it.hasNext());
105
106 assertEquals(addedSwitch.getProperty("type"), "switch");
107 assertEquals(addedSwitch.getProperty("dpid"), dpid);
108 assertEquals(addedSwitch.getProperty("state"), SwitchState.ACTIVE.toString());
109 }
110
111
Jonathan Hart627f10c2013-01-16 14:20:03 -0800112 @Test
113 public void testDeleteSwitch() {
114 String dpid = "00:00:00:00:00:00:0a:01";
115
116 switchStorage.deleteSwitch(dpid);
117
118 Iterator<Vertex> it = titanGraph.getVertices("dpid", dpid).iterator();
119 assertFalse(it.hasNext());
120 }
121
Jonathan Hart627f10c2013-01-16 14:20:03 -0800122 @Test
123 public void testDeletePortByPortNum() {
124 //FIXME fails because query for the port is wrong in SwitchStorageImpl
125
126 String dpid = "00:00:00:00:00:00:0a:01";
127 short portNum = 3;
128
129 switchStorage.deletePort(dpid, portNum);
130
131 Vertex sw = titanGraph.getVertices("dpid", dpid).iterator().next();
132
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -0800133 /*
Jonathan Hart627f10c2013-01-16 14:20:03 -0800134 Iterator<Vertex> it = sw.getVertices(Direction.OUT, "on").iterator();
135
136 while (it.hasNext()){
137 System.out.println(it.next());
138 }
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -0800139 */
Jonathan Hart627f10c2013-01-16 14:20:03 -0800140
141 GremlinPipeline<Vertex, Vertex> pipe = new GremlinPipeline<Vertex, Vertex>();
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -0800142 pipe.start(sw).out("on").has("number", portNum);
Jonathan Hart627f10c2013-01-16 14:20:03 -0800143 assertFalse(pipe.hasNext());
144 }
145
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -0800146 @Ignore @Test
Jonathan Hart627f10c2013-01-16 14:20:03 -0800147 public void testDeletePortStringString() {
148 fail("Not yet implemented");
149 }
150
Jonathan Hartd1c5a1c2013-01-23 00:56:14 -0800151 @Ignore @Test
Jonathan Hart627f10c2013-01-16 14:20:03 -0800152 public void testGetActiveSwitches() {
153 fail("Not yet implemented");
154 }
Pavlin Radoslavov5185fac2013-01-29 16:40:10 -0800155
156 static class MyLoopFunction implements PipeFunction<LoopBundle<Vertex>, Boolean> {
157 String dpid;
158 public MyLoopFunction(String dpid) {
159 super();
160 this.dpid = dpid;
161 }
162 public Boolean compute(LoopBundle<Vertex> bundle) {
163 Boolean output = false;
Pavlin Radoslavov544d3132013-02-13 10:16:52 -0800164 if (bundle.getObject().getProperty("dpid") != dpid) {
Pavlin Radoslavov5185fac2013-01-29 16:40:10 -0800165 output = true;
166 }
167 return output;
168 }
169 }
170
171 @Test
172 public void testShortestPath() {
173 String dpid_src = "00:00:00:00:00:00:0a:01";
174 String dpid_dest = "00:00:00:00:00:00:0a:06";
175
176 //
177 // Implement the Shortest Path between two vertices by using
Pavlin Radoslavov544d3132013-02-13 10:16:52 -0800178 // the following Gremlin CLI code:
179 // 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}
180 // The equivalent code used here is:
181 // 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 -0800182 //
183
Pavlin Radoslavov544d3132013-02-13 10:16:52 -0800184 String gremlin = "v_src.as(\"x\").out(\"on\").out(\"link\").in(\"on\").dedup().loop(\"x\"){it.object.dpid != v_dest.dpid}.path().fill(results)";
185
186 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 -0800187
188 // Get the source vertex
189 Iterator<Vertex> iter = titanGraph.getVertices("dpid", dpid_src).iterator();
190 if (! iter.hasNext())
191 return; // Source vertex not found
192 Vertex v_src = iter.next();
193
194 // Get the destination vertex
195 iter = titanGraph.getVertices("dpid", dpid_dest).iterator();
196 if (! iter.hasNext())
197 return; // Destination vertex not found
198 Vertex v_dest = iter.next();
199
200 //
201 // Implement the Gremlin script and run it
202 //
203 ScriptEngine engine = new GremlinGroovyScriptEngine();
204
205 ArrayList<ArrayList<Vertex>> results = new ArrayList<ArrayList<Vertex>>();
206 engine.getBindings(ScriptContext.ENGINE_SCOPE).put("g", titanGraph);
207 engine.getBindings(ScriptContext.ENGINE_SCOPE).put("v_src", v_src);
208 engine.getBindings(ScriptContext.ENGINE_SCOPE).put("v_dest", v_dest);
209 engine.getBindings(ScriptContext.ENGINE_SCOPE).put("results", results);
210
211 try {
212 engine.eval(gremlin);
213 } catch (ScriptException e) {
214 System.err.println("Caught ScriptException running Gremlin script: " + e.getMessage());
215 return;
216 }
217
218 //
219 // Extract the result and compose it into a string
220 //
221 String results_str = "";
222 // System.out.println("BEGIN " + results.size());
223 for (ArrayList<Vertex> lv : results) {
224 // System.out.println(lv);
225 for (Vertex v: lv) {
226 // System.out.println(v);
227 String type = v.getProperty("type").toString();
228 results_str += "[type: " + type;
229 // System.out.println("type: " + type);
230 if (type.equals("port")) {
231 String number = v.getProperty("number").toString();
232 // System.out.println("number: " + number);
233 results_str += " number: " + number + "]";
234 }
235 if (type.equals("switch")) {
236 String dpid = v.getProperty("dpid").toString();
237 // System.out.println("dpid: " + dpid);
238 results_str += " dpid: " + dpid + "]";
239 }
240 }
241 }
242 // System.out.println("END\n");
243 System.out.println(results_str);
244
245 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]";
246
247
248 // Pipe<Vertex, Vertex> pipe = Gremlin.compile(gremlin);
249 // pipe.setStarts(new SingleIterator<Vertex>(v1));
250
251 //
252 // XXX: An alternative (faster?) solution that fails to compile
253 //
Pavlin Radoslavov524d5072013-02-13 10:25:14 -0800254 // MyLoopFunction whileFunction = new MyLoopFunction(dpid_dest);
255 // GremlinPipeline<Vertex, Vertex> pipe = new GremlinPipeline<Vertex, Vertex>();
256 // ArrayList<ArrayList<Vertex>> results2 = new ArrayList<ArrayList<Vertex>>();
Pavlin Radoslavov544d3132013-02-13 10:16:52 -0800257 // TODO: The statement below doesn't compile
258 // 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 -0800259
260 // Check the result
261 assertEquals(results_str, expected_result);
Pavlin Radoslavov544d3132013-02-13 10:16:52 -0800262
263 //
264 // Test Shortest-Path computation to non-existing destination
265 //
266 results.clear();
267 try {
268 engine.eval(gremlin_nopath);
269 } catch (ScriptException e) {
270 System.err.println("Caught ScriptException running Gremlin script: " + e.getMessage());
271 return;
272 }
273 assertTrue(results.size() == 0);
Pavlin Radoslavov5185fac2013-01-29 16:40:10 -0800274 }
Jonathan Hart627f10c2013-01-16 14:20:03 -0800275}