/**
 *    Copyright 2011, Big Switch Networks, Inc.
 *    Originally created by David Erickson, Stanford University
 *
 *    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 net.onrc.onos.core.linkdiscovery;

import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;

import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import net.floodlightcontroller.core.FloodlightContext;
import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.IListener.Command;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.floodlightcontroller.core.test.MockThreadPoolService;
import net.floodlightcontroller.restserver.IRestApiService;
import net.floodlightcontroller.restserver.RestApiServer;
import net.floodlightcontroller.test.FloodlightTestCase;
import net.floodlightcontroller.threadpool.IThreadPoolService;
import net.onrc.onos.core.packet.Ethernet;
import net.onrc.onos.core.packet.OnosLldp;
import net.onrc.onos.core.registry.IControllerRegistryService;

import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.Test;
import org.openflow.protocol.OFMessage;
import org.openflow.protocol.OFPacketIn;
import org.openflow.protocol.OFPhysicalPort;
import org.openflow.protocol.OFPortStatus;
import org.openflow.protocol.OFPortStatus.OFPortReason;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

// CHECKSTYLE IGNORE WriteTag FOR NEXT 2 LINES
/**
 * @author David Erickson (daviderickson@cs.stanford.edu)
 */
public class LinkDiscoveryManagerTest extends FloodlightTestCase {

    private TestLinkDiscoveryManager ldm;
    protected static final Logger log = LoggerFactory.getLogger(LinkDiscoveryManagerTest.class);

    public class TestLinkDiscoveryManager extends LinkDiscoveryManager {
        public boolean isSendLLDPsCalled = false;
        public boolean isClearLinksCalled = false;

        @Override
        protected void discoverOnAllPorts() {
            isSendLLDPsCalled = true;
            super.discoverOnAllPorts();
        }

        public void reset() {
            isSendLLDPsCalled = false;
            isClearLinksCalled = false;
        }
    }

    public LinkDiscoveryManager getTopology() {
        return ldm;
    }

    public IOFSwitch createMockSwitch(Long id) {
        IOFSwitch mockSwitch = createNiceMock(IOFSwitch.class);
        expect(mockSwitch.getId()).andReturn(id).anyTimes();
        expect(mockSwitch.portEnabled(EasyMock.anyShort())).andReturn(true).anyTimes();
        return mockSwitch;
    }

    @Override
    @Before
    public void setUp() throws Exception {
        super.setUp();
        FloodlightModuleContext cntx = new FloodlightModuleContext();
        ldm = new TestLinkDiscoveryManager();
        //ldm.linkDiscoveryAware = new ArrayList<ILinkDiscoveryListener>();
        MockThreadPoolService tp = new MockThreadPoolService();
        RestApiServer restApi = new RestApiServer();
        IControllerRegistryService registry =
                EasyMock.createMock(IControllerRegistryService.class);
        expect(registry.hasControl(EasyMock.anyLong())).andReturn(true).anyTimes();
        replay(registry);
        cntx.addService(IControllerRegistryService.class, registry);
        cntx.addService(IRestApiService.class, restApi);
        cntx.addService(IThreadPoolService.class, tp);
        cntx.addService(ILinkDiscoveryService.class, ldm);
        cntx.addService(IFloodlightProviderService.class, getMockFloodlightProvider());
        restApi.init(cntx);
        tp.init(cntx);
        ldm.init(cntx);
        restApi.startUp(cntx);
        tp.startUp(cntx);
        ldm.startUp(cntx);

        IOFSwitch sw1 = createMockSwitch(1L);
        IOFSwitch sw2 = createMockSwitch(2L);
        Map<Long, IOFSwitch> switches = new HashMap<Long, IOFSwitch>();
        switches.put(1L, sw1);
        switches.put(2L, sw2);
        getMockFloodlightProvider().setSwitches(switches);
        replay(sw1, sw2);
    }

    @Test
    public void testAddOrUpdateLink() throws Exception {
        LinkDiscoveryManager topology = getTopology();

        Link lt = new Link(1L, 2, 2L, 1);
        long firstSeenTime = System.currentTimeMillis();
        LinkInfo info = new LinkInfo(firstSeenTime,
                System.currentTimeMillis(), 0, 0);
        topology.addOrUpdateLink(lt, info);


        NodePortTuple srcNpt = new NodePortTuple(1L, 2);
        NodePortTuple dstNpt = new NodePortTuple(2L, 1);

        // check invariants hold
        assertNotNull(topology.switchLinks.get(lt.getSrc()));
        assertTrue(topology.switchLinks.get(lt.getSrc()).contains(lt));
        assertNotNull(topology.portLinks.get(srcNpt));
        assertTrue(topology.portLinks.get(srcNpt).contains(lt));
        assertNotNull(topology.portLinks.get(dstNpt));
        assertTrue(topology.portLinks.get(dstNpt).contains(lt));
        assertTrue(topology.links.containsKey(lt));

        LinkInfo infoToVerify = topology.links.get(lt);
        assertEquals(firstSeenTime, infoToVerify.getFirstSeenTime());
        assertEquals(0, infoToVerify.getSrcPortState());
        assertEquals(0, infoToVerify.getDstPortState());

        // Arbitrary new port states to verify that the port state is updated
        final int newSrcPortState = 1;
        final int newDstPortState = 2;

        // Update the last received probe timestamp and the port states
        LinkInfo infoWithStateChange = new LinkInfo(System.currentTimeMillis(),
                System.currentTimeMillis(), newSrcPortState, newDstPortState);

        topology.addOrUpdateLink(lt, infoWithStateChange);

        assertNotNull(topology.links.get(lt));
        infoToVerify = topology.links.get(lt);
        // First seen time should be the original time, not the second update time
        assertEquals(firstSeenTime, infoToVerify.getFirstSeenTime());
        // Both port states should have been updated
        assertEquals(newSrcPortState, infoToVerify.getSrcPortState());
        assertEquals(newDstPortState, infoToVerify.getDstPortState());
    }

    @Test
    public void testDeleteLink() throws Exception {
        LinkDiscoveryManager topology = getTopology();

        Link lt = new Link(1L, 2, 2L, 1);
        LinkInfo info = new LinkInfo(System.currentTimeMillis(),
                System.currentTimeMillis(), 0, 0);
        topology.addOrUpdateLink(lt, info);
        topology.deleteLinks(Collections.singletonList(lt));

        // check invariants hold
        assertNull(topology.switchLinks.get(lt.getSrc()));
        assertNull(topology.switchLinks.get(lt.getDst()));
        assertNull(topology.portLinks.get(lt.getSrc()));
        assertNull(topology.portLinks.get(lt.getDst()));
        assertTrue(topology.links.isEmpty());
    }

    @Test
    public void testAddOrUpdateLinkToSelf() throws Exception {
        LinkDiscoveryManager topology = getTopology();

        Link lt = new Link(1L, 2, 2L, 3);
        NodePortTuple srcNpt = new NodePortTuple(1L, 2);
        NodePortTuple dstNpt = new NodePortTuple(2L, 3);

        LinkInfo info = new LinkInfo(System.currentTimeMillis(),
                System.currentTimeMillis(), 0, 0);
        topology.addOrUpdateLink(lt, info);

        // check invariants hold
        assertNotNull(topology.switchLinks.get(lt.getSrc()));
        assertTrue(topology.switchLinks.get(lt.getSrc()).contains(lt));
        assertNotNull(topology.portLinks.get(srcNpt));
        assertTrue(topology.portLinks.get(srcNpt).contains(lt));
        assertNotNull(topology.portLinks.get(dstNpt));
        assertTrue(topology.portLinks.get(dstNpt).contains(lt));
        assertTrue(topology.links.containsKey(lt));
    }

    @Test
    public void testDeleteLinkToSelf() throws Exception {
        LinkDiscoveryManager topology = getTopology();

        Link lt = new Link(1L, 2, 1L, 3);
        NodePortTuple srcNpt = new NodePortTuple(1L, 2);
        NodePortTuple dstNpt = new NodePortTuple(2L, 3);

        LinkInfo info = new LinkInfo(System.currentTimeMillis(),
                System.currentTimeMillis(), 0, 0);
        topology.addOrUpdateLink(lt, info);
        topology.deleteLinks(Collections.singletonList(lt));

        // check invariants hold
        assertNull(topology.switchLinks.get(lt.getSrc()));
        assertNull(topology.switchLinks.get(lt.getDst()));
        assertNull(topology.portLinks.get(srcNpt));
        assertNull(topology.portLinks.get(dstNpt));
        assertTrue(topology.links.isEmpty());
    }

    @Test
    public void testRemovedSwitch() {
        LinkDiscoveryManager topology = getTopology();

        Link lt = new Link(1L, 2, 2L, 1);
        NodePortTuple srcNpt = new NodePortTuple(1L, 2);
        NodePortTuple dstNpt = new NodePortTuple(2L, 1);
        LinkInfo info = new LinkInfo(System.currentTimeMillis(),
                System.currentTimeMillis(), 0, 0);
        topology.addOrUpdateLink(lt, info);

        IOFSwitch sw1 = getMockFloodlightProvider().getSwitches().get(1L);
        IOFSwitch sw2 = getMockFloodlightProvider().getSwitches().get(2L);
        // Mock up our expected behavior
        topology.removedSwitch(sw1);
        verify(sw1, sw2);

        // check invariants hold
        assertNull(topology.switchLinks.get(lt.getSrc()));
        assertNull(topology.switchLinks.get(lt.getDst()));
        assertNull(topology.portLinks.get(srcNpt));
        assertNull(topology.portLinks.get(dstNpt));
        assertTrue(topology.links.isEmpty());
    }

    @Test
    public void testRemovedSwitchSelf() {
        LinkDiscoveryManager topology = getTopology();
        IOFSwitch sw1 = createMockSwitch(1L);
        replay(sw1);
        Link lt = new Link(1L, 2, 1L, 3);
        LinkInfo info = new LinkInfo(System.currentTimeMillis(),
                System.currentTimeMillis(), 0, 0);
        topology.addOrUpdateLink(lt, info);

        // Mock up our expected behavior
        topology.removedSwitch(sw1);

        verify(sw1);
        // check invariants hold
        assertNull(topology.switchLinks.get(lt.getSrc()));
        assertNull(topology.portLinks.get(lt.getSrc()));
        assertNull(topology.portLinks.get(lt.getDst()));
        assertTrue(topology.links.isEmpty());
    }

    @Test
    public void testAddUpdateLinks() throws Exception {
        LinkDiscoveryManager topology = getTopology();

        Link lt = new Link(1L, 1, 2L, 1);
        NodePortTuple srcNpt = new NodePortTuple(1L, 1);
        NodePortTuple dstNpt = new NodePortTuple(2L, 1);

        LinkInfo info;

        info = new LinkInfo(System.currentTimeMillis() - 40000,
                System.currentTimeMillis() - 40000, 0, 0);
        topology.addOrUpdateLink(lt, info);

        // check invariants hold
        assertNotNull(topology.switchLinks.get(lt.getSrc()));
        assertTrue(topology.switchLinks.get(lt.getSrc()).contains(lt));
        assertNotNull(topology.portLinks.get(srcNpt));
        assertTrue(topology.portLinks.get(srcNpt).contains(lt));
        assertNotNull(topology.portLinks.get(dstNpt));
        assertTrue(topology.portLinks.get(dstNpt).contains(lt));
        assertTrue(topology.links.containsKey(lt));

        topology.timeOutLinks();

        // Add a link info based on info that would be obtained from unicast LLDP
        // Setting the unicast LLDP reception time to be 40 seconds old, so we can use
        // this to test timeout after this test.
        info = new LinkInfo(System.currentTimeMillis() - 40000,
                System.currentTimeMillis() - 40000, 0, 0);
        topology.addOrUpdateLink(lt, info);

        // Expect to timeout the unicast Valid Time, so the link should disappear
        topology.timeOutLinks();
        assertTrue(topology.links.get(lt) == null);
    }

    /**
     * This test case verifies that LinkDiscoveryManager.sendDiscoveryMessage()
     * performs "write" operation on the specified IOFSwitch object
     * with a LLDP packet.
     *
     * @throws IOException
     */
    @Test
    public void testSendDiscoveryMessage() throws IOException {
        byte[] macAddress = new byte[] {0x0, 0x0, 0x0, 0x0, 0x0, 0x1};

        LinkDiscoveryManager topology = getTopology();

        // Mock up our expected behavior
        IOFSwitch swTest = createMockSwitch(3L);
        getMockFloodlightProvider().getSwitches().put(3L, swTest);

        short portNum = 1;
        OFPhysicalPort ofpPort = new OFPhysicalPort();
        ofpPort.setPortNumber(portNum);
        ofpPort.setHardwareAddress(macAddress);

        /* sendDiscoverMessage() should perform the following actions on
         * IOFSwitch object
         * - getPort() with argument as "1"
         * - write() with OFPacketOut
         * - flush()
         */
        expect(swTest.getPort(portNum)).andReturn(ofpPort).atLeastOnce();
        swTest.write(EasyMock.anyObject(OFMessage.class), EasyMock.anyObject(FloodlightContext.class));
        EasyMock.expectLastCall().times(1);
        swTest.flush();
        EasyMock.expectLastCall().once();
        replay(swTest);

        topology.sendDiscoveryMessage(3L, portNum, false);

        verify(swTest);
    }

    @Test
    public void testHandlePortStatusForNewPort() throws IOException {
        byte[] macAddress = new byte[] {0x0, 0x0, 0x0, 0x0, 0x0, 0x1};

        LinkDiscoveryManager linkDiscovery = getTopology();

        long dpid = 3L;
        IOFSwitch sw = createMockSwitch(dpid);
        getMockFloodlightProvider().getSwitches().put(dpid, sw);

        short portNum = 1;
        OFPhysicalPort ofpPort = new OFPhysicalPort();
        ofpPort.setPortNumber(portNum);
        ofpPort.setHardwareAddress(macAddress);

        OFPortStatus portStatus = new OFPortStatus();
        portStatus.setDesc(ofpPort);
        portStatus.setReason((byte) OFPortReason.OFPPR_ADD.ordinal());

        expect(sw.getPort(portNum)).andReturn(ofpPort).anyTimes();
        sw.write(EasyMock.anyObject(OFMessage.class),
                EasyMock.anyObject(FloodlightContext.class));
        sw.flush();

        replay(sw);

        linkDiscovery.handlePortStatus(sw, portStatus);

        verify(sw);
    }

    @Test
    public void testHandlePortStatusForExistingPort() {
        byte[] macAddress = new byte[] {0x0, 0x0, 0x0, 0x0, 0x0, 0x1};

        LinkDiscoveryManager linkDiscovery = getTopology();

        // Add a link that we can update later during the test
        Link lt = new Link(1L, 1, 2L, 1);
        LinkInfo info = new LinkInfo(System.currentTimeMillis(),
                System.currentTimeMillis(), 0, 0);
        linkDiscovery.addOrUpdateLink(lt, info);

        short portNum = 1;
        // src port
        int srcPortState = 2;
        OFPhysicalPort srcPort = new OFPhysicalPort();
        srcPort.setPortNumber(portNum);
        srcPort.setHardwareAddress(macAddress);
        srcPort.setState(srcPortState);

        // dst port
        int dstPortState = 4;
        OFPhysicalPort dstPort = new OFPhysicalPort();
        dstPort.setPortNumber(portNum);
        dstPort.setHardwareAddress(macAddress);
        dstPort.setState(dstPortState);

        OFPortStatus srcPortStatus = new OFPortStatus();
        srcPortStatus.setDesc(srcPort);
        srcPortStatus.setReason((byte) OFPortReason.OFPPR_MODIFY.ordinal());

        OFPortStatus dstPortStatus = new OFPortStatus();
        dstPortStatus.setDesc(dstPort);
        dstPortStatus.setReason((byte) OFPortReason.OFPPR_MODIFY.ordinal());

        linkDiscovery.handlePortStatus(
                getMockFloodlightProvider().getSwitches().get(1L), srcPortStatus);


        LinkInfo newInfo = linkDiscovery.links.get(lt);
        assertEquals(srcPortState, newInfo.getSrcPortState());
        assertEquals(0, newInfo.getDstPortState());


        linkDiscovery.handlePortStatus(
                getMockFloodlightProvider().getSwitches().get(2L), dstPortStatus);

        newInfo = linkDiscovery.links.get(lt);
        assertEquals(srcPortState, newInfo.getSrcPortState());
        assertEquals(dstPortState, newInfo.getDstPortState());
    }

    @Test
    public void testHandlePortStatusForDeletePort() {
        byte[] macAddress = new byte[] {0x0, 0x0, 0x0, 0x0, 0x0, 0x1};

        LinkDiscoveryManager linkDiscovery = getTopology();

        // Add a link that we can delete later during the test
        Link lt = new Link(1L, 1, 2L, 2);
        LinkInfo info = new LinkInfo(System.currentTimeMillis(),
                System.currentTimeMillis(), 0, 0);
        linkDiscovery.addOrUpdateLink(lt, info);

        short portNum = 1;
        int srcPortState = 1;
        OFPhysicalPort srcPort = new OFPhysicalPort();
        srcPort.setPortNumber(portNum);
        srcPort.setHardwareAddress(macAddress);
        srcPort.setState(srcPortState);

        OFPortStatus srcPortStatus = new OFPortStatus();
        srcPortStatus.setDesc(srcPort);
        srcPortStatus.setReason((byte) OFPortReason.OFPPR_DELETE.ordinal());

        assertNotNull(linkDiscovery.getLinks().get(lt));

        // Send a delete port status for the source port, which should result
        // in the link being deleted
        linkDiscovery.handlePortStatus(
                getMockFloodlightProvider().getSwitches().get(1L), srcPortStatus);

        assertNull(linkDiscovery.getLinks().get(lt));
    }

    @Test
    public void testReceive() {
        byte[] macAddress = new byte[] {0x0, 0x0, 0x0, 0x0, 0x0, 0x1};

        OnosLldp lldpPacket = new OnosLldp();
        lldpPacket.setPort((short) 1);
        lldpPacket.setSwitch(1L);
        lldpPacket.setReverse(false);

        Ethernet ethPacket = new Ethernet();
        ethPacket.setEtherType(Ethernet.TYPE_LLDP);
        ethPacket.setSourceMACAddress(macAddress);
        ethPacket.setDestinationMACAddress(
                LinkDiscoveryManager.LLDP_STANDARD_DST_MAC_STRING);
        ethPacket.setPayload(lldpPacket);
        ethPacket.setPad(true);

        OFPacketIn pi = new OFPacketIn();
        pi.setInPort((short) 2);
        pi.setPacketData(ethPacket.serialize());

        LinkDiscoveryManager linkDiscovery = getTopology();

        Link expectedLink = new Link(1L, 1, 2L, 2);

        assertNull(linkDiscovery.links.get(expectedLink));

        // Sending in the LLDP packet should cause the link to be created
        Command command = linkDiscovery.handleLldp(lldpPacket, 2L, pi);

        assertEquals(Command.STOP, command);
        assertNotNull(linkDiscovery.links.get(expectedLink));
    }
}
