Added topologyNorthbound integration test
[controller.git] / opendaylight / northbound / integrationtest / src / test / java / org / opendaylight / controller / northbound / integrationtest / NorthboundIT.java
1 package org.opendaylight.controller.northbound.integrationtest;
2
3 import org.slf4j.Logger;
4 import org.slf4j.LoggerFactory;
5 import org.osgi.framework.ServiceReference;
6 import org.osgi.framework.Bundle;
7 import javax.inject.Inject;
8
9 import org.junit.Assert;
10 import org.junit.Test;
11 import org.junit.Before;
12 import org.junit.runner.RunWith;
13 import org.ops4j.pax.exam.junit.PaxExam;
14 import org.osgi.framework.BundleContext;
15 import static org.junit.Assert.*;
16 import org.ops4j.pax.exam.junit.Configuration;
17 import static org.ops4j.pax.exam.CoreOptions.*;
18 import org.ops4j.pax.exam.Option;
19 import org.ops4j.pax.exam.util.PathUtils;
20 import java.io.BufferedReader;
21 import java.io.InputStream;
22 import java.io.InputStreamReader;
23 import java.io.OutputStreamWriter;
24 import java.net.HttpURLConnection;
25 import java.net.URL;
26 import java.nio.charset.Charset;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.HashSet;
30 import java.util.List;
31 import java.util.Set;
32
33 import org.apache.commons.codec.binary.Base64;
34
35 import org.codehaus.jettison.json.JSONArray;
36 import org.codehaus.jettison.json.JSONException;
37 import org.codehaus.jettison.json.JSONObject;
38 import org.codehaus.jettison.json.JSONTokener;
39
40 import org.opendaylight.controller.hosttracker.IfIptoHost;
41 import org.opendaylight.controller.sal.core.Bandwidth;
42 import org.opendaylight.controller.sal.core.ConstructionException;
43 import org.opendaylight.controller.sal.core.Edge;
44 import org.opendaylight.controller.sal.core.Latency;
45 import org.opendaylight.controller.sal.core.Node;
46 import org.opendaylight.controller.sal.core.NodeConnector;
47 import org.opendaylight.controller.sal.core.Property;
48 import org.opendaylight.controller.sal.core.State;
49 import org.opendaylight.controller.sal.core.UpdateType;
50 import org.opendaylight.controller.sal.topology.IListenTopoUpdates;
51 import org.opendaylight.controller.sal.topology.TopoEdgeUpdate;
52 import org.opendaylight.controller.switchmanager.IInventoryListener;
53 import org.opendaylight.controller.usermanager.IUserManager;
54
55 @RunWith(PaxExam.class)
56 public class NorthboundIT {
57     private Logger log = LoggerFactory.getLogger(NorthboundIT.class);
58     // get the OSGI bundle context
59     @Inject
60     private BundleContext bc;
61     private IUserManager users = null;
62     private IInventoryListener invtoryListener = null;
63     private IListenTopoUpdates topoUpdates = null;
64
65     private Boolean debugMsg = false;
66
67     private String stateToString(int state) {
68         switch (state) {
69         case Bundle.ACTIVE:
70             return "ACTIVE";
71         case Bundle.INSTALLED:
72             return "INSTALLED";
73         case Bundle.RESOLVED:
74             return "RESOLVED";
75         case Bundle.UNINSTALLED:
76             return "UNINSTALLED";
77         default:
78             return "Not CONVERTED";
79         }
80     }
81
82     @Before
83     public void areWeReady() {
84         assertNotNull(bc);
85         boolean debugit = false;
86         Bundle b[] = bc.getBundles();
87         for (int i = 0; i < b.length; i++) {
88             int state = b[i].getState();
89             if (state != Bundle.ACTIVE && state != Bundle.RESOLVED) {
90                 log.debug("Bundle:" + b[i].getSymbolicName() + " state:" + stateToString(state));
91                 debugit = true;
92             }
93         }
94         if (debugit) {
95             log.debug("Do some debugging because some bundle is " + "unresolved");
96         }
97         // Assert if true, if false we are good to go!
98         assertFalse(debugit);
99
100         ServiceReference r = bc.getServiceReference(IUserManager.class.getName());
101         if (r != null) {
102             this.users = (IUserManager) bc.getService(r);
103         }
104         // If UserManager is null, cannot login to run tests.
105         assertNotNull(this.users);
106
107         r = bc.getServiceReference(IfIptoHost.class.getName());
108         if (r != null) {
109             this.invtoryListener = (IInventoryListener) bc.getService(r);
110         }
111
112         // If inventoryListener is null, cannot run hosttracker tests.
113         assertNotNull(this.invtoryListener);
114
115         r = bc.getServiceReference(IListenTopoUpdates.class.getName());
116         if (r != null) {
117             this.topoUpdates = (IListenTopoUpdates) bc.getService(r);
118         }
119
120         // If topologyManager is null, cannot run topology North tests.
121         assertNotNull(this.topoUpdates);
122
123     }
124
125     // static variable to pass response code from getJsonResult()
126     private static Integer httpResponseCode = null;
127
128     private String getJsonResult(String restUrl) {
129         return getJsonResult(restUrl, "GET", null);
130     }
131
132     private String getJsonResult(String restUrl, String method) {
133         return getJsonResult(restUrl, method, null);
134     }
135
136     private String getJsonResult(String restUrl, String method, String body) {
137         // initialize response code to indicate error
138         httpResponseCode = 400;
139
140         if (debugMsg) {
141             System.out.println("HTTP method: " + method + " url: " + restUrl.toString());
142             if (body != null)
143                 System.out.println("body: " + body);
144         }
145
146         try {
147             URL url = new URL(restUrl);
148             this.users.getAuthorizationList();
149             this.users.authenticate("admin", "admin");
150             String authString = "admin:admin";
151             byte[] authEncBytes = Base64.encodeBase64(authString.getBytes());
152             String authStringEnc = new String(authEncBytes);
153
154             HttpURLConnection connection = (HttpURLConnection) url.openConnection();
155             connection.setRequestMethod(method);
156             connection.setRequestProperty("Authorization", "Basic " + authStringEnc);
157             connection.setRequestProperty("Content-Type", "application/json");
158             connection.setRequestProperty("Accept", "application/json");
159
160             if (body != null) {
161                 connection.setDoOutput(true);
162                 OutputStreamWriter wr = new OutputStreamWriter(connection.getOutputStream());
163                 wr.write(body);
164                 wr.flush();
165             }
166             connection.connect();
167             connection.getContentType();
168
169             // Response code for success should be 2xx
170             httpResponseCode = connection.getResponseCode();
171             if (httpResponseCode > 299)
172                 return httpResponseCode.toString();
173
174             if (debugMsg) {
175                 System.out.println("HTTP response code: " + connection.getResponseCode());
176                 System.out.println("HTTP response message: " + connection.getResponseMessage());
177             }
178
179             InputStream is = connection.getInputStream();
180             BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
181             StringBuilder sb = new StringBuilder();
182             int cp;
183             while ((cp = rd.read()) != -1) {
184                 sb.append((char) cp);
185             }
186             is.close();
187             connection.disconnect();
188             return sb.toString();
189         } catch (Exception e) {
190             return null;
191         }
192     }
193
194     private void testNodeProperties(JSONObject node, Integer nodeId, String nodeType, Integer timestamp,
195             String timestampName, Integer actionsValue, Integer capabilitiesValue, Integer tablesValue,
196             Integer buffersValue) throws JSONException {
197
198         JSONObject nodeInfo = node.getJSONObject("node");
199         Assert.assertEquals(nodeId, (Integer) nodeInfo.getInt("@id"));
200         Assert.assertEquals(nodeType, nodeInfo.getString("@type"));
201
202         JSONObject properties = node.getJSONObject("properties");
203
204         if (timestamp == null || timestampName == null) {
205             Assert.assertFalse(properties.has("timeStamp"));
206         } else {
207             Assert.assertEquals(timestamp, (Integer) properties.getJSONObject("timeStamp").getInt("timestamp"));
208             Assert.assertEquals(timestampName, properties.getJSONObject("timeStamp").getString("timestampName"));
209         }
210         if (actionsValue == null) {
211             Assert.assertFalse(properties.has("actions"));
212         } else {
213             Assert.assertEquals(actionsValue, (Integer) properties.getJSONObject("actions").getInt("actionsValue"));
214         }
215         if (capabilitiesValue == null) {
216             Assert.assertFalse(properties.has("capabilities"));
217         } else {
218             Assert.assertEquals(capabilitiesValue,
219                     (Integer) properties.getJSONObject("capabilities").getInt("capabilitiesValue"));
220         }
221         if (tablesValue == null) {
222             Assert.assertFalse(properties.has("tables"));
223         } else {
224             Assert.assertEquals(tablesValue, (Integer) properties.getJSONObject("tables").getInt("tablesValue"));
225         }
226         if (buffersValue == null) {
227             Assert.assertFalse(properties.has("buffers"));
228         } else {
229             Assert.assertEquals(buffersValue, (Integer) properties.getJSONObject("buffers").getInt("buffersValue"));
230         }
231     }
232
233     private void testNodeConnectorProperties(JSONObject nodeConnectorProperties, Integer ncId, String ncType,
234             Integer nodeId, String nodeType, Integer state, Integer capabilities, Integer bandwidth)
235             throws JSONException {
236
237         JSONObject nodeConnector = nodeConnectorProperties.getJSONObject("nodeconnector");
238         JSONObject node = nodeConnector.getJSONObject("node");
239         JSONObject properties = nodeConnectorProperties.getJSONObject("properties");
240
241         Assert.assertEquals(ncId, (Integer) nodeConnector.getInt("@id"));
242         Assert.assertEquals(ncType, nodeConnector.getString("@type"));
243         Assert.assertEquals(nodeId, (Integer) node.getInt("@id"));
244         Assert.assertEquals(nodeType, node.getString("@type"));
245         if (state == null) {
246             Assert.assertFalse(properties.has("state"));
247         } else {
248             Assert.assertEquals(state, (Integer) properties.getJSONObject("state").getInt("stateValue"));
249         }
250         if (capabilities == null) {
251             Assert.assertFalse(properties.has("capabilities"));
252         } else {
253             Assert.assertEquals(capabilities,
254                     (Integer) properties.getJSONObject("capabilities").getInt("capabilitiesValue"));
255         }
256         if (bandwidth == null) {
257             Assert.assertFalse(properties.has("bandwidth"));
258         } else {
259             Assert.assertEquals(bandwidth, (Integer) properties.getJSONObject("bandwidth").getInt("bandwidthValue"));
260         }
261
262     }
263
264     @Test
265     public void testSubnetsNorthbound() throws JSONException {
266         System.out.println("Starting Subnets JAXB client.");
267         String baseURL = "http://127.0.0.1:8080/controller/nb/v2/subnet/";
268
269         String name1 = "testSubnet1";
270         String subnet1 = "1.1.1.1/24";
271         String name2 = "testSubnet2";
272         String subnet2 = "2.2.2.2/24";
273
274         // Test GET subnets in default container
275         String result = getJsonResult(baseURL + "default");
276         JSONTokener jt = new JSONTokener(result);
277         JSONObject json = new JSONObject(jt);
278         Assert.assertEquals("{}", result);
279
280         // Test GET subnet1 expecting 404
281         result = getJsonResult(baseURL + "default/" + name1);
282         Assert.assertEquals(404, httpResponseCode.intValue());
283
284         // Test POST subnet1
285         String queryParameter = new QueryParameter("subnetName", name1).add("subnet", subnet1).getString();
286         result = getJsonResult(baseURL + "default/" + name1 + queryParameter, "POST");
287         Assert.assertEquals(201, httpResponseCode.intValue());
288
289         // Test GET subnet1
290         result = getJsonResult(baseURL + "default/" + name1);
291         jt = new JSONTokener(result);
292         json = new JSONObject(jt);
293         Assert.assertEquals(200, httpResponseCode.intValue());
294         Assert.assertEquals(name1, json.getString("@name"));
295         Assert.assertEquals(subnet1, json.getString("@subnet"));
296
297         // Test POST subnet2
298         queryParameter = new QueryParameter("subnetName", name2).add("subnet", subnet2).getString();
299         result = getJsonResult(baseURL + "default/" + name2 + queryParameter, "POST");
300         Assert.assertEquals(201, httpResponseCode.intValue());
301
302         // Test GET all subnets in default container
303         result = getJsonResult(baseURL + "default");
304         jt = new JSONTokener(result);
305         json = new JSONObject(jt);
306         JSONArray subnetConfigArray = json.getJSONArray("subnetConfig");
307         JSONObject subnetConfig;
308         Assert.assertEquals(2, subnetConfigArray.length());
309         for (int i = 0; i < subnetConfigArray.length(); i++) {
310             subnetConfig = subnetConfigArray.getJSONObject(i);
311             if (subnetConfig.getString("@name").equals(name1)) {
312                 Assert.assertEquals(subnet1, subnetConfig.getString("@subnet"));
313             } else if (subnetConfig.getString("@name").equals(name2)) {
314                 Assert.assertEquals(subnet2, subnetConfig.getString("@subnet"));
315             } else {
316                 // Unexpected config name
317                 Assert.assertTrue(false);
318             }
319         }
320
321         // Test DELETE subnet1
322         result = getJsonResult(baseURL + "default/" + name1, "DELETE");
323         Assert.assertEquals(200, httpResponseCode.intValue());
324
325         // Test GET deleted subnet1
326         result = getJsonResult(baseURL + "default/" + name1);
327         Assert.assertEquals(404, httpResponseCode.intValue());
328
329     }
330
331     @Test
332     public void testStaticRoutingNorthbound() throws JSONException {
333         System.out.println("Starting StaticRouting JAXB client.");
334         String baseURL = "http://127.0.0.1:8080/controller/nb/v2/staticroute/";
335
336         String name1 = "testRoute1";
337         String prefix1 = "192.168.1.1/24";
338         String nextHop1 = "0.0.0.0";
339         String name2 = "testRoute2";
340         String prefix2 = "192.168.1.1/16";
341         String nextHop2 = "1.1.1.1";
342
343         // Test GET static routes in default container, expecting no results
344         String result = getJsonResult(baseURL + "default");
345         JSONTokener jt = new JSONTokener(result);
346         JSONObject json = new JSONObject(jt);
347         Assert.assertEquals("{}", result);
348
349         // Test insert static route
350         String requestBody = "{\"name\":\"" + name1 + "\", \"prefix\":\"" + prefix1 + "\", \"nextHop\":\"" + nextHop1
351                 + "\"}";
352         result = getJsonResult(baseURL + "default/" + name1, "POST", requestBody);
353         Assert.assertEquals(201, httpResponseCode.intValue());
354
355         requestBody = "{\"name\":\"" + name2 + "\", \"prefix\":\"" + prefix2 + "\", \"nextHop\":\"" + nextHop2 + "\"}";
356         result = getJsonResult(baseURL + "default/" + name2, "POST", requestBody);
357         Assert.assertEquals(201, httpResponseCode.intValue());
358
359         // Test Get all static routes
360         result = getJsonResult(baseURL + "default");
361         jt = new JSONTokener(result);
362         json = new JSONObject(jt);
363         JSONArray staticRoutes = json.getJSONArray("staticRoute");
364         Assert.assertEquals(2, staticRoutes.length());
365         JSONObject route;
366         for (int i = 0; i < staticRoutes.length(); i++) {
367             route = staticRoutes.getJSONObject(i);
368             if (route.getString("name").equals(name1)) {
369                 Assert.assertEquals(prefix1, route.getString("prefix"));
370                 Assert.assertEquals(nextHop1, route.getString("nextHop"));
371             } else if (route.getString("name").equals(name2)) {
372                 Assert.assertEquals(prefix2, route.getString("prefix"));
373                 Assert.assertEquals(nextHop2, route.getString("nextHop"));
374             } else {
375                 // static route has unknown name
376                 Assert.assertTrue(false);
377             }
378         }
379
380         // Test get specific static route
381         result = getJsonResult(baseURL + "default/" + name1);
382         jt = new JSONTokener(result);
383         json = new JSONObject(jt);
384
385         Assert.assertEquals(name1, json.getString("name"));
386         Assert.assertEquals(prefix1, json.getString("prefix"));
387         Assert.assertEquals(nextHop1, json.getString("nextHop"));
388
389         result = getJsonResult(baseURL + "default/" + name2);
390         jt = new JSONTokener(result);
391         json = new JSONObject(jt);
392
393         Assert.assertEquals(name2, json.getString("name"));
394         Assert.assertEquals(prefix2, json.getString("prefix"));
395         Assert.assertEquals(nextHop2, json.getString("nextHop"));
396
397         // Test delete static route
398         result = getJsonResult(baseURL + "default/" + name1, "DELETE");
399         Assert.assertEquals(200, httpResponseCode.intValue());
400
401         result = getJsonResult(baseURL + "default");
402         jt = new JSONTokener(result);
403         json = new JSONObject(jt);
404         JSONObject singleStaticRoute = json.getJSONObject("staticRoute");
405         Assert.assertEquals(name2, singleStaticRoute.getString("name"));
406
407     }
408
409     @Test
410     public void testSwitchManager() throws JSONException {
411         System.out.println("Starting SwitchManager JAXB client.");
412         String baseURL = "http://127.0.0.1:8080/controller/nb/v2/switch/default/";
413
414         // define Node/NodeConnector attributes for test
415         int nodeId_1 = 51966;
416         int nodeId_2 = 3366;
417         int nodeId_3 = 4477;
418         int nodeConnectorId_1 = 51966;
419         int nodeConnectorId_2 = 12;
420         int nodeConnectorId_3 = 34;
421         String nodeType = "STUB";
422         String ncType = "STUB";
423         int timestamp_1 = 100000;
424         String timestampName_1 = "connectedSince";
425         int actionsValue_1 = 2;
426         int capabilitiesValue_1 = 3;
427         int tablesValue_1 = 1;
428         int buffersValue_1 = 1;
429         int ncState = 1;
430         int ncCapabilities = 1;
431         int ncBandwidth = 1000000000;
432
433         // Test GET all nodes
434
435         String result = getJsonResult(baseURL + "nodes");
436         JSONTokener jt = new JSONTokener(result);
437         JSONObject json = new JSONObject(jt);
438
439         // Test for first node
440         JSONObject node = getJsonInstance(json, "nodeProperties", nodeId_1);
441         Assert.assertNotNull(node);
442         testNodeProperties(node, nodeId_1, nodeType, timestamp_1, timestampName_1, actionsValue_1, capabilitiesValue_1,
443                 tablesValue_1, buffersValue_1);
444
445         // Test 2nd node, properties of 2nd node same as first node
446         node = getJsonInstance(json, "nodeProperties", nodeId_2);
447         Assert.assertNotNull(node);
448         testNodeProperties(node, nodeId_2, nodeType, timestamp_1, timestampName_1, actionsValue_1, capabilitiesValue_1,
449                 tablesValue_1, buffersValue_1);
450
451         // Test 3rd node, properties of 3rd node same as first node
452         node = getJsonInstance(json, "nodeProperties", nodeId_3);
453         Assert.assertNotNull(node);
454         testNodeProperties(node, nodeId_3, nodeType, timestamp_1, timestampName_1, actionsValue_1, capabilitiesValue_1,
455                 tablesValue_1, buffersValue_1);
456
457         // Test GET nodeConnectors of a node
458         // Test first node
459         result = getJsonResult(baseURL + "node/STUB/" + nodeId_1);
460         jt = new JSONTokener(result);
461         json = new JSONObject(jt);
462         JSONObject nodeConnectorProperties = json.getJSONObject("nodeConnectorProperties");
463
464         testNodeConnectorProperties(nodeConnectorProperties, nodeConnectorId_1, ncType, nodeId_1, nodeType, ncState,
465                 ncCapabilities, ncBandwidth);
466
467         // Test second node
468         result = getJsonResult(baseURL + "node/STUB/" + nodeId_2);
469         jt = new JSONTokener(result);
470         json = new JSONObject(jt);
471         nodeConnectorProperties = json.getJSONObject("nodeConnectorProperties");
472
473         testNodeConnectorProperties(nodeConnectorProperties, nodeConnectorId_2, ncType, nodeId_2, nodeType, ncState,
474                 ncCapabilities, ncBandwidth);
475
476         // Test third node
477         result = getJsonResult(baseURL + "node/STUB/" + nodeId_3);
478         jt = new JSONTokener(result);
479         json = new JSONObject(jt);
480
481         nodeConnectorProperties = json.getJSONObject("nodeConnectorProperties");
482         testNodeConnectorProperties(nodeConnectorProperties, nodeConnectorId_3, ncType, nodeId_3, nodeType, ncState,
483                 ncCapabilities, ncBandwidth);
484
485         // Test delete node property
486         // Delete timestamp property from node1
487         result = getJsonResult(baseURL + "node/STUB/" + nodeId_1 + "/property/timeStamp", "DELETE");
488         Assert.assertEquals(200, httpResponseCode.intValue());
489
490         // Check node1
491         result = getJsonResult(baseURL + "nodes");
492         jt = new JSONTokener(result);
493         json = new JSONObject(jt);
494         node = getJsonInstance(json, "nodeProperties", nodeId_1);
495         Assert.assertNotNull(node);
496         testNodeProperties(node, nodeId_1, nodeType, null, null, actionsValue_1, capabilitiesValue_1, tablesValue_1,
497                 buffersValue_1);
498
499         // Delete actions property from node2
500         result = getJsonResult(baseURL + "node/STUB/" + nodeId_2 + "/property/actions", "DELETE");
501         Assert.assertEquals(200, httpResponseCode.intValue());
502
503         // Check node2
504         result = getJsonResult(baseURL + "nodes");
505         jt = new JSONTokener(result);
506         json = new JSONObject(jt);
507         node = getJsonInstance(json, "nodeProperties", nodeId_2);
508         Assert.assertNotNull(node);
509         testNodeProperties(node, nodeId_2, nodeType, timestamp_1, timestampName_1, null, capabilitiesValue_1,
510                 tablesValue_1, buffersValue_1);
511
512         // Test add property to node
513         // Add Tier and Bandwidth property to node1
514         result = getJsonResult(baseURL + "node/STUB/" + nodeId_1 + "/property/tier/1001", "PUT");
515         Assert.assertEquals(201, httpResponseCode.intValue());
516         result = getJsonResult(baseURL + "node/STUB/" + nodeId_1 + "/property/bandwidth/1002", "PUT");
517         Assert.assertEquals(201, httpResponseCode.intValue());
518
519         // Test for first node
520         result = getJsonResult(baseURL + "nodes");
521         jt = new JSONTokener(result);
522         json = new JSONObject(jt);
523         node = getJsonInstance(json, "nodeProperties", nodeId_1);
524         Assert.assertNotNull(node);
525         Assert.assertEquals(1001, node.getJSONObject("properties").getJSONObject("tier").getInt("tierValue"));
526         Assert.assertEquals(1002, node.getJSONObject("properties").getJSONObject("bandwidth").getInt("bandwidthValue"));
527
528         // Test delete nodeConnector property
529         // Delete state property of nodeconnector1
530         result = getJsonResult(baseURL + "nodeconnector/STUB/" + nodeId_1 + "/STUB/" + nodeConnectorId_1
531                 + "/property/state", "DELETE");
532         Assert.assertEquals(200, httpResponseCode.intValue());
533
534         result = getJsonResult(baseURL + "node/STUB/" + nodeId_1);
535         jt = new JSONTokener(result);
536         json = new JSONObject(jt);
537         nodeConnectorProperties = json.getJSONObject("nodeConnectorProperties");
538
539         testNodeConnectorProperties(nodeConnectorProperties, nodeConnectorId_1, ncType, nodeId_1, nodeType, null,
540                 ncCapabilities, ncBandwidth);
541
542         // Delete capabilities property of nodeconnector2
543         result = getJsonResult(baseURL + "nodeconnector/STUB/" + nodeId_2 + "/STUB/" + nodeConnectorId_2
544                 + "/property/capabilities", "DELETE");
545         Assert.assertEquals(200, httpResponseCode.intValue());
546
547         result = getJsonResult(baseURL + "node/STUB/" + nodeId_2);
548         jt = new JSONTokener(result);
549         json = new JSONObject(jt);
550         nodeConnectorProperties = json.getJSONObject("nodeConnectorProperties");
551
552         testNodeConnectorProperties(nodeConnectorProperties, nodeConnectorId_2, ncType, nodeId_2, nodeType, ncState,
553                 null, ncBandwidth);
554
555         // Test PUT nodeConnector property
556         int newBandwidth = 1001;
557
558         // Add Name/Bandwidth property to nodeConnector1
559         result = getJsonResult(baseURL + "nodeconnector/STUB/" + nodeId_1 + "/STUB/" + nodeConnectorId_1
560                 + "/property/bandwidth/" + newBandwidth, "PUT");
561         Assert.assertEquals(201, httpResponseCode.intValue());
562
563         result = getJsonResult(baseURL + "node/STUB/" + nodeId_1);
564         jt = new JSONTokener(result);
565         json = new JSONObject(jt);
566         nodeConnectorProperties = json.getJSONObject("nodeConnectorProperties");
567
568         // Check for new bandwidth value, state value removed from previous
569         // test
570         testNodeConnectorProperties(nodeConnectorProperties, nodeConnectorId_1, ncType, nodeId_1, nodeType, null,
571                 ncCapabilities, newBandwidth);
572
573     }
574
575     @Test
576     public void testStatistics() throws JSONException {
577         String actionTypes[] = { "drop", "loopback", "flood", "floodAll", "controller", "swPath", "hwPath", "output",
578                 "setDlSrc", "setDlDst", "setDlType", "setVlanId", "setVlanPcp", "setVlanCfi", "popVlan", "pushVlan",
579                 "setNwSrc", "setNwDst", "setNwTos", "setTpSrc", "setTpDst" };
580         System.out.println("Starting Statistics JAXB client.");
581
582         String baseURL = "http://127.0.0.1:8080/controller/nb/v2/statistics/default/";
583
584         String result = getJsonResult(baseURL + "flowstats");
585         JSONTokener jt = new JSONTokener(result);
586         JSONObject json = new JSONObject(jt);
587         JSONObject flowStatistics = getJsonInstance(json, "flowStatistics", 0xCAFE);
588         JSONObject node = flowStatistics.getJSONObject("node");
589         // test that node was returned properly
590         Assert.assertTrue(node.getInt("@id") == 0xCAFE);
591         Assert.assertEquals(node.getString("@type"), "STUB");
592
593         // test that flow statistics results are correct
594         JSONArray flowStats = flowStatistics.getJSONArray("flowStat");
595         for (int i = 0; i < flowStats.length(); i++) {
596
597             JSONObject flowStat = flowStats.getJSONObject(i);
598             testFlowStat(flowStat, actionTypes[i]);
599
600         }
601
602         // for /controller/nb/v2/statistics/default/portstats
603         result = getJsonResult(baseURL + "portstats");
604         jt = new JSONTokener(result);
605         json = new JSONObject(jt);
606         JSONObject portStatistics = getJsonInstance(json, "portStatistics", 0xCAFE);
607         JSONObject node2 = portStatistics.getJSONObject("node");
608         // test that node was returned properly
609         Assert.assertTrue(node2.getInt("@id") == 0xCAFE);
610         Assert.assertEquals(node2.getString("@type"), "STUB");
611
612         // test that port statistic results are correct
613         JSONObject portStat = portStatistics.getJSONObject("portStat");
614         Assert.assertTrue(portStat.getInt("receivePackets") == 250);
615         Assert.assertTrue(portStat.getInt("transmitPackets") == 500);
616         Assert.assertTrue(portStat.getInt("receiveBytes") == 1000);
617         Assert.assertTrue(portStat.getInt("transmitBytes") == 5000);
618         Assert.assertTrue(portStat.getInt("receiveDrops") == 2);
619         Assert.assertTrue(portStat.getInt("transmitDrops") == 50);
620         Assert.assertTrue(portStat.getInt("receiveErrors") == 3);
621         Assert.assertTrue(portStat.getInt("transmitErrors") == 10);
622         Assert.assertTrue(portStat.getInt("receiveFrameError") == 5);
623         Assert.assertTrue(portStat.getInt("receiveOverRunError") == 6);
624         Assert.assertTrue(portStat.getInt("receiveCrcError") == 1);
625         Assert.assertTrue(portStat.getInt("collisionCount") == 4);
626
627         // test for getting one specific node's stats
628         result = getJsonResult(baseURL + "flowstats/STUB/51966");
629         jt = new JSONTokener(result);
630         json = new JSONObject(jt);
631         node = json.getJSONObject("node");
632         // test that node was returned properly
633         Assert.assertTrue(node.getInt("@id") == 0xCAFE);
634         Assert.assertEquals(node.getString("@type"), "STUB");
635
636         // test that flow statistics results are correct
637         flowStats = json.getJSONArray("flowStat");
638         for (int i = 0; i < flowStats.length(); i++) {
639             JSONObject flowStat = flowStats.getJSONObject(i);
640             testFlowStat(flowStat, actionTypes[i]);
641         }
642
643         result = getJsonResult(baseURL + "portstats/STUB/51966");
644         jt = new JSONTokener(result);
645         json = new JSONObject(jt);
646         node2 = json.getJSONObject("node");
647         // test that node was returned properly
648         Assert.assertTrue(node2.getInt("@id") == 0xCAFE);
649         Assert.assertEquals(node2.getString("@type"), "STUB");
650
651         // test that port statistic results are correct
652         portStat = json.getJSONObject("portStat");
653         Assert.assertTrue(portStat.getInt("receivePackets") == 250);
654         Assert.assertTrue(portStat.getInt("transmitPackets") == 500);
655         Assert.assertTrue(portStat.getInt("receiveBytes") == 1000);
656         Assert.assertTrue(portStat.getInt("transmitBytes") == 5000);
657         Assert.assertTrue(portStat.getInt("receiveDrops") == 2);
658         Assert.assertTrue(portStat.getInt("transmitDrops") == 50);
659         Assert.assertTrue(portStat.getInt("receiveErrors") == 3);
660         Assert.assertTrue(portStat.getInt("transmitErrors") == 10);
661         Assert.assertTrue(portStat.getInt("receiveFrameError") == 5);
662         Assert.assertTrue(portStat.getInt("receiveOverRunError") == 6);
663         Assert.assertTrue(portStat.getInt("receiveCrcError") == 1);
664         Assert.assertTrue(portStat.getInt("collisionCount") == 4);
665     }
666
667     private void testFlowStat(JSONObject flowStat, String actionType) throws JSONException {
668         Assert.assertTrue(flowStat.getInt("tableId") == 1);
669         Assert.assertTrue(flowStat.getInt("durationSeconds") == 40);
670         Assert.assertTrue(flowStat.getInt("durationNanoseconds") == 400);
671         Assert.assertTrue(flowStat.getInt("packetCount") == 200);
672         Assert.assertTrue(flowStat.getInt("byteCount") == 100);
673
674         // test that flow information is correct
675         JSONObject flow = flowStat.getJSONObject("flow");
676         Assert.assertTrue(flow.getInt("priority") == 3500);
677         Assert.assertTrue(flow.getInt("idleTimeout") == 1000);
678         Assert.assertTrue(flow.getInt("hardTimeout") == 2000);
679         Assert.assertTrue(flow.getInt("id") == 12345);
680
681         JSONObject match = (flow.getJSONObject("match").getJSONObject("matchField"));
682         Assert.assertTrue(match.getString("type").equals("NW_DST"));
683         Assert.assertTrue(match.getString("value").equals("1.1.1.1"));
684
685         JSONObject act = flow.getJSONObject("actions");
686         Assert.assertTrue(act.getString("@type").equals(actionType));
687
688         if (act.getString("@type").equals("output")) {
689             JSONObject port = act.getJSONObject("port");
690             JSONObject port_node = port.getJSONObject("node");
691             Assert.assertTrue(port.getInt("@id") == 51966);
692             Assert.assertTrue(port.getString("@type").equals("STUB"));
693             Assert.assertTrue(port_node.getInt("@id") == 51966);
694             Assert.assertTrue(port_node.getString("@type").equals("STUB"));
695         }
696
697         if (act.getString("@type").equals("setDlSrc")) {
698             byte srcMatch[] = { (byte) 5, (byte) 4, (byte) 3, (byte) 2, (byte) 1 };
699             String src = act.getString("address");
700             byte srcBytes[] = new byte[5];
701             srcBytes[0] = Byte.parseByte(src.substring(0, 2));
702             srcBytes[1] = Byte.parseByte(src.substring(2, 4));
703             srcBytes[2] = Byte.parseByte(src.substring(4, 6));
704             srcBytes[3] = Byte.parseByte(src.substring(6, 8));
705             srcBytes[4] = Byte.parseByte(src.substring(8, 10));
706             Assert.assertTrue(Arrays.equals(srcBytes, srcMatch));
707         }
708
709         if (act.getString("@type").equals("setDlDst")) {
710             byte dstMatch[] = { (byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 5 };
711             String dst = act.getString("address");
712             byte dstBytes[] = new byte[5];
713             dstBytes[0] = Byte.parseByte(dst.substring(0, 2));
714             dstBytes[1] = Byte.parseByte(dst.substring(2, 4));
715             dstBytes[2] = Byte.parseByte(dst.substring(4, 6));
716             dstBytes[3] = Byte.parseByte(dst.substring(6, 8));
717             dstBytes[4] = Byte.parseByte(dst.substring(8, 10));
718             Assert.assertTrue(Arrays.equals(dstBytes, dstMatch));
719         }
720         if (act.getString("@type").equals("setDlType"))
721             Assert.assertTrue(act.getInt("dlType") == 10);
722         if (act.getString("@type").equals("setVlanId"))
723             Assert.assertTrue(act.getInt("vlanId") == 2);
724         if (act.getString("@type").equals("setVlanPcp"))
725             Assert.assertTrue(act.getInt("pcp") == 3);
726         if (act.getString("@type").equals("setVlanCfi"))
727             Assert.assertTrue(act.getInt("cfi") == 1);
728
729         if (act.getString("@type").equals("setNwSrc"))
730             Assert.assertTrue(act.getString("address").equals("2.2.2.2"));
731         if (act.getString("@type").equals("setNwDst"))
732             Assert.assertTrue(act.getString("address").equals("1.1.1.1"));
733
734         if (act.getString("@type").equals("pushVlan")) {
735             int head = act.getInt("VlanHeader");
736             // parsing vlan header
737             int id = head & 0xfff;
738             int cfi = (head >> 12) & 0x1;
739             int pcp = (head >> 13) & 0x7;
740             int tag = (head >> 16) & 0xffff;
741             Assert.assertTrue(id == 1234);
742             Assert.assertTrue(cfi == 1);
743             Assert.assertTrue(pcp == 1);
744             Assert.assertTrue(tag == 0x8100);
745         }
746         if (act.getString("@type").equals("setNwTos"))
747             Assert.assertTrue(act.getInt("tos") == 16);
748         if (act.getString("@type").equals("setTpSrc"))
749             Assert.assertTrue(act.getInt("port") == 4201);
750         if (act.getString("@type").equals("setTpDst"))
751             Assert.assertTrue(act.getInt("port") == 8080);
752     }
753
754     @Test
755     public void testFlowProgrammer() throws JSONException {
756         System.out.println("Starting FlowProgrammer JAXB client.");
757         String baseURL = "http://127.0.0.1:8080/controller/nb/v2/flow/default/";
758         // Attempt to get a flow that doesn't exit. Should return 404
759         // status.
760         String result = getJsonResult(baseURL + "STUB/51966/test1", "GET");
761         Assert.assertTrue(result.equals("404"));
762
763         // test add flow1
764         String fc = "{\"dynamic\":\"false\", \"name\":\"test1\", \"node\":{\"@id\":\"51966\",\"@type\":\"STUB\"}, \"actions\":[\"DROP\"]}";
765         result = getJsonResult(baseURL + "STUB/51966/test1", "POST", fc);
766         Assert.assertTrue(httpResponseCode == 201);
767
768         // test get returns flow that was added.
769         result = getJsonResult(baseURL + "STUB/51966/test1", "GET");
770         // check that result came out fine.
771         Assert.assertTrue(httpResponseCode == 200);
772         JSONTokener jt = new JSONTokener(result);
773         JSONObject json = new JSONObject(jt);
774         Assert.assertEquals(json.getString("name"), "test1");
775         Assert.assertEquals(json.getString("actions"), "DROP");
776         Assert.assertEquals(json.getString("installInHw"), "true");
777         JSONObject node = json.getJSONObject("node");
778         Assert.assertEquals(node.getString("@type"), "STUB");
779         Assert.assertEquals(node.getString("@id"), "51966");
780         // test adding same flow again fails due to repeat name..return 409
781         // code
782         result = getJsonResult(baseURL + "STUB/51966/test1", "POST", fc);
783         Assert.assertTrue(result.equals("409"));
784
785         fc = "{\"dynamic\":\"false\", \"name\":\"test2\", \"node\":{\"@id\":\"51966\",\"@type\":\"STUB\"}, \"actions\":[\"DROP\"]}";
786         result = getJsonResult(baseURL + "STUB/51966/test2", "POST", fc);
787         // test should return 500 for error due to same flow being added.
788         Assert.assertTrue(result.equals("500"));
789
790         // add second flow that's different
791         fc = "{\"dynamic\":\"false\", \"name\":\"test2\", \"nwSrc\":\"1.1.1.1\", \"node\":{\"@id\":\"51966\",\"@type\":\"STUB\"}, \"actions\":[\"DROP\"]}";
792         result = getJsonResult(baseURL + "STUB/51966/test2", "POST", fc);
793         Assert.assertTrue(httpResponseCode == 201);
794
795         // check that request returns both flows given node.
796         result = getJsonResult(baseURL + "STUB/51966/", "GET");
797         jt = new JSONTokener(result);
798         json = new JSONObject(jt);
799         Assert.assertTrue(json.get("flowConfig") instanceof JSONArray);
800         JSONArray ja = json.getJSONArray("flowConfig");
801         Integer count = ja.length();
802         Assert.assertTrue(count == 2);
803
804         // check that request returns both flows given just container.
805         result = getJsonResult(baseURL);
806         jt = new JSONTokener(result);
807         json = new JSONObject(jt);
808         Assert.assertTrue(json.get("flowConfig") instanceof JSONArray);
809         ja = json.getJSONArray("flowConfig");
810         count = ja.length();
811         Assert.assertTrue(count == 2);
812
813         // delete a flow, check that it's no longer in list.
814         result = getJsonResult(baseURL + "STUB/51966/test2", "DELETE");
815         Assert.assertTrue(httpResponseCode == 200);
816
817         result = getJsonResult(baseURL + "STUB/51966/test2", "GET");
818         Assert.assertTrue(result.equals("404"));
819     }
820
821     // method to extract a JSONObject with specified node ID from a JSONObject
822     // that may contain an array of JSONObjects
823     // This is specifically written for statistics manager northbound REST
824     // interface
825     // array_name should be either "flowStatistics" or "portStatistics"
826     private JSONObject getJsonInstance(JSONObject json, String array_name, Integer nodeId) throws JSONException {
827         JSONObject result = null;
828         if (json.get(array_name) instanceof JSONArray) {
829             JSONArray json_array = json.getJSONArray(array_name);
830             for (int i = 0; i < json_array.length(); i++) {
831                 result = json_array.getJSONObject(i);
832                 Integer nid = result.getJSONObject("node").getInt("@id");
833                 if (nid.equals(nodeId))
834                     break;
835             }
836         } else {
837             result = json.getJSONObject(array_name);
838             Integer nid = result.getJSONObject("node").getInt("@id");
839             if (!nid.equals(nodeId))
840                 result = null;
841         }
842         return result;
843     }
844
845     // a class to construct query parameter for HTTP request
846     private class QueryParameter {
847         StringBuilder queryString = null;
848
849         // constructor
850         QueryParameter(String key, String value) {
851             queryString = new StringBuilder();
852             queryString.append("?").append(key).append("=").append(value);
853         }
854
855         // method to add more query parameter
856         QueryParameter add(String key, String value) {
857             this.queryString.append("&").append(key).append("=").append(value);
858             return this;
859         }
860
861         // method to get the query parameter string
862         String getString() {
863             return this.queryString.toString();
864         }
865
866     }
867
868     @Test
869     public void testHostTracker() throws JSONException {
870
871         System.out.println("Starting HostTracker JAXB client.");
872
873         // setup 2 host models for @POST method
874         // 1st host
875         String networkAddress_1 = "192.168.0.8";
876         String dataLayerAddress_1 = "11:22:33:44:55:66";
877         String nodeType_1 = "STUB";
878         Integer nodeId_1 = 3366;
879         String nodeConnectorType_1 = "STUB";
880         Integer nodeConnectorId_1 = 12;
881         String vlan_1 = "4";
882
883         // 2nd host
884         String networkAddress_2 = "10.1.1.1";
885         String dataLayerAddress_2 = "1A:2B:3C:4D:5E:6F";
886         String nodeType_2 = "STUB";
887         Integer nodeId_2 = 4477;
888         String nodeConnectorType_2 = "STUB";
889         Integer nodeConnectorId_2 = 34;
890         String vlan_2 = "0";
891
892         String baseURL = "http://127.0.0.1:8080/controller/nb/v2/host/default";
893
894         // test POST method: addHost()
895         String queryParameter = new QueryParameter("dataLayerAddress", dataLayerAddress_1).add("nodeType", nodeType_1)
896                 .add("nodeId", nodeId_1.toString()).add("nodeConnectorType", nodeConnectorType_1)
897                 .add("nodeConnectorId", nodeConnectorId_1.toString()).add("vlan", vlan_1).getString();
898
899         String result = getJsonResult(baseURL + "/" + networkAddress_1 + queryParameter, "POST");
900         Assert.assertTrue(httpResponseCode == 201);
901
902         // vlan is not passed through query parameter but should be
903         // defaulted to "0"
904         queryParameter = new QueryParameter("dataLayerAddress", dataLayerAddress_2).add("nodeType", nodeType_2)
905                 .add("nodeId", nodeId_2.toString()).add("nodeConnectorType", nodeConnectorType_2)
906                 .add("nodeConnectorId", nodeConnectorId_2.toString()).getString();
907
908         result = getJsonResult(baseURL + "/" + networkAddress_2 + queryParameter, "POST");
909         Assert.assertTrue(httpResponseCode == 201);
910
911         // define variables for decoding returned strings
912         String networkAddress;
913         JSONObject host_jo, dl_jo, nc_jo, node_jo;
914
915         // the two hosts should be in inactive host DB
916         // test GET method: getInactiveHosts()
917         result = getJsonResult(baseURL + "/inactive", "GET");
918         Assert.assertTrue(httpResponseCode == 200);
919
920         JSONTokener jt = new JSONTokener(result);
921         JSONObject json = new JSONObject(jt);
922         // there should be at least two hosts in the DB
923         Assert.assertTrue(json.get("host") instanceof JSONArray);
924         JSONArray ja = json.getJSONArray("host");
925         Integer count = ja.length();
926         Assert.assertTrue(count == 2);
927
928         for (int i = 0; i < count; i++) {
929             host_jo = ja.getJSONObject(i);
930             dl_jo = host_jo.getJSONObject("dataLayerAddress");
931             nc_jo = host_jo.getJSONObject("nodeConnector");
932             node_jo = nc_jo.getJSONObject("node");
933
934             networkAddress = host_jo.getString("networkAddress");
935             if (networkAddress.equalsIgnoreCase(networkAddress_1)) {
936                 Assert.assertTrue(dl_jo.getString("macAddress").equalsIgnoreCase(dataLayerAddress_1));
937                 Assert.assertTrue(nc_jo.getString("@type").equalsIgnoreCase(nodeConnectorType_1));
938                 Assert.assertTrue(nc_jo.getInt("@id") == nodeConnectorId_1);
939                 Assert.assertTrue(node_jo.getString("@type").equalsIgnoreCase(nodeType_1));
940                 Assert.assertTrue(node_jo.getInt("@id") == nodeId_1);
941                 Assert.assertTrue(host_jo.getString("vlan").equalsIgnoreCase(vlan_1));
942             } else if (networkAddress.equalsIgnoreCase(networkAddress_2)) {
943                 Assert.assertTrue(dl_jo.getString("macAddress").equalsIgnoreCase(dataLayerAddress_2));
944                 Assert.assertTrue(nc_jo.getString("@type").equalsIgnoreCase(nodeConnectorType_2));
945                 Assert.assertTrue(nc_jo.getInt("@id") == nodeConnectorId_2);
946                 Assert.assertTrue(node_jo.getString("@type").equalsIgnoreCase(nodeType_2));
947                 Assert.assertTrue(node_jo.getInt("@id") == nodeId_2);
948                 Assert.assertTrue(host_jo.getString("vlan").equalsIgnoreCase(vlan_2));
949             } else {
950                 Assert.assertTrue(false);
951             }
952         }
953
954         // test GET method: getActiveHosts() - no host expected
955         result = getJsonResult(baseURL, "GET");
956         Assert.assertTrue(httpResponseCode == 200);
957
958         jt = new JSONTokener(result);
959         json = new JSONObject(jt);
960         Assert.assertFalse(hostInJson(json, networkAddress_1));
961         Assert.assertFalse(hostInJson(json, networkAddress_2));
962
963         // put the 1st host into active host DB
964         Node nd;
965         NodeConnector ndc;
966         try {
967             nd = new Node(nodeType_1, nodeId_1);
968             ndc = new NodeConnector(nodeConnectorType_1, nodeConnectorId_1, nd);
969             this.invtoryListener.notifyNodeConnector(ndc, UpdateType.ADDED, null);
970         } catch (ConstructionException e) {
971             ndc = null;
972             nd = null;
973         }
974
975         // verify the host shows up in active host DB
976
977         result = getJsonResult(baseURL, "GET");
978         Assert.assertTrue(httpResponseCode == 200);
979
980         jt = new JSONTokener(result);
981         json = new JSONObject(jt);
982
983         Assert.assertTrue(hostInJson(json, networkAddress_1));
984
985         // test GET method for getHostDetails()
986
987         result = getJsonResult(baseURL + "/" + networkAddress_1, "GET");
988         Assert.assertTrue(httpResponseCode == 200);
989
990         jt = new JSONTokener(result);
991         json = new JSONObject(jt);
992
993         Assert.assertFalse(json.length() == 0);
994
995         dl_jo = json.getJSONObject("dataLayerAddress");
996         nc_jo = json.getJSONObject("nodeConnector");
997         node_jo = nc_jo.getJSONObject("node");
998
999         Assert.assertTrue(json.getString("networkAddress").equalsIgnoreCase(networkAddress_1));
1000         Assert.assertTrue(dl_jo.getString("macAddress").equalsIgnoreCase(dataLayerAddress_1));
1001         Assert.assertTrue(nc_jo.getString("@type").equalsIgnoreCase(nodeConnectorType_1));
1002         Assert.assertTrue(Integer.parseInt(nc_jo.getString("@id")) == nodeConnectorId_1);
1003         Assert.assertTrue(node_jo.getString("@type").equalsIgnoreCase(nodeType_1));
1004         Assert.assertTrue(Integer.parseInt(node_jo.getString("@id")) == nodeId_1);
1005         Assert.assertTrue(json.getString("vlan").equalsIgnoreCase(vlan_1));
1006
1007         // test DELETE method for deleteFlow()
1008
1009         result = getJsonResult(baseURL + "/" + networkAddress_1, "DELETE");
1010         Assert.assertTrue(httpResponseCode == 200);
1011
1012         // verify host_1 removed from active host DB
1013         // test GET method: getActiveHosts() - no host expected
1014
1015         result = getJsonResult(baseURL, "GET");
1016         Assert.assertTrue(httpResponseCode == 200);
1017
1018         jt = new JSONTokener(result);
1019         json = new JSONObject(jt);
1020
1021         Assert.assertFalse(hostInJson(json, networkAddress_1));
1022
1023     }
1024
1025     private Boolean hostInJson(JSONObject json, String hostIp) throws JSONException {
1026         // input JSONObject may be empty
1027         if (json.length() == 0) {
1028             return false;
1029         }
1030         if (json.get("host") instanceof JSONArray) {
1031             JSONArray ja = json.getJSONArray("host");
1032             for (int i = 0; i < ja.length(); i++) {
1033                 String na = ja.getJSONObject(i).getString("networkAddress");
1034                 if (na.equalsIgnoreCase(hostIp))
1035                     return true;
1036             }
1037             return false;
1038         } else {
1039             String na = json.getJSONObject("host").getString("networkAddress");
1040             return (na.equalsIgnoreCase(hostIp)) ? true : false;
1041         }
1042     }
1043
1044     @Test
1045     public void testTopology() throws JSONException, ConstructionException {
1046         System.out.println("Starting Topology JAXB client.");
1047         String baseURL = "http://127.0.0.1:8080/controller/nb/v2/topology/default";
1048
1049         // === test GET method for getTopology()
1050         short state_1 = State.EDGE_UP, state_2 = State.EDGE_DOWN;
1051         long bw_1 = Bandwidth.BW10Gbps, bw_2 = Bandwidth.BW100Mbps;
1052         long lat_1 = Latency.LATENCY100ns, lat_2 = Latency.LATENCY1ms;
1053         String nodeType = "STUB";
1054         String nodeConnType = "STUB";
1055         int headNC1_nodeId = 1, headNC1_nodeConnId = 11;
1056         int tailNC1_nodeId = 2, tailNC1_nodeConnId = 22;
1057         int headNC2_nodeId = 2, headNC2_nodeConnId = 21;
1058         int tailNC2_nodeId = 1, tailNC2_nodeConnId = 12;
1059
1060         List<TopoEdgeUpdate> topoedgeupdateList = new ArrayList<TopoEdgeUpdate>();
1061         NodeConnector headnc1 = new NodeConnector(nodeConnType, headNC1_nodeConnId, new Node(nodeType, headNC1_nodeId));
1062         NodeConnector tailnc1 = new NodeConnector(nodeConnType, tailNC1_nodeConnId, new Node(nodeType, tailNC1_nodeId));
1063         Edge e1 = new Edge(tailnc1, headnc1);
1064         Set<Property> props_1 = new HashSet<Property>();
1065         props_1.add(new State(state_1));
1066         props_1.add(new Bandwidth(bw_1));
1067         props_1.add(new Latency(lat_1));
1068         TopoEdgeUpdate teu1 = new TopoEdgeUpdate(e1, props_1, UpdateType.ADDED);
1069         topoedgeupdateList.add(teu1);
1070
1071         NodeConnector headnc2 = new NodeConnector(nodeConnType, headNC2_nodeConnId, new Node(nodeType, headNC2_nodeId));
1072         NodeConnector tailnc2 = new NodeConnector(nodeConnType, tailNC2_nodeConnId, new Node(nodeType, tailNC2_nodeId));
1073         Edge e2 = new Edge(tailnc2, headnc2);
1074         Set<Property> props_2 = new HashSet<Property>();
1075         props_2.add(new State(state_2));
1076         props_2.add(new Bandwidth(bw_2));
1077         props_2.add(new Latency(lat_2));
1078
1079         TopoEdgeUpdate teu2 = new TopoEdgeUpdate(e2, props_2, UpdateType.ADDED);
1080         topoedgeupdateList.add(teu2);
1081
1082         topoUpdates.edgeUpdate(topoedgeupdateList);
1083
1084         // HTTP request
1085         String result = getJsonResult(baseURL, "GET");
1086         Assert.assertTrue(httpResponseCode == 200);
1087         if (debugMsg) {
1088             System.out.println("Get Topology: " + result);
1089         }
1090
1091         // returned data must be an array of edges
1092         JSONTokener jt = new JSONTokener(result);
1093         JSONObject json = new JSONObject(jt);
1094         Assert.assertTrue(json.get("edgeProperties") instanceof JSONArray);
1095         JSONArray ja = json.getJSONArray("edgeProperties");
1096
1097         for (int i = 0; i < ja.length(); i++) {
1098             JSONObject edgeProp = ja.getJSONObject(i);
1099             JSONObject edge = edgeProp.getJSONObject("edge");
1100             JSONObject tailNC = edge.getJSONObject("tailNodeConnector");
1101             JSONObject tailNode = tailNC.getJSONObject("node");
1102
1103             JSONObject headNC = edge.getJSONObject("headNodeConnector");
1104             JSONObject headNode = headNC.getJSONObject("node");
1105             JSONObject Props = edgeProp.getJSONObject("properties");
1106             JSONObject bandw = Props.getJSONObject("bandwidth");
1107             JSONObject stt = Props.getJSONObject("state");
1108             JSONObject ltc = Props.getJSONObject("latency");
1109
1110             if (headNC.getInt("@id") == headNC1_nodeConnId) {
1111                 Assert.assertEquals(headNode.getString("@type"), nodeType);
1112                 Assert.assertEquals(headNode.getLong("@id"), headNC1_nodeId);
1113                 Assert.assertEquals(headNC.getString("@type"), nodeConnType);
1114                 Assert.assertEquals(tailNode.getString("@type"),nodeType);
1115                 Assert.assertEquals(tailNode.getString("@type"), nodeConnType);
1116                 Assert.assertEquals(tailNC.getLong("@id"), tailNC1_nodeConnId);
1117                 Assert.assertEquals(bandw.getLong("bandwidthValue"), bw_1);
1118                 Assert.assertTrue((short) stt.getInt("stateValue") == state_1);
1119                 Assert.assertEquals(ltc.getLong("latencyValue"), lat_1);
1120             } else if (headNC.getInt("@id") == headNC2_nodeConnId) {
1121                 Assert.assertEquals(headNode.getString("@type"),nodeType);
1122                 Assert.assertEquals(headNode.getLong("@id"), headNC2_nodeId);
1123                 Assert.assertEquals(headNC.getString("@type"), nodeConnType);
1124                 Assert.assertEquals(tailNode.getString("@type"), nodeType);
1125                 Assert.assertTrue(tailNode.getInt("@id") == tailNC2_nodeId);
1126                 Assert.assertEquals(tailNC.getString("@type"), nodeConnType);
1127                 Assert.assertEquals(tailNC.getLong("@id"), tailNC2_nodeConnId);
1128                 Assert.assertEquals(bandw.getLong("bandwidthValue"), bw_2);
1129                 Assert.assertTrue((short) stt.getInt("stateValue") == state_2);
1130                 Assert.assertEquals(ltc.getLong("latencyValue"), lat_2);
1131             }
1132         }
1133
1134         // === test POST method for addUserLink()
1135         // define 2 sample nodeConnectors for user link configuration tests
1136         String nodeType_1 = "STUB";
1137         Integer nodeId_1 = 3366;
1138         String nodeConnectorType_1 = "STUB";
1139         Integer nodeConnectorId_1 = 12;
1140
1141         String nodeType_2 = "STUB";
1142         Integer nodeId_2 = 4477;
1143         String nodeConnectorType_2 = "STUB";
1144         Integer nodeConnectorId_2 = 34;
1145
1146         JSONObject jo = new JSONObject()
1147                 .append("name", "userLink_1")
1148                 .append("srcNodeConnector",
1149                         nodeConnectorType_1 + "|" + nodeConnectorId_1 + "@" + nodeType_1 + "|" + nodeId_1)
1150                 .append("dstNodeConnector",
1151                         nodeConnectorType_2 + "|" + nodeConnectorId_2 + "@" + nodeType_2 + "|" + nodeId_2);
1152         // execute HTTP request and verify response code
1153         result = getJsonResult(baseURL + "/userLink", "POST", jo.toString());
1154         Assert.assertTrue(httpResponseCode == 201);
1155
1156         // === test GET method for getUserLinks()
1157         result = getJsonResult(baseURL + "/userLink", "GET");
1158         Assert.assertTrue(httpResponseCode == 200);
1159         if (debugMsg) {
1160             System.out.println("result:" + result);
1161         }
1162
1163         jt = new JSONTokener(result);
1164         json = new JSONObject(jt);
1165
1166         // should have at least one object returned
1167         Assert.assertFalse(json.length() == 0);
1168         JSONObject userlink = new JSONObject();
1169
1170         if (json.get("userLinks") instanceof JSONArray) {
1171             ja = json.getJSONArray("userLinks");
1172             int i;
1173             for (i = 0; i < ja.length(); i++) {
1174                 userlink = ja.getJSONObject(i);
1175                 if (userlink.getString("name").equalsIgnoreCase("userLink_1"))
1176                     break;
1177             }
1178             Assert.assertFalse(i == ja.length());
1179         } else {
1180             userlink = json.getJSONObject("userLinks");
1181             Assert.assertTrue(userlink.getString("name").equalsIgnoreCase("userLink_1"));
1182         }
1183
1184         String[] level_1, level_2;
1185         level_1 = userlink.getString("srcNodeConnector").split("\\@");
1186         level_2 = level_1[0].split("\\|");
1187         Assert.assertTrue(level_2[0].equalsIgnoreCase(nodeConnectorType_1));
1188         Assert.assertTrue(Integer.parseInt(level_2[1]) == nodeConnectorId_1);
1189         level_2 = level_1[1].split("\\|");
1190         Assert.assertTrue(level_2[0].equalsIgnoreCase(nodeType_1));
1191         Assert.assertTrue(Integer.parseInt(level_2[1]) == nodeId_1);
1192         level_1 = userlink.getString("dstNodeConnector").split("\\@");
1193         level_2 = level_1[0].split("\\|");
1194         Assert.assertTrue(level_2[0].equalsIgnoreCase(nodeConnectorType_2));
1195         Assert.assertTrue(Integer.parseInt(level_2[1]) == nodeConnectorId_2);
1196         level_2 = level_1[1].split("\\|");
1197         Assert.assertTrue(level_2[0].equalsIgnoreCase(nodeType_2));
1198         Assert.assertTrue(Integer.parseInt(level_2[1]) == nodeId_2);
1199
1200         // === test DELETE method for deleteUserLink()
1201         String userName = "userLink_1";
1202         result = getJsonResult(baseURL + "/userLink/" + userName, "DELETE");
1203         Assert.assertTrue(httpResponseCode == 200);
1204
1205         // execute another getUserLinks() request to verify that userLink_1 is
1206         // removed
1207         result = getJsonResult(baseURL + "/userLink", "GET");
1208         Assert.assertTrue(httpResponseCode == 200);
1209         if (debugMsg) {
1210             System.out.println("result:" + result);
1211         }
1212         jt = new JSONTokener(result);
1213         json = new JSONObject(jt);
1214
1215         if (json.length() != 0) {
1216             if (json.get("userLinks") instanceof JSONArray) {
1217                 ja = json.getJSONArray("userLinks");
1218                 for (int i = 0; i < ja.length(); i++) {
1219                     userlink = ja.getJSONObject(i);
1220                     Assert.assertFalse(userlink.getString("name").equalsIgnoreCase("userLink_1"));
1221                 }
1222             } else {
1223                 userlink = json.getJSONObject("userLinks");
1224                 Assert.assertFalse(userlink.getString("name").equalsIgnoreCase("userLink_1"));
1225             }
1226         }
1227     }
1228
1229     // Configure the OSGi container
1230     @Configuration
1231     public Option[] config() {
1232         return options(
1233                 //
1234                 systemProperty("logback.configurationFile").value(
1235                         "file:" + PathUtils.getBaseDir() + "/src/test/resources/logback.xml"),
1236                 // To start OSGi console for inspection remotely
1237                 systemProperty("osgi.console").value("2401"),
1238                 systemProperty("org.eclipse.gemini.web.tomcat.config.path").value(
1239                         PathUtils.getBaseDir() + "/src/test/resources/tomcat-server.xml"),
1240
1241                 // setting default level. Jersey bundles will need to be started
1242                 // earlier.
1243                 systemProperty("osgi.bundles.defaultStartLevel").value("4"),
1244
1245                 // Set the systemPackages (used by clustering)
1246                 systemPackages("sun.reflect", "sun.reflect.misc", "sun.misc"),
1247                 mavenBundle("javax.servlet", "servlet-api", "2.5"),
1248
1249                 mavenBundle("org.slf4j", "jcl-over-slf4j", "1.7.2"),
1250                 mavenBundle("org.slf4j", "slf4j-api", "1.7.2"),
1251                 mavenBundle("org.slf4j", "log4j-over-slf4j", "1.7.2"),
1252                 mavenBundle("ch.qos.logback", "logback-core", "1.0.9"),
1253                 mavenBundle("ch.qos.logback", "logback-classic", "1.0.9"),
1254                 mavenBundle("org.apache.commons", "commons-lang3", "3.1"),
1255                 mavenBundle("org.apache.felix", "org.apache.felix.dependencymanager", "3.1.0"),
1256
1257                 // the plugin stub to get data for the tests
1258                 mavenBundle("org.opendaylight.controller", "protocol_plugins.stub", "0.4.0-SNAPSHOT"),
1259
1260                 // List all the opendaylight modules
1261                 mavenBundle("org.opendaylight.controller", "security", "0.4.0-SNAPSHOT").noStart(),
1262                 mavenBundle("org.opendaylight.controller", "sal", "0.5.0-SNAPSHOT"),
1263                 mavenBundle("org.opendaylight.controller", "sal.implementation", "0.4.0-SNAPSHOT"),
1264                 mavenBundle("org.opendaylight.controller", "statisticsmanager", "0.4.0-SNAPSHOT"),
1265                 mavenBundle("org.opendaylight.controller", "statisticsmanager.implementation", "0.4.0-SNAPSHOT"),
1266                 mavenBundle("org.opendaylight.controller", "containermanager", "0.4.0-SNAPSHOT"),
1267                 mavenBundle("org.opendaylight.controller", "containermanager.implementation", "0.4.0-SNAPSHOT"),
1268                 mavenBundle("org.opendaylight.controller", "forwardingrulesmanager", "0.4.0-SNAPSHOT"),
1269                 mavenBundle("org.opendaylight.controller", "forwardingrulesmanager.implementation", "0.4.0-SNAPSHOT"),
1270                 mavenBundle("org.opendaylight.controller", "arphandler", "0.4.0-SNAPSHOT"),
1271                 mavenBundle("org.opendaylight.controller", "clustering.services", "0.4.0-SNAPSHOT"),
1272                 mavenBundle("org.opendaylight.controller", "clustering.services-implementation", "0.4.0-SNAPSHOT"),
1273                 mavenBundle("org.opendaylight.controller", "switchmanager", "0.4.0-SNAPSHOT"),
1274                 mavenBundle("org.opendaylight.controller", "switchmanager.implementation", "0.4.0-SNAPSHOT"),
1275                 mavenBundle("org.opendaylight.controller", "configuration", "0.4.0-SNAPSHOT"),
1276                 mavenBundle("org.opendaylight.controller", "configuration.implementation", "0.4.0-SNAPSHOT"),
1277                 mavenBundle("org.opendaylight.controller", "hosttracker", "0.4.0-SNAPSHOT"),
1278                 mavenBundle("org.opendaylight.controller", "hosttracker.implementation", "0.4.0-SNAPSHOT"),
1279                 mavenBundle("org.opendaylight.controller", "arphandler", "0.4.0-SNAPSHOT"),
1280                 mavenBundle("org.opendaylight.controller", "routing.dijkstra_implementation", "0.4.0-SNAPSHOT"),
1281                 mavenBundle("org.opendaylight.controller", "topologymanager", "0.4.0-SNAPSHOT"),
1282
1283                 mavenBundle("org.opendaylight.controller", "usermanager", "0.4.0-SNAPSHOT"),
1284                 mavenBundle("org.opendaylight.controller", "usermanager.implementation", "0.4.0-SNAPSHOT"),
1285                 mavenBundle("org.opendaylight.controller", "logging.bridge", "0.4.0-SNAPSHOT"),
1286                 mavenBundle("org.opendaylight.controller", "clustering.test", "0.4.0-SNAPSHOT"),
1287
1288                 mavenBundle("org.opendaylight.controller", "forwarding.staticrouting", "0.4.0-SNAPSHOT"),
1289
1290                 // Northbound bundles
1291                 mavenBundle("org.opendaylight.controller", "commons.northbound", "0.4.0-SNAPSHOT"),
1292                 mavenBundle("org.opendaylight.controller", "forwarding.staticrouting.northbound", "0.4.0-SNAPSHOT"),
1293                 mavenBundle("org.opendaylight.controller", "statistics.northbound", "0.4.0-SNAPSHOT"),
1294                 mavenBundle("org.opendaylight.controller", "topology.northbound", "0.4.0-SNAPSHOT"),
1295                 mavenBundle("org.opendaylight.controller", "hosttracker.northbound", "0.4.0-SNAPSHOT"),
1296                 mavenBundle("org.opendaylight.controller", "switchmanager.northbound", "0.4.0-SNAPSHOT"),
1297                 mavenBundle("org.opendaylight.controller", "flowprogrammer.northbound", "0.4.0-SNAPSHOT"),
1298                 mavenBundle("org.opendaylight.controller", "subnets.northbound", "0.4.0-SNAPSHOT"),
1299
1300                 mavenBundle("org.codehaus.jackson", "jackson-mapper-asl", "1.9.8"),
1301                 mavenBundle("org.codehaus.jackson", "jackson-core-asl", "1.9.8"),
1302                 mavenBundle("org.codehaus.jackson", "jackson-jaxrs", "1.9.8"),
1303                 mavenBundle("org.codehaus.jettison", "jettison", "1.3.3"),
1304
1305                 mavenBundle("commons-io", "commons-io", "2.3"),
1306
1307                 mavenBundle("commons-fileupload", "commons-fileupload", "1.2.2"),
1308
1309                 mavenBundle("equinoxSDK381", "javax.servlet", "3.0.0.v201112011016"),
1310                 mavenBundle("equinoxSDK381", "javax.servlet.jsp", "2.2.0.v201112011158"),
1311                 mavenBundle("equinoxSDK381", "org.eclipse.equinox.ds", "1.4.0.v20120522-1841"),
1312                 mavenBundle("orbit", "javax.xml.rpc", "1.1.0.v201005080400"),
1313                 mavenBundle("equinoxSDK381", "org.eclipse.equinox.util", "1.0.400.v20120522-2049"),
1314                 mavenBundle("equinoxSDK381", "org.eclipse.osgi.services", "3.3.100.v20120522-1822"),
1315                 mavenBundle("equinoxSDK381", "org.apache.felix.gogo.command", "0.8.0.v201108120515"),
1316                 mavenBundle("equinoxSDK381", "org.apache.felix.gogo.runtime", "0.8.0.v201108120515"),
1317                 mavenBundle("equinoxSDK381", "org.apache.felix.gogo.shell", "0.8.0.v201110170705"),
1318                 mavenBundle("equinoxSDK381", "org.eclipse.equinox.cm", "1.0.400.v20120522-1841"),
1319                 mavenBundle("equinoxSDK381", "org.eclipse.equinox.console", "1.0.0.v20120522-1841"),
1320                 mavenBundle("equinoxSDK381", "org.eclipse.equinox.launcher", "1.3.0.v20120522-1813"),
1321
1322                 mavenBundle("geminiweb", "org.eclipse.gemini.web.core", "2.2.0.RELEASE"),
1323                 mavenBundle("geminiweb", "org.eclipse.gemini.web.extender", "2.2.0.RELEASE"),
1324                 mavenBundle("geminiweb", "org.eclipse.gemini.web.tomcat", "2.2.0.RELEASE"),
1325                 mavenBundle("geminiweb", "org.eclipse.virgo.kernel.equinox.extensions", "3.6.0.RELEASE").noStart(),
1326                 mavenBundle("geminiweb", "org.eclipse.virgo.util.common", "3.6.0.RELEASE"),
1327                 mavenBundle("geminiweb", "org.eclipse.virgo.util.io", "3.6.0.RELEASE"),
1328                 mavenBundle("geminiweb", "org.eclipse.virgo.util.math", "3.6.0.RELEASE"),
1329                 mavenBundle("geminiweb", "org.eclipse.virgo.util.osgi", "3.6.0.RELEASE"),
1330                 mavenBundle("geminiweb", "org.eclipse.virgo.util.osgi.manifest", "3.6.0.RELEASE"),
1331                 mavenBundle("geminiweb", "org.eclipse.virgo.util.parser.manifest", "3.6.0.RELEASE"),
1332
1333                 mavenBundle("org.apache.felix", "org.apache.felix.dependencymanager", "3.1.0"),
1334                 mavenBundle("org.apache.felix", "org.apache.felix.dependencymanager.shell", "3.0.1"),
1335
1336                 mavenBundle("com.google.code.gson", "gson", "2.1"),
1337                 mavenBundle("org.jboss.spec.javax.transaction", "jboss-transaction-api_1.1_spec", "1.0.1.Final"),
1338                 mavenBundle("org.apache.felix", "org.apache.felix.fileinstall", "3.1.6"),
1339                 mavenBundle("org.apache.commons", "commons-lang3", "3.1"),
1340                 mavenBundle("commons-codec", "commons-codec"),
1341                 mavenBundle("virgomirror", "org.eclipse.jdt.core.compiler.batch", "3.8.0.I20120518-2145"),
1342                 mavenBundle("eclipselink", "javax.persistence", "2.0.4.v201112161009"),
1343
1344                 mavenBundle("orbit", "javax.activation", "1.1.0.v201211130549"),
1345                 mavenBundle("orbit", "javax.annotation", "1.1.0.v201209060031"),
1346                 mavenBundle("orbit", "javax.ejb", "3.1.1.v201204261316"),
1347                 mavenBundle("orbit", "javax.el", "2.2.0.v201108011116"),
1348                 mavenBundle("orbit", "javax.mail.glassfish", "1.4.1.v201108011116"),
1349                 mavenBundle("orbit", "javax.xml.rpc", "1.1.0.v201005080400"),
1350                 mavenBundle("orbit", "org.apache.catalina", "7.0.32.v201211201336"),
1351                 // these are bundle fragments that can't be started on its own
1352                 mavenBundle("orbit", "org.apache.catalina.ha", "7.0.32.v201211201952").noStart(),
1353                 mavenBundle("orbit", "org.apache.catalina.tribes", "7.0.32.v201211201952").noStart(),
1354                 mavenBundle("orbit", "org.apache.coyote", "7.0.32.v201211201952").noStart(),
1355                 mavenBundle("orbit", "org.apache.jasper", "7.0.32.v201211201952").noStart(),
1356
1357                 mavenBundle("orbit", "org.apache.el", "7.0.32.v201211081135"),
1358                 mavenBundle("orbit", "org.apache.juli.extras", "7.0.32.v201211081135"),
1359                 mavenBundle("orbit", "org.apache.tomcat.api", "7.0.32.v201211081135"),
1360                 mavenBundle("orbit", "org.apache.tomcat.util", "7.0.32.v201211201952").noStart(),
1361                 mavenBundle("orbit", "javax.servlet.jsp.jstl", "1.2.0.v201105211821"),
1362                 mavenBundle("orbit", "javax.servlet.jsp.jstl.impl", "1.2.0.v201210211230"),
1363
1364                 mavenBundle("org.ops4j.pax.exam", "pax-exam-container-native"),
1365                 mavenBundle("org.ops4j.pax.exam", "pax-exam-junit4"),
1366                 mavenBundle("org.ops4j.pax.exam", "pax-exam-link-mvn"),
1367                 mavenBundle("org.ops4j.pax.url", "pax-url-aether"),
1368
1369                 mavenBundle("org.springframework", "org.springframework.asm", "3.1.3.RELEASE"),
1370                 mavenBundle("org.springframework", "org.springframework.aop", "3.1.3.RELEASE"),
1371                 mavenBundle("org.springframework", "org.springframework.context", "3.1.3.RELEASE"),
1372                 mavenBundle("org.springframework", "org.springframework.context.support", "3.1.3.RELEASE"),
1373                 mavenBundle("org.springframework", "org.springframework.core", "3.1.3.RELEASE"),
1374                 mavenBundle("org.springframework", "org.springframework.beans", "3.1.3.RELEASE"),
1375                 mavenBundle("org.springframework", "org.springframework.expression", "3.1.3.RELEASE"),
1376                 mavenBundle("org.springframework", "org.springframework.web", "3.1.3.RELEASE"),
1377
1378                 mavenBundle("org.aopalliance", "com.springsource.org.aopalliance", "1.0.0"),
1379                 mavenBundle("org.springframework", "org.springframework.web.servlet", "3.1.3.RELEASE"),
1380                 mavenBundle("org.springframework.security", "spring-security-config", "3.1.3.RELEASE"),
1381                 mavenBundle("org.springframework.security", "spring-security-core", "3.1.3.RELEASE"),
1382                 mavenBundle("org.springframework.security", "spring-security-web", "3.1.3.RELEASE"),
1383                 mavenBundle("org.springframework.security", "spring-security-taglibs", "3.1.3.RELEASE"),
1384                 mavenBundle("org.springframework", "org.springframework.transaction", "3.1.3.RELEASE"),
1385
1386                 mavenBundle("org.ow2.chameleon.management", "chameleon-mbeans", "1.0.0"),
1387                 mavenBundle("org.opendaylight.controller.thirdparty", "net.sf.jung2", "2.0.1-SNAPSHOT"),
1388                 mavenBundle("org.opendaylight.controller.thirdparty", "com.sun.jersey.jersey-servlet", "1.17-SNAPSHOT"),
1389
1390                 // Jersey needs to be started before the northbound application
1391                 // bundles, using a lower start level
1392                 mavenBundle("com.sun.jersey", "jersey-client", "1.17"),
1393                 mavenBundle("com.sun.jersey", "jersey-server", "1.17").startLevel(2),
1394                 mavenBundle("com.sun.jersey", "jersey-core", "1.17").startLevel(2),
1395                 mavenBundle("com.sun.jersey", "jersey-json", "1.17").startLevel(2), junitBundles());
1396     }
1397
1398 }