ONOS-7647 - add mock tests for ciena driver

Change-Id: I6e5b0d1333c5d138c2fb3bcdbf9b9ccecc86ce54
diff --git a/drivers/netconf/src/test/java/org/onosproject/drivers/netconf/MockCoreService.java b/drivers/netconf/src/test/java/org/onosproject/drivers/netconf/MockCoreService.java
index d10ca71..45c5646 100644
--- a/drivers/netconf/src/test/java/org/onosproject/drivers/netconf/MockCoreService.java
+++ b/drivers/netconf/src/test/java/org/onosproject/drivers/netconf/MockCoreService.java
@@ -15,6 +15,9 @@
  */
 package org.onosproject.drivers.netconf;
 
+import java.util.HashSet;
+import java.util.Set;
+
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
 import org.onosproject.core.DefaultApplicationId;
@@ -22,19 +25,25 @@
 import org.onosproject.core.Version;
 import org.onosproject.net.intent.MockIdGenerator;
 
-import java.util.HashSet;
-import java.util.Set;
-
 public class MockCoreService implements CoreService {
 
     private HashSet<ApplicationId> appIds;
     private Version version;
-    private IdGenerator idGenerator;
+    private int nextAppId = 101;
+
+    public MockCoreService(int baseId, String... apps) {
+        nextAppId = baseId;
+        appIds = new HashSet<ApplicationId>();
+        for (String app : apps) {
+            appIds.add(new DefaultApplicationId(nextAppId, app));
+            nextAppId += 1;
+        }
+        version = Version.version(1, 1, "1", "1");
+    }
 
     public MockCoreService() {
+        this(101, "org.onosproject.drivers.netconf");
         appIds = new HashSet<ApplicationId>();
-        appIds.add(new DefaultApplicationId(101, "org.onosproject.drivers.netconf"));
-        version = Version.version(1, 1, "1", "1");
     }
 
     @Override
@@ -49,7 +58,7 @@
 
     @Override
     public ApplicationId getAppId(Short id) {
-        for (ApplicationId appId:appIds) {
+        for (ApplicationId appId : appIds) {
             if (appId.id() == id.shortValue()) {
                 return appId;
             }
@@ -59,7 +68,7 @@
 
     @Override
     public ApplicationId getAppId(String name) {
-        for (ApplicationId appId:appIds) {
+        for (ApplicationId appId : appIds) {
             if (appId.name().equalsIgnoreCase(name)) {
                 return appId;
             }
@@ -69,8 +78,13 @@
 
     @Override
     public ApplicationId registerApplication(String name) {
-        ApplicationId appId = new DefaultApplicationId(101, name);
-        appIds.add(appId);
+        // Check if the app already exists
+        ApplicationId appId = getAppId(name);
+        if (appId == null) {
+            appId = new DefaultApplicationId(nextAppId, name);
+            nextAppId += 1;
+            appIds.add(appId);
+        }
         return appId;
     }
 
diff --git a/drivers/netconf/src/test/java/org/onosproject/drivers/netconf/MockDevice.java b/drivers/netconf/src/test/java/org/onosproject/drivers/netconf/MockDevice.java
new file mode 100644
index 0000000..559297b
--- /dev/null
+++ b/drivers/netconf/src/test/java/org/onosproject/drivers/netconf/MockDevice.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.netconf;
+
+import org.onlab.packet.ChassisId;
+import org.onosproject.net.Annotations;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.device.DeviceDescription;
+import org.onosproject.net.driver.Behaviour;
+import org.onosproject.net.provider.ProviderId;
+
+public class MockDevice implements Device {
+
+    private final DeviceDescription desc;
+    private final DeviceId id;
+
+    public MockDevice(DeviceId id, DeviceDescription desc) {
+        this.desc = desc;
+        this.id = id;
+    }
+
+    @Override
+    public Annotations annotations() {
+        return desc.annotations();
+    }
+
+    @Override
+    public ProviderId providerId() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public <B extends Behaviour> B as(Class<B> projectionClass) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public <B extends Behaviour> boolean is(Class<B> projectionClass) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public DeviceId id() {
+        return id;
+    }
+
+    @Override
+    public Type type() {
+        return desc.type();
+    }
+
+    @Override
+    public String manufacturer() {
+        return desc.manufacturer();
+    }
+
+    @Override
+    public String hwVersion() {
+        return desc.hwVersion();
+    }
+
+    @Override
+    public String swVersion() {
+        return desc.swVersion();
+    }
+
+    @Override
+    public String serialNumber() {
+        return desc.serialNumber();
+    }
+
+    @Override
+    public ChassisId chassisId() {
+        return desc.chassisId();
+    }
+
+}
diff --git a/drivers/netconf/src/test/java/org/onosproject/drivers/netconf/MockDeviceService.java b/drivers/netconf/src/test/java/org/onosproject/drivers/netconf/MockDeviceService.java
new file mode 100644
index 0000000..679b8c9
--- /dev/null
+++ b/drivers/netconf/src/test/java/org/onosproject/drivers/netconf/MockDeviceService.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.netconf;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.onosproject.net.Device;
+import org.onosproject.net.Device.Type;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.MastershipRole;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceListener;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.device.PortStatistics;
+
+public class MockDeviceService implements DeviceService {
+
+    private List<Device> devices = new ArrayList<Device>();
+
+    public void addDevice(Device device) {
+        if (!devices.contains(device)) {
+            devices.add(device);
+        }
+    }
+
+    @Override
+    public void addListener(DeviceListener listener) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void removeListener(DeviceListener listener) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public int getDeviceCount() {
+        return devices.size();
+    }
+
+    @Override
+    public Iterable<Device> getDevices() {
+        return new ArrayList<Device>(devices);
+    }
+
+    @Override
+    public Iterable<Device> getDevices(Type type) {
+        return devices.stream().filter(d -> d.type() == type).collect(Collectors.toList());
+    }
+
+    @Override
+    public Iterable<Device> getAvailableDevices() {
+        return new ArrayList<Device>(devices);
+    }
+
+    @Override
+    public Iterable<Device> getAvailableDevices(Type type) {
+        return devices.stream().filter(d -> d.type() == type).collect(Collectors.toList());
+    }
+
+    @Override
+    public Device getDevice(DeviceId deviceId) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public MastershipRole getRole(DeviceId deviceId) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public List<Port> getPorts(DeviceId deviceId) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public List<PortStatistics> getPortStatistics(DeviceId deviceId) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public List<PortStatistics> getPortDeltaStatistics(DeviceId deviceId) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Port getPort(DeviceId deviceId, PortNumber portNumber) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public boolean isAvailable(DeviceId deviceId) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public String localStatus(DeviceId deviceId) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public long getLastUpdatedInstant(DeviceId deviceId) {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+}
diff --git a/drivers/netconf/src/test/java/org/onosproject/drivers/netconf/MockDriverHandler.java b/drivers/netconf/src/test/java/org/onosproject/drivers/netconf/MockDriverHandler.java
index bfa6d51..d898158 100644
--- a/drivers/netconf/src/test/java/org/onosproject/drivers/netconf/MockDriverHandler.java
+++ b/drivers/netconf/src/test/java/org/onosproject/drivers/netconf/MockDriverHandler.java
@@ -15,12 +15,25 @@
  */
 package org.onosproject.drivers.netconf;
 
+import static org.junit.Assert.fail;
+
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Map;
 
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathFactory;
+
+import org.apache.commons.io.IOUtils;
 import org.onosproject.core.CoreService;
 import org.onosproject.mastership.MastershipService;
 import org.onosproject.net.DeviceId;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.driver.AbstractDriverLoader;
 import org.onosproject.net.driver.Behaviour;
 import org.onosproject.net.driver.DefaultDriver;
 import org.onosproject.net.driver.DefaultDriverData;
@@ -30,33 +43,78 @@
 import org.onosproject.net.flow.FlowRuleProgrammable;
 import org.onosproject.netconf.NetconfController;
 import org.onosproject.netconf.NetconfException;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import com.google.common.io.Resources;
 
 public class MockDriverHandler implements DriverHandler {
 
     private DriverData mockDriverData;
-
     private NetconfController ncc;
     private CoreService coreService;
+    private DeviceService deviceService;
     private MastershipService mastershipService;
 
-    public MockDriverHandler() throws NetconfException {
-        Map<Class<? extends Behaviour>, Class<? extends Behaviour>> behaviours =
-                new HashMap<Class<? extends Behaviour>, Class<? extends Behaviour>>();
-        behaviours.put(FlowRuleProgrammable.class, FlowRuleProgrammable.class);
-
+    // Centralize some initialization.
+    private void init(Map<Class<? extends Behaviour>, Class<? extends Behaviour>> behaviours, DeviceId mockDeviceId,
+            CoreService mockCoreService, DeviceService mockDeviceService) throws NetconfException {
         Map<String, String> properties = new HashMap<String, String>();
 
-        Driver mockDriver =
-                new DefaultDriver("mockDriver", null, "ONOSProject", "1.0.0", "1.0.0", behaviours, properties);
-        DeviceId mockDeviceId = DeviceId.deviceId("netconf:1.2.3.4:830");
+        Driver mockDriver = new DefaultDriver("mockDriver", null, "ONOSProject", "1.0.0", "1.0.0", behaviours,
+                properties);
         mockDriverData = new DefaultDriverData(mockDriver, mockDeviceId);
 
-
         ncc = new MockNetconfController();
         ncc.connectDevice(mockDeviceId);
-
-        coreService = new MockCoreService();
+        coreService = mockCoreService;
         mastershipService = new MockMastershipService();
+        deviceService = mockDeviceService;
+    }
+
+    @SuppressWarnings("unchecked")
+    public MockDriverHandler(Class<? extends AbstractDriverLoader> loaderClass, String behaviorSpec,
+            DeviceId mockDeviceId, CoreService mockCoreService, DeviceService mockDeviceService) {
+
+        // Had to split into declaration and initialization to make stylecheck happy
+        // else line was considered too long
+        // and auto format couldn't be tweak to make it correct
+        Map<Class<? extends Behaviour>, Class<? extends Behaviour>> behaviours;
+        behaviours = new HashMap<Class<? extends Behaviour>, Class<? extends Behaviour>>();
+
+        try {
+            String data = Resources.toString(Resources.getResource(loaderClass, behaviorSpec), StandardCharsets.UTF_8);
+            InputStream resp = IOUtils.toInputStream(data, StandardCharsets.UTF_8);
+            DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
+            DocumentBuilder builder = builderFactory.newDocumentBuilder();
+            Document document = builder.parse(resp);
+
+            XPath xp = XPathFactory.newInstance().newXPath();
+            NodeList list = (NodeList) xp.evaluate("//behaviour", document, XPathConstants.NODESET);
+            for (int i = 0; i < list.getLength(); i += 1) {
+                Node node = list.item(i);
+                NamedNodeMap attrs = node.getAttributes();
+                Class<? extends Behaviour> api = (Class<? extends Behaviour>) Class
+                        .forName(attrs.getNamedItem("api").getNodeValue());
+                Class<? extends Behaviour> impl = (Class<? extends Behaviour>) Class
+                        .forName(attrs.getNamedItem("impl").getNodeValue());
+                behaviours.put(api, impl);
+            }
+            init(behaviours, mockDeviceId, mockCoreService, mockDeviceService);
+        } catch (Exception e) {
+            fail(e.toString());
+        }
+    }
+
+    public MockDriverHandler() throws NetconfException {
+        Map<Class<? extends Behaviour>, Class<? extends Behaviour>> behaviours;
+        behaviours = new HashMap<Class<? extends Behaviour>, Class<? extends Behaviour>>();
+        behaviours.put(FlowRuleProgrammable.class, FlowRuleProgrammable.class);
+        DeviceId mockDeviceId = DeviceId.deviceId("netconf:1.2.3.4:830");
+        coreService = new MockCoreService();
+        init(behaviours, mockDeviceId, coreService, null);
     }
 
     @Override
@@ -75,17 +133,17 @@
         return null;
     }
 
+    @SuppressWarnings("unchecked")
     @Override
     public <T> T get(Class<T> serviceClass) {
         if (serviceClass.equals(NetconfController.class)) {
             return (T) ncc;
-
         } else if (serviceClass.equals(CoreService.class)) {
             return (T) coreService;
-
         } else if (serviceClass.equals(MastershipService.class)) {
             return (T) mastershipService;
-
+        } else if (serviceClass.equals(DeviceService.class)) {
+            return (T) deviceService;
         }
 
         return null;
diff --git a/drivers/netconf/src/test/java/org/onosproject/drivers/netconf/MockTemplateRequestDriver.java b/drivers/netconf/src/test/java/org/onosproject/drivers/netconf/MockTemplateRequestDriver.java
new file mode 100644
index 0000000..5a86e86
--- /dev/null
+++ b/drivers/netconf/src/test/java/org/onosproject/drivers/netconf/MockTemplateRequestDriver.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.drivers.netconf;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathFactory;
+
+import org.apache.commons.io.IOUtils;
+import org.onosproject.net.DeviceId;
+import org.onosproject.netconf.NetconfDevice;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.slf4j.Logger;
+import org.w3c.dom.Document;
+
+import com.google.common.io.Resources;
+
+public class MockTemplateRequestDriver implements TemplateRequestDriver {
+    private static final Logger log = getLogger(MockTemplateRequestDriver.class);
+    private static final DeviceId DEFAULT_RESPONSES_ID = DeviceId.deviceId("mock:default:1234");
+
+    private Map<DeviceId, Map<String, String>> responses = new HashMap<DeviceId, Map<String, String>>();
+
+    private Map<NetconfSession, DeviceId> sessionMap = new HashMap<NetconfSession, DeviceId>();
+
+    @Override
+    public Object doRequest(NetconfSession session, String templateName, Map<String, Object> templateContext,
+            String baseXPath, QName returnType) throws NetconfException {
+
+        try {
+            DeviceId deviceId = sessionMap.get(session);
+            Map<String, String> deviceResponses = responses.get(deviceId);
+            String responseTemplate = null;
+            if (deviceResponses != null) {
+                responseTemplate = deviceResponses.get(templateName);
+            }
+            if (responseTemplate == null) {
+                deviceResponses = responses.get(DEFAULT_RESPONSES_ID);
+                if (deviceResponses != null) {
+                    responseTemplate = deviceResponses.get(templateName);
+                }
+            }
+            if (responseTemplate == null) {
+                throw new Exception(
+                        String.format("Reponse template '%s' for device '%s' not found", templateName, deviceId));
+            }
+            InputStream resp = IOUtils.toInputStream(responseTemplate, StandardCharsets.UTF_8);
+            DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
+            DocumentBuilder builder = builderFactory.newDocumentBuilder();
+            Document document = builder.parse(resp);
+            XPath xp = XPathFactory.newInstance().newXPath();
+            return xp.evaluate(baseXPath, document, returnType);
+        } catch (Exception e) {
+            NetconfException ne = new NetconfException(e.getMessage(), e);
+            throw ne;
+        }
+    }
+
+    public void load(Class<? extends Object> reference, String pattern, DeviceId id, String... reponseNames) {
+        for (String name : reponseNames) {
+            String key = name;
+            String resource;
+
+            // If the template name begins with a '/', then assume it is a full path
+            // specification
+            if (name.charAt(0) == '/') {
+                int start = name.lastIndexOf('/') + 1;
+                int end = name.lastIndexOf('.');
+                if (end == -1) {
+                    key = name.substring(start);
+                } else {
+                    key = name.substring(start, end);
+                }
+                resource = name;
+            } else {
+                resource = String.format(pattern, name);
+            }
+
+            log.debug("LOAD RESPONSE TEMPLATE: '{}' as '{}' from '{}'", name, key, resource);
+
+            try {
+                DeviceId use = id;
+                if (use == null) {
+                    use = DEFAULT_RESPONSES_ID;
+                }
+                Map<String, String> deviceResponses = responses.get(use);
+                if (deviceResponses == null) {
+                    deviceResponses = new HashMap<String, String>();
+                    responses.put(use, deviceResponses);
+                }
+                deviceResponses.put(name,
+                        Resources.toString(Resources.getResource(reference, resource), StandardCharsets.UTF_8));
+            } catch (IOException ioe) {
+                log.error("Unable to load NETCONF response template '{}' from '{}'", key, resource, ioe);
+            }
+        }
+    }
+
+    public void setDeviceMap(Map<DeviceId, NetconfDevice> devicesMap) {
+        // sessionMap.clear();
+
+        for (Map.Entry<DeviceId, NetconfDevice> entry : devicesMap.entrySet()) {
+            sessionMap.put(entry.getValue().getSession(), entry.getKey());
+        }
+    }
+}