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