cord-486 TestClass added

Change-Id: Ic1ce77cde4d728fbc0cb17178cc6ed2b5c5c714e
diff --git a/apps/routing/src/test/java/org/onosproject/routing/impl/ControlPlaneRedirectManagerTest.java b/apps/routing/src/test/java/org/onosproject/routing/impl/ControlPlaneRedirectManagerTest.java
new file mode 100644
index 0000000..b6b9808
--- /dev/null
+++ b/apps/routing/src/test/java/org/onosproject/routing/impl/ControlPlaneRedirectManagerTest.java
@@ -0,0 +1,554 @@
+/*
+ * 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.routing.impl;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+import org.easymock.EasyMock;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.EthType;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.core.CoreServiceAdapter;
+import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.intf.InterfaceService;
+import org.onosproject.mastership.MastershipService;
+import org.onosproject.mastership.MastershipServiceAdapter;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.NetTestTools;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.config.Config;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigEvent.Type;
+import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.net.config.NetworkConfigServiceAdapter;
+import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.device.DeviceListener;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.device.DeviceServiceAdapter;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.DefaultNextObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.NextObjective;
+import org.onosproject.net.host.HostListener;
+import org.onosproject.net.host.HostService;
+import org.onosproject.net.host.HostServiceAdapter;
+import org.onosproject.net.host.InterfaceIpAddress;
+import org.onosproject.net.intent.AbstractIntentTest;
+import org.onosproject.routing.RoutingService;
+import org.onosproject.routing.config.RouterConfig;
+import org.slf4j.Logger;
+
+import com.google.common.collect.Sets;
+
+/**
+ * UnitTests for ControlPlaneRedirectManager.
+ */
+public class ControlPlaneRedirectManagerTest extends AbstractIntentTest {
+
+    private final Logger log = getLogger(getClass());
+
+    private DeviceService deviceService;
+    private FlowObjectiveService flowObjectiveService;
+    private NetworkConfigService networkConfigService;
+    private final Set<Interface> interfaces = Sets.newHashSet();
+    static Device dev3 = NetTestTools.device("0000000000000001");
+    private static final int OSPF_IP_PROTO = 0x59;
+    private CoreService coreService = new TestCoreService();
+    private InterfaceService interfaceService;
+    private static final ApplicationId APPID = TestApplicationId.create("org.onosproject.cpredirect");
+
+    /**
+     * Interface Configuration.
+     *
+     **/
+    private ConnectPoint controlPlaneConnectPoint = new ConnectPoint(DeviceId.deviceId("of:0000000000000001"),
+            PortNumber.portNumber(1));
+    private static final ConnectPoint SW1_ETH1 = new ConnectPoint(DeviceId.deviceId("of:0000000000000001"),
+            PortNumber.portNumber(1));
+
+    private static final ConnectPoint SW1_ETH2 = new ConnectPoint(DeviceId.deviceId("of:0000000000000001"),
+            PortNumber.portNumber(2));
+
+    private static final ConnectPoint SW1_ETH3 = new ConnectPoint(DeviceId.deviceId("of:0000000000000001"),
+            PortNumber.portNumber(3));
+    protected HostService hostService;
+
+    private ControlPlaneRedirectManager controlPlaneRedirectManager = new ControlPlaneRedirectManager();;
+    private RouterConfig routerConfig = new TestRouterConfig();
+    private NetworkConfigListener networkConfigListener;
+    private DeviceListener deviceListener;
+    private MastershipService mastershipService = new InternalMastershipServiceTest();
+    private HostListener hostListener;
+
+    /**
+     * @throws java.lang.Exception
+     */
+    @Override
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        interfaceService = createMock(InterfaceService.class);
+        networkConfigListener = createMock(NetworkConfigListener.class);
+        hostService = new TestHostService();
+        deviceService = new TestDeviceService();
+        deviceListener = createMock(DeviceListener.class);
+        hostListener = createMock(HostListener.class);
+        hostService.addListener(hostListener);
+        deviceService.addListener(deviceListener);
+        setUpInterfaceService();
+        networkConfigService = new TestNetworkConfigService();
+        networkConfigService.addListener(networkConfigListener);
+        flowObjectiveService = createMock(FlowObjectiveService.class);
+        setUpFlowObjectiveService();
+
+        controlPlaneRedirectManager.coreService = coreService;
+        controlPlaneRedirectManager.flowObjectiveService = flowObjectiveService;
+        controlPlaneRedirectManager.networkConfigService = networkConfigService;
+        controlPlaneRedirectManager.interfaceService = interfaceService;
+        controlPlaneRedirectManager.deviceService = deviceService;
+        controlPlaneRedirectManager.hostService = hostService;
+        controlPlaneRedirectManager.mastershipService = mastershipService;
+        controlPlaneRedirectManager.activate();
+        verify(flowObjectiveService);
+    }
+    /**
+     * setup flow Configuration for all configured Interfaces.
+     *
+     **/
+    private void setUpFlowObjectiveService() {
+
+        expect(flowObjectiveService.allocateNextId()).andReturn(1).anyTimes();
+        DeviceId deviceId = controlPlaneConnectPoint.deviceId();
+        PortNumber controlPlanePort = controlPlaneConnectPoint.port();
+        int cpNextId, intfNextId;
+        for (Interface intf : interfaceService.getInterfaces()) {
+            for (InterfaceIpAddress ip : intf.ipAddresses()) {
+                if (intf.vlan() == VlanId.NONE) {
+                    // cpNextId = 1;
+                    // intfNextId = 1;
+                    cpNextId = createNextObjective(deviceId, controlPlanePort,
+                            VlanId.vlanId(SingleSwitchFibInstaller.ASSIGNED_VLAN), true);
+                    intfNextId = createNextObjective(deviceId, intf.connectPoint().port(),
+                            VlanId.vlanId(SingleSwitchFibInstaller.ASSIGNED_VLAN), true);
+                } else {
+                    // cpNextId = 1;
+                    // intfNextId = 1;
+
+                    cpNextId = createNextObjective(deviceId, controlPlanePort, intf.vlan(), false);
+                    intfNextId = createNextObjective(deviceId, intf.connectPoint().port(), intf.vlan(), false);
+                }
+                TrafficSelector toSelector = DefaultTrafficSelector.builder().matchInPort(intf.connectPoint().port())
+                        .matchEthDst(intf.mac()).matchEthType(EthType.EtherType.IPV4.ethType().toShort())
+                        .matchVlanId(intf.vlan()).matchIPDst(ip.ipAddress().toIpPrefix()).build();
+                flowObjectiveService.forward(deviceId, buildForwardingObjective(toSelector, null, cpNextId, true));
+                expectLastCall().once();
+                // IPv4 from router
+                TrafficSelector fromSelector = DefaultTrafficSelector.builder().matchInPort(controlPlanePort)
+                        .matchEthSrc(intf.mac()).matchVlanId(intf.vlan())
+                        .matchEthType(EthType.EtherType.IPV4.ethType().toShort())
+                        .matchIPSrc(ip.ipAddress().toIpPrefix()).build();
+                flowObjectiveService.forward(deviceId, buildForwardingObjective(fromSelector, null, intfNextId, true));
+                expectLastCall().once();
+                // ARP to router
+                toSelector = DefaultTrafficSelector.builder().matchInPort(intf.connectPoint().port())
+                        .matchEthType(EthType.EtherType.ARP.ethType().toShort()).matchVlanId(intf.vlan()).build();
+
+                TrafficTreatment puntTreatment = DefaultTrafficTreatment.builder().punt().build();
+                flowObjectiveService.forward(deviceId,
+                        buildForwardingObjective(toSelector, puntTreatment, cpNextId, true));
+                expectLastCall().once();
+                // ARP from router
+                fromSelector = DefaultTrafficSelector.builder().matchInPort(controlPlanePort).matchEthSrc(intf.mac())
+                        .matchVlanId(intf.vlan()).matchEthType(EthType.EtherType.ARP.ethType().toShort())
+                        .matchArpSpa(ip.ipAddress().getIp4Address()).build();
+                flowObjectiveService.forward(deviceId,
+                        buildForwardingObjective(fromSelector, puntTreatment, intfNextId, true));
+                expectLastCall().once();
+
+            }
+            updateOspfForwarding(intf);
+        }
+
+        replay(flowObjectiveService);
+    }
+
+    /**
+     * setup expectations on flowobjectService.forward for ospfForwarding.
+     *
+     **/
+    private void updateOspfForwarding(Interface intf) {
+        // OSPF to router
+        TrafficSelector toSelector = DefaultTrafficSelector.builder().matchInPort(intf.connectPoint().port())
+                .matchEthType(EthType.EtherType.IPV4.ethType().toShort()).matchVlanId(intf.vlan())
+                .matchIPProtocol((byte) OSPF_IP_PROTO).build();
+
+        PortNumber controlPlanePort = controlPlaneConnectPoint.port();
+        DeviceId deviceId = controlPlaneConnectPoint.deviceId();
+        int cpNextId;
+        if (intf.vlan() == VlanId.NONE) {
+            cpNextId = createNextObjective(deviceId, controlPlanePort,
+                    VlanId.vlanId(SingleSwitchFibInstaller.ASSIGNED_VLAN), true);
+        } else {
+            cpNextId = createNextObjective(deviceId, controlPlanePort, intf.vlan(), false);
+        }
+        log.debug("ospf flows intf:{} nextid:{}", intf, cpNextId);
+        flowObjectiveService.forward(controlPlaneConnectPoint.deviceId(),
+                buildForwardingObjective(toSelector, null, cpNextId, true));
+        expectLastCall().once();
+    }
+
+    /**
+     * setup expectations on flowObjectiveService.next for NextObjective.
+     *
+     **/
+    private int createNextObjective(DeviceId deviceId, PortNumber portNumber, VlanId vlanId, boolean popVlan) {
+
+        NextObjective.Builder nextObjBuilder = DefaultNextObjective.builder().withId(1)
+                .withType(NextObjective.Type.SIMPLE).fromApp(APPID);
+
+        TrafficTreatment.Builder ttBuilder = DefaultTrafficTreatment.builder();
+        if (popVlan) {
+            ttBuilder.popVlan();
+        }
+        ttBuilder.setOutput(portNumber);
+
+        // setup metadata to pass to nextObjective - indicate the vlan on egress
+        // if needed by the switch pipeline.
+        TrafficSelector.Builder metabuilder = DefaultTrafficSelector.builder();
+        metabuilder.matchVlanId(vlanId);
+
+        nextObjBuilder.withMeta(metabuilder.build());
+        nextObjBuilder.addTreatment(ttBuilder.build());
+        log.debug("Submited next objective {} in device {} for port/vlan {}/{}", 1, deviceId, portNumber, vlanId);
+        flowObjectiveService.next(deviceId, nextObjBuilder.add());
+        expectLastCall().once();
+        return 1;
+    }
+
+    /**
+     * setup Interface expectation for all Testcases.
+     *
+     **/
+    private void setUpInterfaceService() {
+
+        Set<InterfaceIpAddress> interfaceIpAddresses1 = Sets.newHashSet();
+        interfaceIpAddresses1
+                .add(new InterfaceIpAddress(IpAddress.valueOf("192.168.10.101"), IpPrefix.valueOf("192.168.10.0/24")));
+        Interface sw1Eth1 = new Interface(SW1_ETH1.deviceId().toString(), SW1_ETH1, interfaceIpAddresses1,
+                MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE);
+        interfaces.add(sw1Eth1);
+
+        Set<InterfaceIpAddress> interfaceIpAddresses2 = Sets.newHashSet();
+        interfaceIpAddresses2
+                .add(new InterfaceIpAddress(IpAddress.valueOf("192.168.20.101"), IpPrefix.valueOf("192.168.20.0/24")));
+        Interface sw1Eth2 = new Interface(SW1_ETH1.deviceId().toString(), SW1_ETH2, interfaceIpAddresses2,
+                MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE);
+        interfaces.add(sw1Eth2);
+
+        Set<InterfaceIpAddress> interfaceIpAddresses3 = Sets.newHashSet();
+        interfaceIpAddresses3
+                .add(new InterfaceIpAddress(IpAddress.valueOf("192.168.30.101"), IpPrefix.valueOf("192.168.30.0/24")));
+        Interface sw1Eth3 = new Interface(SW1_ETH1.deviceId().toString(), SW1_ETH3, interfaceIpAddresses3,
+                MacAddress.valueOf("00:00:00:00:00:03"), VlanId.NONE);
+        interfaces.add(sw1Eth3);
+
+        expect(interfaceService.getInterfacesByPort(SW1_ETH1)).andReturn(Collections.singleton(sw1Eth1)).anyTimes();
+        expect(interfaceService.getMatchingInterface(Ip4Address.valueOf("192.168.10.1"))).andReturn(sw1Eth1).anyTimes();
+        expect(interfaceService.getInterfacesByPort(SW1_ETH2)).andReturn(Collections.singleton(sw1Eth2)).anyTimes();
+        expect(interfaceService.getMatchingInterface(Ip4Address.valueOf("192.168.20.1"))).andReturn(sw1Eth2).anyTimes();
+
+        expect(interfaceService.getInterfacesByPort(SW1_ETH3)).andReturn(Collections.singleton(sw1Eth3)).anyTimes();
+        expect(interfaceService.getMatchingInterface(Ip4Address.valueOf("192.168.30.1"))).andReturn(sw1Eth3).anyTimes();
+        expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
+        replay(interfaceService);
+        interfaceService.getInterfaces();
+        verify(interfaceService);
+    }
+
+    /**
+     * Tests adding new Device to a  controlplane.
+     *
+     * @throws SecurityException
+     * @throws NoSuchFieldException
+     * @throws IllegalAccessException
+     * @throws IllegalArgumentException
+     */
+
+    @Test
+    public void testAddDevice()
+            throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
+
+        ConnectPoint sw1eth4 = new ConnectPoint(DeviceId.deviceId("of:0000000000000001"), PortNumber.portNumber(4));
+        Set<InterfaceIpAddress> interfaceIpAddresses4 = Sets.newHashSet();
+        interfaceIpAddresses4
+                .add(new InterfaceIpAddress(IpAddress.valueOf("192.168.40.101"), IpPrefix.valueOf("192.168.40.0/24")));
+
+        Interface sw1Eth4 = new Interface(sw1eth4.deviceId().toString(), sw1eth4, interfaceIpAddresses4,
+                MacAddress.valueOf("00:00:00:00:00:04"), VlanId.NONE);
+        interfaces.add(sw1Eth4);
+        EasyMock.reset(interfaceService);
+        expect(interfaceService.getInterfacesByPort(sw1eth4)).andReturn(Collections.singleton(sw1Eth4)).anyTimes();
+        expect(interfaceService.getMatchingInterface(Ip4Address.valueOf("192.168.40.1"))).andReturn(sw1Eth4).anyTimes();
+        expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
+        replay(interfaceService);
+        interfaceService.getInterfaces();
+        EasyMock.reset(flowObjectiveService);
+        setUpFlowObjectiveService();
+        deviceListener.event(new DeviceEvent(DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED, dev3));
+        deviceService.addListener(deviceListener);
+
+        verify(flowObjectiveService);
+    }
+
+    /**
+     * Tests adding while updating the networkConfig.
+     *
+     * @throws SecurityException
+     * @throws NoSuchFieldException
+     * @throws IllegalAccessException
+     * @throws IllegalArgumentException
+     */
+    @Test
+    public void testUpdateNetworkConfig()
+            throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
+
+        ConnectPoint sw1eth4 = new ConnectPoint(DeviceId.deviceId("of:0000000000000001"), PortNumber.portNumber(4));
+        Set<InterfaceIpAddress> interfaceIpAddresses4 = Sets.newHashSet();
+        interfaceIpAddresses4
+                .add(new InterfaceIpAddress(IpAddress.valueOf("192.168.40.101"), IpPrefix.valueOf("192.168.40.0/24")));
+
+        Interface sw1Eth4 = new Interface(sw1eth4.deviceId().toString(), sw1eth4, interfaceIpAddresses4,
+                MacAddress.valueOf("00:00:00:00:00:04"), VlanId.NONE);
+        interfaces.add(sw1Eth4);
+        EasyMock.reset(interfaceService);
+        expect(interfaceService.getInterfacesByPort(sw1eth4)).andReturn(Collections.singleton(sw1Eth4)).anyTimes();
+        expect(interfaceService.getMatchingInterface(Ip4Address.valueOf("192.168.40.1"))).andReturn(sw1Eth4).anyTimes();
+        expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
+        replay(interfaceService);
+        interfaceService.getInterfaces();
+        EasyMock.reset(flowObjectiveService);
+        setUpFlowObjectiveService();
+        networkConfigListener
+                .event(new NetworkConfigEvent(Type.CONFIG_UPDATED, dev3, RoutingService.ROUTER_CONFIG_CLASS));
+        // deviceService.addListener(deviceListener);
+        networkConfigService.addListener(networkConfigListener);
+        verify(flowObjectiveService);
+    }
+
+
+    private ForwardingObjective buildForwardingObjective(TrafficSelector selector, TrafficTreatment treatment,
+            int nextId, boolean add) {
+        DefaultForwardingObjective.Builder fobBuilder = DefaultForwardingObjective.builder();
+        fobBuilder.withSelector(selector);
+        if (treatment != null) {
+            fobBuilder.withTreatment(treatment);
+        }
+        if (nextId != -1) {
+            fobBuilder.nextStep(nextId);
+        }
+        fobBuilder.fromApp(APPID).withPriority(40001).withFlag(ForwardingObjective.Flag.VERSATILE);
+
+        return add ? fobBuilder.add() : fobBuilder.remove();
+    }
+
+    /**
+     * @param intf
+     */
+
+    private class TestCoreService extends CoreServiceAdapter {
+        @Override
+        public ApplicationId getAppId(String name) {
+            return APPID;
+        }
+
+        @Override
+        public ApplicationId registerApplication(String name) {
+            // TODO Auto-generated method stub
+            return new TestApplicationId(name);
+        }
+
+    }
+
+    private class TestDeviceService extends DeviceServiceAdapter {
+
+        @Override
+        public boolean isAvailable(DeviceId deviceId) {
+            // TODO Auto-generated method stub
+            boolean flag = false;
+            if (deviceId.equals(controlPlaneConnectPoint.deviceId())) {
+                flag = true;
+            }
+            return flag;
+        }
+
+        @Override
+        public void addListener(DeviceListener listener) {
+            // TODO Auto-generated method stub
+            ControlPlaneRedirectManagerTest.this.deviceListener = listener;
+        }
+
+    }
+
+    private class TestHostService extends HostServiceAdapter {
+
+        @Override
+        public void addListener(HostListener listener) {
+            // TODO Auto-generated method stub
+            ControlPlaneRedirectManagerTest.this.hostListener = listener;
+        }
+
+    }
+
+    private class TestRouterConfig extends RouterConfig {
+
+        @Override
+        public ConnectPoint getControlPlaneConnectPoint() {
+            // TODO Auto-generated method stub
+            return controlPlaneConnectPoint;
+        }
+
+        @Override
+        public boolean getOspfEnabled() {
+            // TODO Auto-generated method stub
+            return true;
+        }
+
+        @Override
+        public List<String> getInterfaces() {
+            // TODO Auto-generated method stub
+
+            ArrayList<String> interfaces = new ArrayList<>();
+            interfaces.add("of:0000000000000001");
+            interfaces.add("of:0000000000000001/2");
+            interfaces.add("of:0000000000000001/3");
+            return interfaces;
+        }
+
+    }
+
+    private class TestNetworkConfigService extends NetworkConfigServiceAdapter {
+
+        @Override
+        public void addListener(NetworkConfigListener listener) {
+            // TODO Auto-generated method stub
+            ControlPlaneRedirectManagerTest.this.networkConfigListener = listener;
+        }
+
+        @Override
+        public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
+            // TODO Auto-generated method stub
+
+            return (C) ControlPlaneRedirectManagerTest.this.routerConfig;
+        }
+
+    }
+
+    private static class TestApplicationId implements ApplicationId {
+
+        private final String name;
+        private final short id;
+
+        public TestApplicationId(String name) {
+            this.name = name;
+            this.id = (short) Objects.hash(name);
+        }
+
+        public static ApplicationId create(String name) {
+            return new TestApplicationId(name);
+        }
+
+        @Override
+        public short id() {
+            return id;
+        }
+
+        @Override
+        public String name() {
+            return name;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + id;
+            result = prime * result + ((name == null) ? 0 : name.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj == null) {
+                return false;
+            }
+            if (getClass() != obj.getClass()) {
+                return false;
+            }
+            TestApplicationId other = (TestApplicationId) obj;
+            if (id != other.id) {
+                return false;
+            }
+            if (name == null) {
+                if (other.name != null) {
+                    return false;
+            }
+            } else if (!name.equals(other.name)) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    private class InternalMastershipServiceTest extends MastershipServiceAdapter {
+
+        @Override
+        public boolean isLocalMaster(DeviceId deviceId) {
+            // TODO Auto-generated method stub
+            boolean flag = deviceId.equals(controlPlaneConnectPoint.deviceId());
+            return flag;
+        }
+
+    }
+}