Added New Test Case to Validate Netconf Device Provider.

Change-Id: Ib92adcfe433580e400dd8c7ecb88a3328e47c31e
diff --git a/providers/netconf/device/pom.xml b/providers/netconf/device/pom.xml
index 0ebe079..ee7ef1f 100644
--- a/providers/netconf/device/pom.xml
+++ b/providers/netconf/device/pom.xml
@@ -58,6 +58,20 @@
             <version>1.1.4</version>
             <optional>true</optional>
         </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onlab-junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.easymock</groupId>
+            <artifactId>easymock</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProvider.java b/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProvider.java
index 5fb6ead..e3399f6 100644
--- a/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProvider.java
+++ b/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProvider.java
@@ -66,7 +66,7 @@
 
     private final Logger log = getLogger(NetconfDeviceProvider.class);
 
-    private Map<DeviceId, NetconfDevice> netconfDeviceMap = new ConcurrentHashMap<DeviceId, NetconfDevice>();
+    protected Map<DeviceId, NetconfDevice> netconfDeviceMap = new ConcurrentHashMap<DeviceId, NetconfDevice>();
 
     private DeviceProviderService providerService;
 
diff --git a/providers/netconf/device/src/test/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProviderTest.java b/providers/netconf/device/src/test/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProviderTest.java
new file mode 100644
index 0000000..7667cc9
--- /dev/null
+++ b/providers/netconf/device/src/test/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProviderTest.java
@@ -0,0 +1,443 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.provider.netconf.device.impl;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.junit.Assert.assertFalse;
+import static org.onlab.util.Tools.delay;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Collection;
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.ChassisId;
+import org.onosproject.cfg.ComponentConfigService;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.MastershipRole;
+import org.onosproject.net.device.DefaultDeviceDescription;
+import org.onosproject.net.device.DeviceDescription;
+import org.onosproject.net.device.DeviceProvider;
+import org.onosproject.net.device.DeviceProviderRegistry;
+import org.onosproject.net.device.DeviceProviderService;
+import org.onosproject.net.device.PortDescription;
+import org.onosproject.net.device.PortStatistics;
+import org.onosproject.net.provider.ProviderId;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+
+import com.tailf.jnc.JNCException;
+
+/**
+ * Test Case to Validate Netconf Device Provider.
+ *
+ */
+public class NetconfDeviceProviderTest {
+    // private NetconfDevice device;
+
+    TestDeviceCreator create;
+
+    private final Logger log = getLogger(NetconfDeviceProviderTest.class);
+
+    private Map<DeviceId, NetconfDevice> netconfDeviceMap = new ConcurrentHashMap<DeviceId, NetconfDevice>();
+
+    private DeviceProviderService providerService;
+
+    private static final int EVENTINTERVAL = 5;
+
+    private static final String SCHEME = "netconf";
+
+    private static final DeviceId DID1 = DeviceId
+            .deviceId("of:0000000000000001");
+
+    private final NetconfDeviceProvider provider = new NetconfDeviceProvider();
+    private final TestDeviceRegistry registry = new TestDeviceRegistry();
+
+    private ComponentConfigService mockCfgService;
+
+    @Before
+    public void setUp() {
+        mockCfgService = EasyMock.createMock(ComponentConfigService.class);
+        provider.cfgService = mockCfgService;
+        provider.providerRegistry = registry;
+    }
+
+    @SuppressWarnings("unchecked")
+    private Dictionary<String, String> getDictionaryMock(ComponentContext componentContext) {
+        Dictionary<String, String> dictionary = EasyMock
+                .createMock(Dictionary.class);
+        expect(dictionary.get("devConfigs"))
+                .andReturn("cisco:cisco@10.18.11.14:22:active,"
+                                   + "sanjay:b33rb3lly@10.18.24.122:2022:inactive");
+        replay(dictionary);
+        expect(componentContext.getProperties()).andReturn(dictionary);
+        return dictionary;
+    }
+
+    @SuppressWarnings("unchecked")
+    private Dictionary<String, String> getDictionaryMockWithoutValues(ComponentContext componentContext) {
+        Dictionary<String, String> dictionary = EasyMock
+                .createMock(Dictionary.class);
+        expect(dictionary.get("devConfigs")).andReturn("");
+        replay(dictionary);
+        expect(componentContext.getProperties()).andReturn(dictionary);
+        return dictionary;
+    }
+
+    @SuppressWarnings("unchecked")
+    private Dictionary<String, String> getDictionaryMockWithDeviceEntryNull(ComponentContext componentContext) {
+        Dictionary<String, String> dictionary = EasyMock
+                .createMock(Dictionary.class);
+        expect(dictionary.get("devConfigs")).andReturn("null,null");
+        replay(dictionary);
+        expect(componentContext.getProperties()).andReturn(dictionary);
+        return dictionary;
+    }
+
+    @SuppressWarnings("unchecked")
+    private Dictionary<String, String> getDictionaryMockDeviceEntryNumberFomatEx(ComponentContext componentContext) {
+        Dictionary<String, String> dictionary = EasyMock
+                .createMock(Dictionary.class);
+        expect(dictionary.get("devConfigs"))
+                .andReturn("cisco:cisco@10.18.11.14:cisco:active")
+                .andThrow(new NumberFormatException());
+        replay(dictionary);
+        expect(componentContext.getProperties()).andReturn(dictionary);
+        return dictionary;
+    }
+
+    @SuppressWarnings("unchecked")
+    private Dictionary<String, String> getDictionaryMockWithoutUsernameAndPassword(ComponentContext componentContext) {
+        Dictionary<String, String> dictionary = EasyMock
+                .createMock(Dictionary.class);
+        expect(dictionary.get("devConfigs"))
+                .andReturn("null:null@null:0:active");
+        replay(dictionary);
+        expect(componentContext.getProperties()).andReturn(dictionary);
+        return dictionary;
+    }
+
+    @SuppressWarnings("unchecked")
+    private Dictionary<String, String> getDictionaryMockWithDifferentDeviceState(ComponentContext componentContext) {
+        Dictionary<String, String> dictionary = EasyMock
+                .createMock(Dictionary.class);
+        expect(dictionary.get("devConfigs"))
+                .andReturn("cisco:cisco@10.18.11.14:22:active,cisco:cisco@10.18.11.18:22:inactive,"
+                                   + "cisco:cisco@10.18.11.14:22:invalid,cisco:cisco@10.18.11.14:22:null");
+        replay(dictionary);
+        expect(componentContext.getProperties()).andReturn(dictionary);
+        return dictionary;
+    }
+
+    @SuppressWarnings("unchecked")
+    private Dictionary<String, String> getDictionaryMockDeviceWithArrayOutOFBoundEx(ComponentContext componentContext) {
+        Dictionary<String, String> dictionary = EasyMock
+                .createMock(Dictionary.class);
+        expect(dictionary.get("devConfigs"))
+                .andReturn("@10.18.11.14:22:active")
+                .andThrow(new ArrayIndexOutOfBoundsException());
+        replay(dictionary);
+        expect(componentContext.getProperties()).andReturn(dictionary);
+        return dictionary;
+    }
+
+    @SuppressWarnings("unchecked")
+    private Dictionary<String, String> getDictionaryMockDeviceEntryForDeactivate(ComponentContext componentContext) {
+        Dictionary<String, String> dictionary = EasyMock
+                .createMock(Dictionary.class);
+        expect(dictionary.get("devConfigs"))
+                .andReturn("netconf:cisco@10.18.11.14:22:active")
+                .andThrow(new ArrayIndexOutOfBoundsException());
+        replay(dictionary);
+        expect(componentContext.getProperties()).andReturn(dictionary);
+        return dictionary;
+    }
+
+    @Test(expected = IOException.class)
+    public void testSSHAuthentication() throws IOException, JNCException {
+        TestDeviceCreator objForTestDev = new TestDeviceCreator(
+                                                                new NetconfDevice(
+                                                                                  "10.18.14.19",
+                                                                                  22,
+                                                                                  "cisco",
+                                                                                  "cisco"),
+                                                                true);
+        objForTestDev.run();
+    }
+
+    @After
+    public void tearDown() {
+        provider.providerRegistry = null;
+        provider.cfgService = null;
+    }
+
+    @Test
+    public void testActiveWithComponentContext() {
+
+        ComponentContext componentContext = EasyMock
+                .createMock(ComponentContext.class);
+        getDictionaryMock(componentContext);
+        replay(componentContext);
+        provider.activate(componentContext);
+    }
+
+    // To check if deviceCfgValue is empty or null
+    @Test
+    public void testActiveWithcomponentContextIsNull() {
+
+        ComponentContext componentContext = EasyMock
+                .createMock(ComponentContext.class);
+        getDictionaryMockWithoutValues(componentContext);
+        replay(componentContext);
+        provider.activate(componentContext);
+    }
+
+    // To check deviceEntry and device is null
+    @Test
+    public void testActiveWithDeviceEntryIsNull() {
+
+        ComponentContext componentContext = EasyMock
+                .createMock(ComponentContext.class);
+        getDictionaryMockWithDeviceEntryNull(componentContext);
+        replay(componentContext);
+        provider.activate(componentContext);
+    }
+
+    @Test
+    public void testActiveWithDeviceEntryWithoutUsernameAndPassword() {
+
+        ComponentContext componentContext = EasyMock
+                .createMock(ComponentContext.class);
+        getDictionaryMockWithoutUsernameAndPassword(componentContext);
+        replay(componentContext);
+        provider.activate(componentContext);
+    }
+
+    @Test
+    public void testActiveWithDeviceEntryWithNumberFomatEx() {
+
+        ComponentContext componentContext = EasyMock
+                .createMock(ComponentContext.class);
+        getDictionaryMockDeviceEntryNumberFomatEx(componentContext);
+        replay(componentContext);
+        provider.activate(componentContext);
+    }
+
+    @Test
+    public void testActiveWithDeviceEntryWithDifferentDeviceState() {
+
+        ComponentContext componentContext = EasyMock
+                .createMock(ComponentContext.class);
+        getDictionaryMockWithDifferentDeviceState(componentContext);
+        replay(componentContext);
+        provider.activate(componentContext);
+    }
+
+    @Test
+    public void testActiveWithDeviceEntryWithArrayOutOFBoundEx() {
+
+        ComponentContext componentContext = EasyMock
+                .createMock(ComponentContext.class);
+        getDictionaryMockDeviceWithArrayOutOFBoundEx(componentContext);
+        replay(componentContext);
+        provider.activate(componentContext);
+    }
+
+    @Test
+    public void isReachableWithInvalidDeviceId() {
+        assertFalse("Initially the Device ID Should not be reachable",
+                    provider.isReachable(DID1));
+        NetconfDevice device = new NetconfDevice("", 0, "", "");
+        provider.netconfDeviceMap.put(DID1, device);
+        assertFalse("Particular Device ID cannot be Reachable",
+                    provider.isReachable(DID1));
+    }
+
+    @Test
+    public void testDeactivate() {
+
+        ComponentContext componentContext = EasyMock
+                .createMock(ComponentContext.class);
+        getDictionaryMockDeviceEntryForDeactivate(componentContext);
+        replay(componentContext);
+        testActiveWithComponentContext();
+        provider.deactivate(componentContext);
+    }
+
+    private class TestDeviceCreator {
+
+        private NetconfDevice device;
+        private boolean createFlag;
+
+        public TestDeviceCreator(NetconfDevice device, boolean createFlag) {
+            this.device = device;
+            this.createFlag = createFlag;
+        }
+
+        public void run() throws JNCException, IOException {
+            if (createFlag) {
+                log.info("Trying to create Device Info on ONOS core");
+                advertiseDevices();
+            } else {
+                log.info("Trying to remove Device Info on ONOS core");
+                removeDevices();
+            }
+        }
+
+        /**
+         * For each Netconf Device, remove the entry from the device store.
+         * @throws URISyntaxException
+         */
+        private void removeDevices() {
+            if (device == null) {
+                log.warn("The Request Netconf Device is null, cannot proceed further");
+                return;
+            }
+            try {
+                DeviceId did = getDeviceId();
+                if (!netconfDeviceMap.containsKey(did)) {
+                    log.error("BAD Request: 'Currently device is not discovered, "
+                            + "so cannot remove/disconnect the device: "
+                            + device.deviceInfo() + "'");
+                    return;
+                }
+                providerService.deviceDisconnected(did);
+                device.disconnect();
+                netconfDeviceMap.remove(did);
+                delay(EVENTINTERVAL);
+            } catch (URISyntaxException uriSyntaxExcpetion) {
+                log.error("Syntax Error while creating URI for the device: "
+                                  + device.deviceInfo()
+                                  + " couldn't remove the device from the store",
+                          uriSyntaxExcpetion);
+            }
+        }
+
+        /**
+         * Initialize Netconf Device object, and notify core saying device
+         * connected.
+         */
+        private void advertiseDevices() throws JNCException, IOException {
+            try {
+                if (device == null) {
+                    log.warn("The Request Netconf Device is null, cannot proceed further");
+                    return;
+                }
+                device.init();
+                DeviceId did = getDeviceId();
+                ChassisId cid = new ChassisId();
+                DeviceDescription desc = new DefaultDeviceDescription(
+                                                                      did.uri(),
+                                                                      Device.Type.OTHER,
+                                                                      "", "",
+                                                                      "", "",
+                                                                      cid);
+                log.info("Persisting Device" + did.uri().toString());
+
+                netconfDeviceMap.put(did, device);
+                providerService.deviceConnected(did, desc);
+                log.info("Done with Device Info Creation on ONOS core. Device Info: "
+                        + device.deviceInfo() + " " + did.uri().toString());
+                delay(EVENTINTERVAL);
+            } catch (URISyntaxException e) {
+                log.error("Syntax Error while creating URI for the device: "
+                        + device.deviceInfo()
+                        + " couldn't persist the device onto the store", e);
+            } catch (JNCException e) {
+                throw e;
+            } catch (IOException e) {
+                throw e;
+            } catch (Exception e) {
+                log.error("Error while initializing session for the device: "
+                        + device.deviceInfo(), e);
+            }
+        }
+
+        private DeviceId getDeviceId() throws URISyntaxException {
+            String additionalSSP = new StringBuilder(device.getUsername())
+                    .append("@").append(device.getSshHost()).append(":")
+                    .append(device.getSshPort()).toString();
+            DeviceId did = DeviceId.deviceId(new URI(SCHEME, additionalSSP,
+                                                     null));
+            return did;
+        }
+    }
+
+    private class TestDeviceRegistry implements DeviceProviderRegistry {
+
+        @Override
+        public DeviceProviderService register(DeviceProvider provider) {
+            return new TestProviderService();
+        }
+
+        @Override
+        public void unregister(DeviceProvider provider) {
+        }
+
+        @Override
+        public Set<ProviderId> getProviders() {
+            return null;
+        }
+
+        private class TestProviderService implements DeviceProviderService {
+
+            public DeviceProvider provider() {
+                return null;
+            }
+
+            public void deviceConnected(DeviceId deviceId,
+                                        DeviceDescription deviceDescription) {
+            }
+
+            public void deviceDisconnected(DeviceId deviceId) {
+
+            }
+
+            public void updatePorts(DeviceId deviceId,
+                                    List<PortDescription> portDescriptions) {
+
+            }
+
+            public void portStatusChanged(DeviceId deviceId,
+                                          PortDescription portDescription) {
+
+            }
+
+            public void receivedRoleReply(DeviceId deviceId,
+                                          MastershipRole requested,
+                                          MastershipRole response) {
+
+            }
+
+            public void updatePortStatistics(DeviceId deviceId,
+                                             Collection<PortStatistics> portStatistics) {
+
+            }
+        }
+    }
+}