Unit testing code for the Netconf Controller.

Change-Id: Id6e4097768562888e76b1a101b2d85ee9e6841d9
diff --git a/protocols/netconf/ctl/src/test/java/org/onosproject/netconf/ctl/NetconfControllerImplTest.java b/protocols/netconf/ctl/src/test/java/org/onosproject/netconf/ctl/NetconfControllerImplTest.java
new file mode 100644
index 0000000..87bdda0
--- /dev/null
+++ b/protocols/netconf/ctl/src/test/java/org/onosproject/netconf/ctl/NetconfControllerImplTest.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright 2016 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.netconf.ctl;
+
+import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.IpAddress;
+import org.onosproject.net.DeviceId;
+import org.onosproject.netconf.NetconfDevice;
+import org.onosproject.netconf.NetconfDeviceFactory;
+import org.onosproject.netconf.NetconfDeviceInfo;
+import org.onosproject.netconf.NetconfDeviceListener;
+import org.onosproject.netconf.NetconfDeviceOutputEvent;
+import org.onosproject.netconf.NetconfDeviceOutputEventListener;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+
+import java.lang.reflect.Field;
+import java.util.Map;
+import java.util.Optional;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+/**
+ * Unit tests for the Netconf controller implementation test.
+ */
+public class NetconfControllerImplTest {
+    NetconfControllerImpl ctrl;
+
+    //DeviceInfo
+    NetconfDeviceInfo deviceInfo1;
+    NetconfDeviceInfo deviceInfo2;
+    NetconfDeviceInfo badDeviceInfo3;
+
+    //Devices & DeviceId
+    NetconfDevice device1;
+    DeviceId deviceId1;
+    NetconfDevice device2;
+    DeviceId deviceId2;
+
+    //Events
+    NetconfDeviceOutputEvent eventForDeviceInfo1;
+    NetconfDeviceOutputEvent eventForDeviceInfo2;
+
+    private Map<DeviceId, NetconfDevice> reflectedDeviceMap;
+    private NetconfDeviceOutputEventListener reflectedDownListener;
+
+    //Test Device IP addresses and ports
+    private static final String DEVICE_1_IP = "10.10.10.11";
+    private static final String DEVICE_2_IP = "10.10.10.12";
+    private static final String BAD_DEVICE_IP = "10.10.10.13";
+
+    private static final int DEVICE_1_PORT = 11;
+    private static final int DEVICE_2_PORT = 12;
+    private static final int BAD_DEVICE_PORT = 13;
+
+
+    @Before
+    public void setUp() throws Exception {
+        ctrl = new NetconfControllerImpl();
+        ctrl.deviceFactory = new TestNetconfDeviceFactory();
+
+        //Creating mock devices
+        deviceInfo1 = new NetconfDeviceInfo("device1", "001", IpAddress.valueOf(DEVICE_1_IP), DEVICE_1_PORT);
+        deviceInfo2 = new NetconfDeviceInfo("device2", "002", IpAddress.valueOf(DEVICE_2_IP), DEVICE_2_PORT);
+        badDeviceInfo3 = new NetconfDeviceInfo("device3", "003", IpAddress.valueOf(BAD_DEVICE_IP), BAD_DEVICE_PORT);
+
+        device1 = new TestNetconfDevice(deviceInfo1);
+        deviceId1 = deviceInfo1.getDeviceId();
+        device2 = new TestNetconfDevice(deviceInfo2);
+        deviceId2 = deviceInfo2.getDeviceId();
+
+        //Adding to the map for testing get device calls.
+        Field field1 = ctrl.getClass().getDeclaredField("netconfDeviceMap");
+        field1.setAccessible(true);
+        reflectedDeviceMap = (Map<DeviceId, NetconfDevice>) field1.get(ctrl);
+        reflectedDeviceMap.put(deviceId1, device1);
+        reflectedDeviceMap.put(deviceId2, device2);
+
+        //Creating mock events for testing NetconfDeviceOutputEventListener
+        Field field2 = ctrl.getClass().getDeclaredField("downListener");
+        field2.setAccessible(true);
+        reflectedDownListener = (NetconfDeviceOutputEventListener) field2.get(ctrl);
+
+        eventForDeviceInfo1 = new NetconfDeviceOutputEvent(NetconfDeviceOutputEvent.Type.DEVICE_NOTIFICATION, null,
+                null, Optional.of(1), deviceInfo1);
+        eventForDeviceInfo2 = new NetconfDeviceOutputEvent(NetconfDeviceOutputEvent.Type.DEVICE_UNREGISTERED, null,
+                null, Optional.of(2), deviceInfo2);
+    }
+
+    @After
+    public void tearDown() {
+        ctrl.deactivate();
+    }
+
+    /**
+     * Test to add DeviceListeners,
+     * and also to check whether the netconfDeviceListeners set is
+     * updating or not which was present in NetconfControllerImpl class.
+     */
+    @Test
+    public void testAddRemoveDeviceListener() {
+        NetconfDeviceListener deviceListener1 = EasyMock.createMock(NetconfDeviceListener.class);
+        NetconfDeviceListener deviceListener2 = EasyMock.createMock(NetconfDeviceListener.class);
+        NetconfDeviceListener deviceListener3 = EasyMock.createMock(NetconfDeviceListener.class);
+
+        ctrl.addDeviceListener(deviceListener1);
+        ctrl.addDeviceListener(deviceListener2);
+        ctrl.addDeviceListener(deviceListener3);
+        assertThat("Incorrect number of listeners", ctrl.netconfDeviceListeners, hasSize(3));
+        assertThat("Not matching listeners", ctrl.netconfDeviceListeners, hasItems(deviceListener1,
+                deviceListener2, deviceListener3));
+
+        ctrl.removeDeviceListener(deviceListener1);
+        assertThat("Incorrect number of listeners", ctrl.netconfDeviceListeners, hasSize(2));
+        assertThat("Not matching listeners", ctrl.netconfDeviceListeners, hasItems(deviceListener2, deviceListener3));
+    }
+
+    @Test
+    public void testGetNetconfDevice() {
+        NetconfDevice fetchedDevice1 = ctrl.getNetconfDevice(deviceId1);
+        assertThat("Incorrect device fetched", fetchedDevice1, is(device1));
+
+        NetconfDevice fetchedDevice2 = ctrl.getNetconfDevice(deviceId2);
+        assertThat("Incorrect device fetched", fetchedDevice2, is(device2));
+    }
+
+    @Test
+    public void testGetNetconfDeviceWithIPPort() {
+        NetconfDevice fetchedDevice1 = ctrl.getNetconfDevice(IpAddress.valueOf(DEVICE_1_IP), DEVICE_1_PORT);
+        assertEquals("Incorrect device fetched", fetchedDevice1.getDeviceInfo().ip(), device1.getDeviceInfo().ip());
+
+        NetconfDevice fetchedDevice2 = ctrl.getNetconfDevice(IpAddress.valueOf(DEVICE_2_IP), DEVICE_2_PORT);
+        assertEquals("Incorrect device fetched", fetchedDevice2.getDeviceInfo().ip(), device2.getDeviceInfo().ip());
+    }
+
+    /**
+     * Check for bad device connection. In this case the device map shouldn't get modified.
+     */
+    @Test(expected = NetconfException.class)
+    public void testConnectBadDevice() throws Exception {
+        reflectedDeviceMap.clear();
+        try {
+            ctrl.connectDevice(badDeviceInfo3);
+        } finally {
+            assertEquals("Incorrect device connection", 0, ctrl.getDevicesMap().size());
+        }
+    }
+
+    /**
+     * Check for correct device connection. In this case the device map get modified.
+     */
+    @Test
+    public void testConnectCorrectDevice() throws Exception {
+        reflectedDeviceMap.clear();
+        ctrl.connectDevice(deviceInfo1);
+        ctrl.connectDevice(deviceInfo2);
+        assertTrue("Incorrect device connection", ctrl.getDevicesMap().containsKey(deviceId1));
+        assertTrue("Incorrect device connection", ctrl.getDevicesMap().containsKey(deviceId2));
+        assertEquals("Incorrect device connection", 2, ctrl.getDevicesMap().size());
+    }
+
+
+    /**
+     * Check for connect devices already added to the map.
+     */
+    @Test
+    public void testConnectAlreadyExistingDevice() throws Exception {
+        NetconfDevice alreadyExistingDevice1 = ctrl.connectDevice(deviceInfo1);
+        NetconfDevice alreadyExistingDevice2 = ctrl.connectDevice(deviceInfo2);
+        assertEquals("Incorrect device connection", alreadyExistingDevice1.getDeviceInfo().getDeviceId(),
+                deviceInfo1.getDeviceId());
+        assertEquals("Incorrect device connection", alreadyExistingDevice2.getDeviceInfo().getDeviceId(),
+                deviceInfo2.getDeviceId());
+    }
+
+    /**
+     * Check for removeDevice exception.
+     */
+    @Test
+    public void testRemoveDevice() throws Exception {
+        ctrl.removeDevice(deviceInfo1);
+        assertFalse("Incorrect device removal", ctrl.getDevicesMap().containsKey(deviceId1));
+    }
+
+    /**
+     * Test to get the connected device map.
+     */
+    @Test
+    public void testGetDevicesMap() {
+        assertEquals("Incorrect device map size", 2, ctrl.getDevicesMap().size());
+    }
+
+    /**
+     * Test to check whether the DeviceDownEventListener removes the device from the map when session
+     * for a particular device getting closed.
+     */
+    @Test
+    public void testDeviceDownEventListener() throws Exception {
+        reflectedDeviceMap.clear();
+        ctrl.connectDevice(deviceInfo1);
+        boolean result1 = reflectedDownListener.isRelevant(eventForDeviceInfo2);
+        assertFalse("Irrelevant Device Event", result1);
+        assertEquals("Incorrect device map size", 1, ctrl.getDevicesMap().size());
+        reflectedDownListener.event(eventForDeviceInfo1);
+        assertEquals("Incorrect device map size", 1, ctrl.getDevicesMap().size());
+        ctrl.connectDevice(deviceInfo2);
+        boolean result2 = reflectedDownListener.isRelevant(eventForDeviceInfo2);
+        assertTrue("Irrelevant Device Event", result2);
+        assertEquals("Incorrect device map size", 2, ctrl.getDevicesMap().size());
+        reflectedDownListener.event(eventForDeviceInfo2);
+        assertEquals("Incorrect device map size", 1, ctrl.getDevicesMap().size());
+    }
+
+    /**
+     * Mock NetconfDeviceFactory class.
+     */
+    private class TestNetconfDeviceFactory implements NetconfDeviceFactory {
+
+        @Override
+        public NetconfDevice createNetconfDevice(NetconfDeviceInfo netconfDeviceInfo) throws NetconfException {
+            return new TestNetconfDevice(netconfDeviceInfo);
+        }
+    }
+
+    /**
+     * Mock NetconfDeviceImpl class, used for creating test devices.
+     */
+    protected class TestNetconfDevice implements NetconfDevice {
+        private NetconfDeviceInfo netconfDeviceInfo;
+        private boolean deviceState = false;
+        private NetconfSession netconfSession;
+
+        public TestNetconfDevice(NetconfDeviceInfo deviceInfo) throws NetconfException {
+            netconfDeviceInfo = deviceInfo;
+            if (netconfDeviceInfo.ip() != badDeviceInfo3.ip()) {
+                netconfSession = EasyMock.createMock(NetconfSession.class);
+                deviceState = true;
+            } else {
+                throw new NetconfException("Cannot create Connection and Session");
+            }
+        }
+
+        @Override
+        public boolean isActive() {
+            return deviceState;
+        }
+
+        @Override
+        public NetconfSession getSession() {
+            return netconfSession;
+        }
+
+        @Override
+        public void disconnect() {
+            deviceState = false;
+            netconfSession = null;
+        }
+
+        @Override
+        public NetconfDeviceInfo getDeviceInfo() {
+            return netconfDeviceInfo;
+        }
+
+    }
+}
diff --git a/protocols/netconf/pom.xml b/protocols/netconf/pom.xml
index 19b79c3..d46582e 100644
--- a/protocols/netconf/pom.xml
+++ b/protocols/netconf/pom.xml
@@ -53,6 +53,11 @@
             <artifactId>onos-api</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.easymock</groupId>
+            <artifactId>easymock</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
 </project>