Merge "Add container context debug osgi cli command to Switch Manager"
[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("timestamp"));
212             Assert.assertEquals(timestampName, properties.getJSONObject("timeStamp").getString("timestampName"));
213         }
214         if (actionsValue == null) {
215             Assert.assertFalse(properties.has("actions"));
216         } else {
217             Assert.assertEquals(actionsValue, (Integer) properties.getJSONObject("actions").getInt("actionsValue"));
218         }
219         if (capabilitiesValue == null) {
220             Assert.assertFalse(properties.has("capabilities"));
221         } else {
222             Assert.assertEquals(capabilitiesValue,
223                     (Integer) properties.getJSONObject("capabilities").getInt("capabilitiesValue"));
224         }
225         if (tablesValue == null) {
226             Assert.assertFalse(properties.has("tables"));
227         } else {
228             Assert.assertEquals(tablesValue, (Integer) properties.getJSONObject("tables").getInt("tablesValue"));
229         }
230         if (buffersValue == null) {
231             Assert.assertFalse(properties.has("buffers"));
232         } else {
233             Assert.assertEquals(buffersValue, (Integer) properties.getJSONObject("buffers").getInt("buffersValue"));
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("stateValue"));
253         }
254         if (capabilities == null) {
255             Assert.assertFalse(properties.has("capabilities"));
256         } else {
257             Assert.assertEquals(capabilities,
258                     (Integer) properties.getJSONObject("capabilities").getInt("capabilitiesValue"));
259         }
260         if (bandwidth == null) {
261             Assert.assertFalse(properties.has("bandwidth"));
262         } else {
263             Assert.assertEquals(bandwidth, (Integer) properties.getJSONObject("bandwidth").getInt("bandwidthValue"));
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/" + name1, "POST", requestBody);
357         Assert.assertEquals(201, httpResponseCode.intValue());
358
359         requestBody = "{\"name\":\"" + name2 + "\", \"prefix\":\"" + prefix2 + "\", \"nextHop\":\"" + nextHop2 + "\"}";
360         result = getJsonResult(baseURL + "default/" + 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/" + 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/" + 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/" + 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(200, httpResponseCode.intValue());
493         result = getJsonResult(baseURL + "node/STUB/" + nodeId_1 + "/property/description/node1", "PUT");
494         Assert.assertEquals(200, 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("tierValue"));
503         Assert.assertEquals("node1", node.getJSONObject("properties").getJSONObject("description").getString("descriptionValue"));
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 + "flowstats");
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("flowStat");
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/portstats
580         result = getJsonResult(baseURL + "portstats");
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("portStat");
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 + "flowstats/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("flowStat");
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 + "portstats/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("portStat");
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 + "STUB/51966/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 + "STUB/51966/test1", "POST", fc);
743         Assert.assertTrue(httpResponseCode == 201);
744
745         // test get returns flow that was added.
746         result = getJsonResult(baseURL + "STUB/51966/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 + "STUB/51966/test1", "POST", 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 + "STUB/51966/test2", "POST", fc);
764         // test should return 500 for error due to same flow being added.
765         Assert.assertTrue(result.equals("500"));
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 + "STUB/51966/test2", "POST", fc);
770         Assert.assertTrue(httpResponseCode == 201);
771
772         // check that request returns both flows given node.
773         result = getJsonResult(baseURL + "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 + "STUB/51966/test2", "DELETE");
792         Assert.assertTrue(httpResponseCode == 200);
793
794         result = getJsonResult(baseURL + "STUB/51966/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 POST method: addHost()
872         String queryParameter = new QueryParameter("dataLayerAddress", dataLayerAddress_1).add("nodeType", nodeType_1)
873                 .add("nodeId", nodeId_1.toString()).add("nodeConnectorType", nodeConnectorType_1)
874                 .add("nodeConnectorId", nodeConnectorId_1.toString()).add("vlan", vlan_1).getString();
875
876         String result = getJsonResult(baseURL + "/" + networkAddress_1 + queryParameter, "POST");
877         Assert.assertTrue(httpResponseCode == 201);
878
879         // vlan is not passed through query parameter but should be
880         // defaulted to "0"
881         queryParameter = new QueryParameter("dataLayerAddress", dataLayerAddress_2).add("nodeType", nodeType_2)
882                 .add("nodeId", nodeId_2.toString()).add("nodeConnectorType", nodeConnectorType_2)
883                 .add("nodeConnectorId", nodeConnectorId_2.toString()).getString();
884
885         result = getJsonResult(baseURL + "/" + networkAddress_2 + queryParameter, "POST");
886         Assert.assertTrue(httpResponseCode == 201);
887
888         // define variables for decoding returned strings
889         String networkAddress;
890         JSONObject host_jo, dl_jo, nc_jo, node_jo;
891
892         // the two hosts should be in inactive host DB
893         // test GET method: getInactiveHosts()
894         result = getJsonResult(baseURL + "/inactive", "GET");
895         Assert.assertTrue(httpResponseCode == 200);
896
897         JSONTokener jt = new JSONTokener(result);
898         JSONObject json = new JSONObject(jt);
899         // there should be at least two hosts in the DB
900         Assert.assertTrue(json.get("host") instanceof JSONArray);
901         JSONArray ja = json.getJSONArray("host");
902         Integer count = ja.length();
903         Assert.assertTrue(count == 2);
904
905         for (int i = 0; i < count; i++) {
906             host_jo = ja.getJSONObject(i);
907             dl_jo = host_jo.getJSONObject("dataLayerAddress");
908             nc_jo = host_jo.getJSONObject("nodeConnector");
909             node_jo = nc_jo.getJSONObject("node");
910
911             networkAddress = host_jo.getString("networkAddress");
912             if (networkAddress.equalsIgnoreCase(networkAddress_1)) {
913                 Assert.assertTrue(dl_jo.getString("macAddress").equalsIgnoreCase(dataLayerAddress_1));
914                 Assert.assertTrue(nc_jo.getString("@type").equalsIgnoreCase(nodeConnectorType_1));
915                 Assert.assertTrue(nc_jo.getInt("@id") == nodeConnectorId_1);
916                 Assert.assertTrue(node_jo.getString("@type").equalsIgnoreCase(nodeType_1));
917                 Assert.assertTrue(node_jo.getInt("@id") == nodeId_1);
918                 Assert.assertTrue(host_jo.getString("vlan").equalsIgnoreCase(vlan_1));
919             } else if (networkAddress.equalsIgnoreCase(networkAddress_2)) {
920                 Assert.assertTrue(dl_jo.getString("macAddress").equalsIgnoreCase(dataLayerAddress_2));
921                 Assert.assertTrue(nc_jo.getString("@type").equalsIgnoreCase(nodeConnectorType_2));
922                 Assert.assertTrue(nc_jo.getInt("@id") == nodeConnectorId_2);
923                 Assert.assertTrue(node_jo.getString("@type").equalsIgnoreCase(nodeType_2));
924                 Assert.assertTrue(node_jo.getInt("@id") == nodeId_2);
925                 Assert.assertTrue(host_jo.getString("vlan").equalsIgnoreCase(vlan_2));
926             } else {
927                 Assert.assertTrue(false);
928             }
929         }
930
931         // test GET method: getActiveHosts() - no host expected
932         result = getJsonResult(baseURL, "GET");
933         Assert.assertTrue(httpResponseCode == 200);
934
935         jt = new JSONTokener(result);
936         json = new JSONObject(jt);
937         Assert.assertFalse(hostInJson(json, networkAddress_1));
938         Assert.assertFalse(hostInJson(json, networkAddress_2));
939
940         // put the 1st host into active host DB
941         Node nd;
942         NodeConnector ndc;
943         try {
944             nd = new Node(nodeType_1, nodeId_1);
945             ndc = new NodeConnector(nodeConnectorType_1, nodeConnectorId_1, nd);
946             this.invtoryListener.notifyNodeConnector(ndc, UpdateType.ADDED, null);
947         } catch (ConstructionException e) {
948             ndc = null;
949             nd = null;
950         }
951
952         // verify the host shows up in active host DB
953
954         result = getJsonResult(baseURL, "GET");
955         Assert.assertTrue(httpResponseCode == 200);
956
957         jt = new JSONTokener(result);
958         json = new JSONObject(jt);
959
960         Assert.assertTrue(hostInJson(json, networkAddress_1));
961
962         // test GET method for getHostDetails()
963
964         result = getJsonResult(baseURL + "/" + networkAddress_1, "GET");
965         Assert.assertTrue(httpResponseCode == 200);
966
967         jt = new JSONTokener(result);
968         json = new JSONObject(jt);
969
970         Assert.assertFalse(json.length() == 0);
971
972         dl_jo = json.getJSONObject("dataLayerAddress");
973         nc_jo = json.getJSONObject("nodeConnector");
974         node_jo = nc_jo.getJSONObject("node");
975
976         Assert.assertTrue(json.getString("networkAddress").equalsIgnoreCase(networkAddress_1));
977         Assert.assertTrue(dl_jo.getString("macAddress").equalsIgnoreCase(dataLayerAddress_1));
978         Assert.assertTrue(nc_jo.getString("@type").equalsIgnoreCase(nodeConnectorType_1));
979         Assert.assertTrue(Integer.parseInt(nc_jo.getString("@id")) == nodeConnectorId_1);
980         Assert.assertTrue(node_jo.getString("@type").equalsIgnoreCase(nodeType_1));
981         Assert.assertTrue(Integer.parseInt(node_jo.getString("@id")) == nodeId_1);
982         Assert.assertTrue(json.getString("vlan").equalsIgnoreCase(vlan_1));
983
984         // test DELETE method for deleteFlow()
985
986         result = getJsonResult(baseURL + "/" + networkAddress_1, "DELETE");
987         Assert.assertTrue(httpResponseCode == 200);
988
989         // verify host_1 removed from active host DB
990         // test GET method: getActiveHosts() - no host expected
991
992         result = getJsonResult(baseURL, "GET");
993         Assert.assertTrue(httpResponseCode == 200);
994
995         jt = new JSONTokener(result);
996         json = new JSONObject(jt);
997
998         Assert.assertFalse(hostInJson(json, networkAddress_1));
999
1000     }
1001
1002     private Boolean hostInJson(JSONObject json, String hostIp) throws JSONException {
1003         // input JSONObject may be empty
1004         if (json.length() == 0) {
1005             return false;
1006         }
1007         if (json.get("host") instanceof JSONArray) {
1008             JSONArray ja = json.getJSONArray("host");
1009             for (int i = 0; i < ja.length(); i++) {
1010                 String na = ja.getJSONObject(i).getString("networkAddress");
1011                 if (na.equalsIgnoreCase(hostIp))
1012                     return true;
1013             }
1014             return false;
1015         } else {
1016             String na = json.getJSONObject("host").getString("networkAddress");
1017             return (na.equalsIgnoreCase(hostIp)) ? true : false;
1018         }
1019     }
1020
1021     @Test
1022     public void testTopology() throws JSONException, ConstructionException {
1023         System.out.println("Starting Topology JAXB client.");
1024         String baseURL = "http://127.0.0.1:8080/controller/nb/v2/topology/default";
1025
1026         // === test GET method for getTopology()
1027         short state_1 = State.EDGE_UP, state_2 = State.EDGE_DOWN;
1028         long bw_1 = Bandwidth.BW10Gbps, bw_2 = Bandwidth.BW100Mbps;
1029         long lat_1 = Latency.LATENCY100ns, lat_2 = Latency.LATENCY1ms;
1030         String nodeType = "STUB";
1031         String nodeConnType = "STUB";
1032         int headNC1_nodeId = 1, headNC1_nodeConnId = 11;
1033         int tailNC1_nodeId = 2, tailNC1_nodeConnId = 22;
1034         int headNC2_nodeId = 2, headNC2_nodeConnId = 21;
1035         int tailNC2_nodeId = 1, tailNC2_nodeConnId = 12;
1036
1037         List<TopoEdgeUpdate> topoedgeupdateList = new ArrayList<TopoEdgeUpdate>();
1038         NodeConnector headnc1 = new NodeConnector(nodeConnType, headNC1_nodeConnId, new Node(nodeType, headNC1_nodeId));
1039         NodeConnector tailnc1 = new NodeConnector(nodeConnType, tailNC1_nodeConnId, new Node(nodeType, tailNC1_nodeId));
1040         Edge e1 = new Edge(tailnc1, headnc1);
1041         Set<Property> props_1 = new HashSet<Property>();
1042         props_1.add(new State(state_1));
1043         props_1.add(new Bandwidth(bw_1));
1044         props_1.add(new Latency(lat_1));
1045         TopoEdgeUpdate teu1 = new TopoEdgeUpdate(e1, props_1, UpdateType.ADDED);
1046         topoedgeupdateList.add(teu1);
1047
1048         NodeConnector headnc2 = new NodeConnector(nodeConnType, headNC2_nodeConnId, new Node(nodeType, headNC2_nodeId));
1049         NodeConnector tailnc2 = new NodeConnector(nodeConnType, tailNC2_nodeConnId, new Node(nodeType, tailNC2_nodeId));
1050         Edge e2 = new Edge(tailnc2, headnc2);
1051         Set<Property> props_2 = new HashSet<Property>();
1052         props_2.add(new State(state_2));
1053         props_2.add(new Bandwidth(bw_2));
1054         props_2.add(new Latency(lat_2));
1055
1056         TopoEdgeUpdate teu2 = new TopoEdgeUpdate(e2, props_2, UpdateType.ADDED);
1057         topoedgeupdateList.add(teu2);
1058
1059         topoUpdates.edgeUpdate(topoedgeupdateList);
1060
1061         // HTTP request
1062         String result = getJsonResult(baseURL, "GET");
1063         Assert.assertTrue(httpResponseCode == 200);
1064         if (debugMsg) {
1065             System.out.println("Get Topology: " + result);
1066         }
1067
1068         // returned data must be an array of edges
1069         JSONTokener jt = new JSONTokener(result);
1070         JSONObject json = new JSONObject(jt);
1071         Assert.assertTrue(json.get("edgeProperties") instanceof JSONArray);
1072         JSONArray ja = json.getJSONArray("edgeProperties");
1073
1074         for (int i = 0; i < ja.length(); i++) {
1075             JSONObject edgeProp = ja.getJSONObject(i);
1076             JSONObject edge = edgeProp.getJSONObject("edge");
1077             JSONObject tailNC = edge.getJSONObject("tailNodeConnector");
1078             JSONObject tailNode = tailNC.getJSONObject("node");
1079
1080             JSONObject headNC = edge.getJSONObject("headNodeConnector");
1081             JSONObject headNode = headNC.getJSONObject("node");
1082             JSONObject Props = edgeProp.getJSONObject("properties");
1083             JSONObject bandw = Props.getJSONObject("bandwidth");
1084             JSONObject stt = Props.getJSONObject("state");
1085             JSONObject ltc = Props.getJSONObject("latency");
1086
1087             if (headNC.getInt("@id") == headNC1_nodeConnId) {
1088                 Assert.assertEquals(headNode.getString("@type"), nodeType);
1089                 Assert.assertEquals(headNode.getLong("@id"), headNC1_nodeId);
1090                 Assert.assertEquals(headNC.getString("@type"), nodeConnType);
1091                 Assert.assertEquals(tailNode.getString("@type"),nodeType);
1092                 Assert.assertEquals(tailNode.getString("@type"), nodeConnType);
1093                 Assert.assertEquals(tailNC.getLong("@id"), tailNC1_nodeConnId);
1094                 Assert.assertEquals(bandw.getLong("bandwidthValue"), bw_1);
1095                 Assert.assertTrue((short) stt.getInt("stateValue") == state_1);
1096                 Assert.assertEquals(ltc.getLong("latencyValue"), lat_1);
1097             } else if (headNC.getInt("@id") == headNC2_nodeConnId) {
1098                 Assert.assertEquals(headNode.getString("@type"),nodeType);
1099                 Assert.assertEquals(headNode.getLong("@id"), headNC2_nodeId);
1100                 Assert.assertEquals(headNC.getString("@type"), nodeConnType);
1101                 Assert.assertEquals(tailNode.getString("@type"), nodeType);
1102                 Assert.assertTrue(tailNode.getInt("@id") == tailNC2_nodeId);
1103                 Assert.assertEquals(tailNC.getString("@type"), nodeConnType);
1104                 Assert.assertEquals(tailNC.getLong("@id"), tailNC2_nodeConnId);
1105                 Assert.assertEquals(bandw.getLong("bandwidthValue"), bw_2);
1106                 Assert.assertTrue((short) stt.getInt("stateValue") == state_2);
1107                 Assert.assertEquals(ltc.getLong("latencyValue"), lat_2);
1108             }
1109         }
1110
1111         // === test POST method for addUserLink()
1112         // define 2 sample nodeConnectors for user link configuration tests
1113         String nodeType_1 = "STUB";
1114         Integer nodeId_1 = 3366;
1115         String nodeConnectorType_1 = "STUB";
1116         Integer nodeConnectorId_1 = 12;
1117
1118         String nodeType_2 = "STUB";
1119         Integer nodeId_2 = 4477;
1120         String nodeConnectorType_2 = "STUB";
1121         Integer nodeConnectorId_2 = 34;
1122
1123         JSONObject jo = new JSONObject()
1124                 .append("name", "userLink_1")
1125                 .append("srcNodeConnector",
1126                         nodeConnectorType_1 + "|" + nodeConnectorId_1 + "@" + nodeType_1 + "|" + nodeId_1)
1127                 .append("dstNodeConnector",
1128                         nodeConnectorType_2 + "|" + nodeConnectorId_2 + "@" + nodeType_2 + "|" + nodeId_2);
1129         // execute HTTP request and verify response code
1130         result = getJsonResult(baseURL + "/userLink", "POST", jo.toString());
1131         Assert.assertTrue(httpResponseCode == 201);
1132
1133         // === test GET method for getUserLinks()
1134         result = getJsonResult(baseURL + "/userLink", "GET");
1135         Assert.assertTrue(httpResponseCode == 200);
1136         if (debugMsg) {
1137             System.out.println("result:" + result);
1138         }
1139
1140         jt = new JSONTokener(result);
1141         json = new JSONObject(jt);
1142
1143         // should have at least one object returned
1144         Assert.assertFalse(json.length() == 0);
1145         JSONObject userlink = new JSONObject();
1146
1147         if (json.get("userLinks") instanceof JSONArray) {
1148             ja = json.getJSONArray("userLinks");
1149             int i;
1150             for (i = 0; i < ja.length(); i++) {
1151                 userlink = ja.getJSONObject(i);
1152                 if (userlink.getString("name").equalsIgnoreCase("userLink_1"))
1153                     break;
1154             }
1155             Assert.assertFalse(i == ja.length());
1156         } else {
1157             userlink = json.getJSONObject("userLinks");
1158             Assert.assertTrue(userlink.getString("name").equalsIgnoreCase("userLink_1"));
1159         }
1160
1161         String[] level_1, level_2;
1162         level_1 = userlink.getString("srcNodeConnector").split("\\@");
1163         level_2 = level_1[0].split("\\|");
1164         Assert.assertTrue(level_2[0].equalsIgnoreCase(nodeConnectorType_1));
1165         Assert.assertTrue(Integer.parseInt(level_2[1]) == nodeConnectorId_1);
1166         level_2 = level_1[1].split("\\|");
1167         Assert.assertTrue(level_2[0].equalsIgnoreCase(nodeType_1));
1168         Assert.assertTrue(Integer.parseInt(level_2[1]) == nodeId_1);
1169         level_1 = userlink.getString("dstNodeConnector").split("\\@");
1170         level_2 = level_1[0].split("\\|");
1171         Assert.assertTrue(level_2[0].equalsIgnoreCase(nodeConnectorType_2));
1172         Assert.assertTrue(Integer.parseInt(level_2[1]) == nodeConnectorId_2);
1173         level_2 = level_1[1].split("\\|");
1174         Assert.assertTrue(level_2[0].equalsIgnoreCase(nodeType_2));
1175         Assert.assertTrue(Integer.parseInt(level_2[1]) == nodeId_2);
1176
1177         // === test DELETE method for deleteUserLink()
1178         String userName = "userLink_1";
1179         result = getJsonResult(baseURL + "/userLink/" + userName, "DELETE");
1180         Assert.assertTrue(httpResponseCode == 200);
1181
1182         // execute another getUserLinks() request to verify that userLink_1 is
1183         // removed
1184         result = getJsonResult(baseURL + "/userLink", "GET");
1185         Assert.assertTrue(httpResponseCode == 200);
1186         if (debugMsg) {
1187             System.out.println("result:" + result);
1188         }
1189         jt = new JSONTokener(result);
1190         json = new JSONObject(jt);
1191
1192         if (json.length() != 0) {
1193             if (json.get("userLinks") instanceof JSONArray) {
1194                 ja = json.getJSONArray("userLinks");
1195                 for (int i = 0; i < ja.length(); i++) {
1196                     userlink = ja.getJSONObject(i);
1197                     Assert.assertFalse(userlink.getString("name").equalsIgnoreCase("userLink_1"));
1198                 }
1199             } else {
1200                 userlink = json.getJSONObject("userLinks");
1201                 Assert.assertFalse(userlink.getString("name").equalsIgnoreCase("userLink_1"));
1202             }
1203         }
1204     }
1205
1206     // Configure the OSGi container
1207     @Configuration
1208     public Option[] config() {
1209         return options(
1210                 //
1211                 systemProperty("logback.configurationFile").value(
1212                         "file:" + PathUtils.getBaseDir() + "/src/test/resources/logback.xml"),
1213                 // To start OSGi console for inspection remotely
1214                 systemProperty("osgi.console").value("2401"),
1215                 systemProperty("org.eclipse.gemini.web.tomcat.config.path").value(
1216                         PathUtils.getBaseDir() + "/src/test/resources/tomcat-server.xml"),
1217
1218                 // setting default level. Jersey bundles will need to be started
1219                 // earlier.
1220                 systemProperty("osgi.bundles.defaultStartLevel").value("4"),
1221
1222                 // Set the systemPackages (used by clustering)
1223                 systemPackages("sun.reflect", "sun.reflect.misc", "sun.misc"),
1224                 mavenBundle("javax.servlet", "servlet-api", "2.5"),
1225
1226                 mavenBundle("org.slf4j", "jcl-over-slf4j", "1.7.2"),
1227                 mavenBundle("org.slf4j", "slf4j-api", "1.7.2"),
1228                 mavenBundle("org.slf4j", "log4j-over-slf4j", "1.7.2"),
1229                 mavenBundle("ch.qos.logback", "logback-core", "1.0.9"),
1230                 mavenBundle("ch.qos.logback", "logback-classic", "1.0.9"),
1231                 mavenBundle("org.apache.commons", "commons-lang3", "3.1"),
1232                 mavenBundle("org.apache.felix", "org.apache.felix.dependencymanager", "3.1.0"),
1233
1234                 // the plugin stub to get data for the tests
1235                 mavenBundle("org.opendaylight.controller", "protocol_plugins.stub", "0.4.0-SNAPSHOT"),
1236
1237                 // List all the opendaylight modules
1238                 mavenBundle("org.opendaylight.controller", "configuration", "0.4.0-SNAPSHOT"),
1239                 mavenBundle("org.opendaylight.controller", "configuration.implementation", "0.4.0-SNAPSHOT"),
1240                 mavenBundle("org.opendaylight.controller", "containermanager", "0.4.0-SNAPSHOT"),
1241                 mavenBundle("org.opendaylight.controller", "containermanager.implementation", "0.4.0-SNAPSHOT"),
1242                 mavenBundle("org.opendaylight.controller", "clustering.services", "0.4.0-SNAPSHOT"),
1243                 mavenBundle("org.opendaylight.controller", "clustering.services-implementation", "0.4.0-SNAPSHOT"),
1244                 mavenBundle("org.opendaylight.controller", "security", "0.4.0-SNAPSHOT").noStart(),
1245                 mavenBundle("org.opendaylight.controller", "sal", "0.5.0-SNAPSHOT"),
1246                 mavenBundle("org.opendaylight.controller", "sal.implementation", "0.4.0-SNAPSHOT"),
1247                 mavenBundle("org.opendaylight.controller", "sal.connection", "0.1.0-SNAPSHOT"),
1248                 mavenBundle("org.opendaylight.controller", "sal.connection.implementation", "0.1.0-SNAPSHOT"),
1249                 mavenBundle("org.opendaylight.controller", "switchmanager", "0.5.0-SNAPSHOT"),
1250                 mavenBundle("org.opendaylight.controller", "connectionmanager", "0.1.0-SNAPSHOT"),
1251                 mavenBundle("org.opendaylight.controller", "connectionmanager.implementation", "0.1.0-SNAPSHOT"),
1252                 mavenBundle("org.opendaylight.controller", "switchmanager.implementation", "0.4.0-SNAPSHOT"),
1253                 mavenBundle("org.opendaylight.controller", "forwardingrulesmanager", "0.4.0-SNAPSHOT"),
1254                 mavenBundle("org.opendaylight.controller", "forwardingrulesmanager.implementation", "0.4.0-SNAPSHOT"),
1255                 mavenBundle("org.opendaylight.controller", "statisticsmanager", "0.4.0-SNAPSHOT"),
1256                 mavenBundle("org.opendaylight.controller", "statisticsmanager.implementation", "0.4.0-SNAPSHOT"),
1257                 mavenBundle("org.opendaylight.controller", "arphandler", "0.4.0-SNAPSHOT"),
1258                 mavenBundle("org.opendaylight.controller", "hosttracker", "0.4.0-SNAPSHOT"),
1259                 mavenBundle("org.opendaylight.controller", "hosttracker.implementation", "0.4.0-SNAPSHOT"),
1260                 mavenBundle("org.opendaylight.controller", "arphandler", "0.4.0-SNAPSHOT"),
1261                 mavenBundle("org.opendaylight.controller", "routing.dijkstra_implementation", "0.4.0-SNAPSHOT"),
1262                 mavenBundle("org.opendaylight.controller", "topologymanager", "0.4.0-SNAPSHOT"),
1263                 mavenBundle("org.opendaylight.controller", "usermanager", "0.4.0-SNAPSHOT"),
1264                 mavenBundle("org.opendaylight.controller", "usermanager.implementation", "0.4.0-SNAPSHOT"),
1265                 mavenBundle("org.opendaylight.controller", "logging.bridge", "0.4.0-SNAPSHOT"),
1266                 mavenBundle("org.opendaylight.controller", "clustering.test", "0.4.0-SNAPSHOT"),
1267                 mavenBundle("org.opendaylight.controller", "forwarding.staticrouting", "0.4.0-SNAPSHOT"),
1268
1269                 // Northbound bundles
1270                 mavenBundle("org.opendaylight.controller", "commons.northbound", "0.4.0-SNAPSHOT"),
1271                 mavenBundle("org.opendaylight.controller", "forwarding.staticrouting.northbound", "0.4.0-SNAPSHOT"),
1272                 mavenBundle("org.opendaylight.controller", "statistics.northbound", "0.4.0-SNAPSHOT"),
1273                 mavenBundle("org.opendaylight.controller", "topology.northbound", "0.4.0-SNAPSHOT"),
1274                 mavenBundle("org.opendaylight.controller", "hosttracker.northbound", "0.4.0-SNAPSHOT"),
1275                 mavenBundle("org.opendaylight.controller", "switchmanager.northbound", "0.4.0-SNAPSHOT"),
1276                 mavenBundle("org.opendaylight.controller", "flowprogrammer.northbound", "0.4.0-SNAPSHOT"),
1277                 mavenBundle("org.opendaylight.controller", "subnets.northbound", "0.4.0-SNAPSHOT"),
1278
1279                 mavenBundle("org.codehaus.jackson", "jackson-mapper-asl", "1.9.8"),
1280                 mavenBundle("org.codehaus.jackson", "jackson-core-asl", "1.9.8"),
1281                 mavenBundle("org.codehaus.jackson", "jackson-jaxrs", "1.9.8"),
1282                 mavenBundle("org.codehaus.jettison", "jettison", "1.3.3"),
1283
1284                 mavenBundle("commons-io", "commons-io", "2.3"),
1285
1286                 mavenBundle("commons-fileupload", "commons-fileupload", "1.2.2"),
1287
1288                 mavenBundle("equinoxSDK381", "javax.servlet", "3.0.0.v201112011016"),
1289                 mavenBundle("equinoxSDK381", "javax.servlet.jsp", "2.2.0.v201112011158"),
1290                 mavenBundle("equinoxSDK381", "org.eclipse.equinox.ds", "1.4.0.v20120522-1841"),
1291                 mavenBundle("orbit", "javax.xml.rpc", "1.1.0.v201005080400"),
1292                 mavenBundle("equinoxSDK381", "org.eclipse.equinox.util", "1.0.400.v20120522-2049"),
1293                 mavenBundle("equinoxSDK381", "org.eclipse.osgi.services", "3.3.100.v20120522-1822"),
1294                 mavenBundle("equinoxSDK381", "org.apache.felix.gogo.command", "0.8.0.v201108120515"),
1295                 mavenBundle("equinoxSDK381", "org.apache.felix.gogo.runtime", "0.8.0.v201108120515"),
1296                 mavenBundle("equinoxSDK381", "org.apache.felix.gogo.shell", "0.8.0.v201110170705"),
1297                 mavenBundle("equinoxSDK381", "org.eclipse.equinox.cm", "1.0.400.v20120522-1841"),
1298                 mavenBundle("equinoxSDK381", "org.eclipse.equinox.console", "1.0.0.v20120522-1841"),
1299                 mavenBundle("equinoxSDK381", "org.eclipse.equinox.launcher", "1.3.0.v20120522-1813"),
1300
1301                 mavenBundle("geminiweb", "org.eclipse.gemini.web.core", "2.2.0.RELEASE"),
1302                 mavenBundle("geminiweb", "org.eclipse.gemini.web.extender", "2.2.0.RELEASE"),
1303                 mavenBundle("geminiweb", "org.eclipse.gemini.web.tomcat", "2.2.0.RELEASE"),
1304                 mavenBundle("geminiweb", "org.eclipse.virgo.kernel.equinox.extensions", "3.6.0.RELEASE").noStart(),
1305                 mavenBundle("geminiweb", "org.eclipse.virgo.util.common", "3.6.0.RELEASE"),
1306                 mavenBundle("geminiweb", "org.eclipse.virgo.util.io", "3.6.0.RELEASE"),
1307                 mavenBundle("geminiweb", "org.eclipse.virgo.util.math", "3.6.0.RELEASE"),
1308                 mavenBundle("geminiweb", "org.eclipse.virgo.util.osgi", "3.6.0.RELEASE"),
1309                 mavenBundle("geminiweb", "org.eclipse.virgo.util.osgi.manifest", "3.6.0.RELEASE"),
1310                 mavenBundle("geminiweb", "org.eclipse.virgo.util.parser.manifest", "3.6.0.RELEASE"),
1311
1312                 mavenBundle("org.apache.felix", "org.apache.felix.dependencymanager", "3.1.0"),
1313                 mavenBundle("org.apache.felix", "org.apache.felix.dependencymanager.shell", "3.0.1"),
1314
1315                 mavenBundle("com.google.code.gson", "gson", "2.1"),
1316                 mavenBundle("org.jboss.spec.javax.transaction", "jboss-transaction-api_1.1_spec", "1.0.1.Final"),
1317                 mavenBundle("org.apache.felix", "org.apache.felix.fileinstall", "3.1.6"),
1318                 mavenBundle("org.apache.commons", "commons-lang3", "3.1"),
1319                 mavenBundle("commons-codec", "commons-codec"),
1320                 mavenBundle("virgomirror", "org.eclipse.jdt.core.compiler.batch", "3.8.0.I20120518-2145"),
1321                 mavenBundle("eclipselink", "javax.persistence", "2.0.4.v201112161009"),
1322                 mavenBundle("eclipselink", "javax.resource", "1.5.0.v200906010428"),
1323
1324                 mavenBundle("orbit", "javax.activation", "1.1.0.v201211130549"),
1325                 mavenBundle("orbit", "javax.annotation", "1.1.0.v201209060031"),
1326                 mavenBundle("orbit", "javax.ejb", "3.1.1.v201204261316"),
1327                 mavenBundle("orbit", "javax.el", "2.2.0.v201108011116"),
1328                 mavenBundle("orbit", "javax.mail.glassfish", "1.4.1.v201108011116"),
1329                 mavenBundle("orbit", "javax.xml.rpc", "1.1.0.v201005080400"),
1330                 mavenBundle("orbit", "org.apache.catalina", "7.0.32.v201211201336"),
1331                 // these are bundle fragments that can't be started on its own
1332                 mavenBundle("orbit", "org.apache.catalina.ha", "7.0.32.v201211201952").noStart(),
1333                 mavenBundle("orbit", "org.apache.catalina.tribes", "7.0.32.v201211201952").noStart(),
1334                 mavenBundle("orbit", "org.apache.coyote", "7.0.32.v201211201952").noStart(),
1335                 mavenBundle("orbit", "org.apache.jasper", "7.0.32.v201211201952").noStart(),
1336
1337                 mavenBundle("orbit", "org.apache.el", "7.0.32.v201211081135"),
1338                 mavenBundle("orbit", "org.apache.juli.extras", "7.0.32.v201211081135"),
1339                 mavenBundle("orbit", "org.apache.tomcat.api", "7.0.32.v201211081135"),
1340                 mavenBundle("orbit", "org.apache.tomcat.util", "7.0.32.v201211201952").noStart(),
1341                 mavenBundle("orbit", "javax.servlet.jsp.jstl", "1.2.0.v201105211821"),
1342                 mavenBundle("orbit", "javax.servlet.jsp.jstl.impl", "1.2.0.v201210211230"),
1343
1344                 mavenBundle("org.ops4j.pax.exam", "pax-exam-container-native"),
1345                 mavenBundle("org.ops4j.pax.exam", "pax-exam-junit4"),
1346                 mavenBundle("org.ops4j.pax.exam", "pax-exam-link-mvn"),
1347                 mavenBundle("org.ops4j.pax.url", "pax-url-aether"),
1348
1349                 mavenBundle("org.springframework", "org.springframework.asm", "3.1.3.RELEASE"),
1350                 mavenBundle("org.springframework", "org.springframework.aop", "3.1.3.RELEASE"),
1351                 mavenBundle("org.springframework", "org.springframework.context", "3.1.3.RELEASE"),
1352                 mavenBundle("org.springframework", "org.springframework.context.support", "3.1.3.RELEASE"),
1353                 mavenBundle("org.springframework", "org.springframework.core", "3.1.3.RELEASE"),
1354                 mavenBundle("org.springframework", "org.springframework.beans", "3.1.3.RELEASE"),
1355                 mavenBundle("org.springframework", "org.springframework.expression", "3.1.3.RELEASE"),
1356                 mavenBundle("org.springframework", "org.springframework.web", "3.1.3.RELEASE"),
1357
1358                 mavenBundle("org.aopalliance", "com.springsource.org.aopalliance", "1.0.0"),
1359                 mavenBundle("org.springframework", "org.springframework.web.servlet", "3.1.3.RELEASE"),
1360                 mavenBundle("org.springframework.security", "spring-security-config", "3.1.3.RELEASE"),
1361                 mavenBundle("org.springframework.security", "spring-security-core", "3.1.3.RELEASE"),
1362                 mavenBundle("org.springframework.security", "spring-security-web", "3.1.3.RELEASE"),
1363                 mavenBundle("org.springframework.security", "spring-security-taglibs", "3.1.3.RELEASE"),
1364                 mavenBundle("org.springframework", "org.springframework.transaction", "3.1.3.RELEASE"),
1365
1366                 mavenBundle("org.ow2.chameleon.management", "chameleon-mbeans", "1.0.0"),
1367                 mavenBundle("org.opendaylight.controller.thirdparty", "net.sf.jung2", "2.0.1-SNAPSHOT"),
1368                 mavenBundle("org.opendaylight.controller.thirdparty", "com.sun.jersey.jersey-servlet", "1.17-SNAPSHOT"),
1369
1370                 // Jersey needs to be started before the northbound application
1371                 // bundles, using a lower start level
1372                 mavenBundle("com.sun.jersey", "jersey-client", "1.17"),
1373                 mavenBundle("com.sun.jersey", "jersey-server", "1.17").startLevel(2),
1374                 mavenBundle("com.sun.jersey", "jersey-core", "1.17").startLevel(2),
1375                 mavenBundle("com.sun.jersey", "jersey-json", "1.17").startLevel(2), junitBundles());
1376     }
1377
1378 }