/**
 *    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 java.util.Set;

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.easymock.IArgumentMatcher;
import org.junit.Before;
import org.junit.Test;
import org.projectfloodlight.openflow.protocol.OFFactories;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFPacketIn;
import org.projectfloodlight.openflow.protocol.OFPacketOut;
import org.projectfloodlight.openflow.protocol.OFPortConfig;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.OFPortReason;
import org.projectfloodlight.openflow.protocol.OFPortState;
import org.projectfloodlight.openflow.protocol.OFPortStatus;
import org.projectfloodlight.openflow.protocol.OFVersion;
import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
import org.projectfloodlight.openflow.types.MacAddress;
import org.projectfloodlight.openflow.types.OFPort;

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

    private LinkDiscoveryManager ldm;

    private static final Set<OFPortState> EMPTY_PORT_STATE =
            Collections.<OFPortState>emptySet();

    // Arbitrary MAC address that we can feed in to our mock objects. This
    // value is never actually checked during the tests so it doesn't matter if
    // all ports have the same MAC address.
    private static final byte[] DEFAULT_MAC_ADDRESS =
            new byte[] {0x0, 0x0, 0x0, 0x0, 0x0, 0x1};

    private OFFactory factory10 = OFFactories.getFactory(OFVersion.OF_10);

    /**
     * EasyMock matcher to verify the value of the output port of a packet out.
     * This is used to verify that the packet out messages generated by
     * LinkDiscoveryManager contain the correct output port.
     *
     */
    private static final class PacketOutPortMatcher implements IArgumentMatcher {
        private final int portNumber;

        public PacketOutPortMatcher(int portNumber) {
            this.portNumber = portNumber;
        }

        @Override
        public void appendTo(StringBuffer strBuffer) {
            strBuffer.append("PacketOutPortMatcher failed to verify output port");
        }

        @Override
        public boolean matches(Object object) {
            if (!(object instanceof OFPacketOut)) {
                return false;
            }

            OFPacketOut po = (OFPacketOut) object;

            if (po.getActions().size() != 1
                    || !(po.getActions().get(0) instanceof OFActionOutput)) {
                return false;
            }

            OFActionOutput action = (OFActionOutput) po.getActions().get(0);

            return action.getPort().getPortNumber() == portNumber;
        }
    }

    /**
     * Matcher method to match a given output port against a packet out message
     * passed as an argument to a mock switch.
     *
     * @param outPort the output port to check in the packet out
     * @return anything of type OFPacketOut
     */
    private static OFPacketOut matchOutPort(int outPort) {
        EasyMock.reportMatcher(new PacketOutPortMatcher(outPort));
        return null;
    }

    private LinkDiscoveryManager getLinkDiscoveryManager() {
        return ldm;
    }

    private 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;
    }

    private OFPortDesc createMockPort(short portNumber) {
        return createMockPortWithState(portNumber,
               Collections.<OFPortState>emptySet());
    }

    private OFPortDesc createMockPortWithState(short portNumber,
            Set<OFPortState> state) {
        OFPort ofPort = EasyMock.createMock(OFPort.class);
        expect(ofPort.getShortPortNumber()).andReturn(portNumber).anyTimes();

        OFPortDesc ofPortDesc = EasyMock.createMock(OFPortDesc.class);
        expect(ofPortDesc.getPortNo()).andReturn(ofPort).anyTimes();
        expect(ofPortDesc.getHwAddr()).andReturn(
                MacAddress.of(DEFAULT_MAC_ADDRESS)).anyTimes();
        expect(ofPortDesc.getConfig()).
                andReturn(Collections.<OFPortConfig>emptySet()).anyTimes();
        expect(ofPortDesc.getState()).andReturn(state).anyTimes();

        replay(ofPort);
        replay(ofPortDesc);

        return ofPortDesc;
    }

    @Override
    @Before
    public void setUp() throws Exception {
        super.setUp();
        FloodlightModuleContext cntx = new FloodlightModuleContext();
        ldm = new LinkDiscoveryManager();
        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 linkDiscovery = getLinkDiscoveryManager();

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

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

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

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

        // Arbitrary new port states to verify that the port state is updated
        final Set<OFPortState> newSrcPortState =
                Collections.singleton(OFPortState.STP_BLOCK);
        final Set<OFPortState> newDstPortState =
                Collections.singleton(OFPortState.LINK_DOWN);

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

        linkDiscovery.addOrUpdateLink(lt, infoWithStateChange);

        assertNotNull(linkDiscovery.links.get(lt));
        infoToVerify = linkDiscovery.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 linkDiscovery = getLinkDiscoveryManager();

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

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

    @Test
    public void testAddOrUpdateLinkToSelf() throws Exception {
        LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager();

        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(), EMPTY_PORT_STATE, EMPTY_PORT_STATE);
        linkDiscovery.addOrUpdateLink(lt, info);

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

    @Test
    public void testDeleteLinkToSelf() throws Exception {
        LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager();

        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(), EMPTY_PORT_STATE, EMPTY_PORT_STATE);
        linkDiscovery.addOrUpdateLink(lt, info);
        linkDiscovery.deleteLinks(Collections.singletonList(lt));

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

    @Test
    public void testRemovedSwitch() {
        LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager();

        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(), EMPTY_PORT_STATE, EMPTY_PORT_STATE);
        linkDiscovery.addOrUpdateLink(lt, info);

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

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

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

        // Mock up our expected behavior
        linkDiscovery.switchDisconnected(sw1.getId());

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

    @Test
    public void testAddUpdateLinks() throws Exception {
        LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager();

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

        LinkInfo info;

        // Setting the last LLDP reception time to be 40 seconds old, so we
        // can use this to test that an old link times out correctly
        info = new LinkInfo(System.currentTimeMillis() - 40000,
                System.currentTimeMillis() - 40000,
                EMPTY_PORT_STATE, EMPTY_PORT_STATE);
        linkDiscovery.addOrUpdateLink(lt, info);

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

        linkDiscovery.timeOutLinks();

        // Setting the last LLDP reception time to be 40 seconds old, so we
        // can use this to test that an old link times out correctly
        info = new LinkInfo(System.currentTimeMillis() - 40000,
                System.currentTimeMillis() - 40000,
                EMPTY_PORT_STATE, EMPTY_PORT_STATE);
        linkDiscovery.addOrUpdateLink(lt, info);

        // Expect to timeout the unicast Valid Time, so the link should disappear
        linkDiscovery.timeOutLinks();
        assertTrue(linkDiscovery.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 {
        LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager();

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

        short portNum = 1;

        OFPortDesc ofPortDesc = createMockPort(portNum);

        expect(swTest.getPort(portNum)).andReturn(ofPortDesc).atLeastOnce();
        swTest.write(matchOutPort(portNum),
                EasyMock.anyObject(FloodlightContext.class));
        EasyMock.expectLastCall().times(1);
        swTest.flush();
        EasyMock.expectLastCall().once();
        replay(swTest);

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

        verify(swTest);
    }

    @Test
    public void testHandlePortStatusForNewPort() throws IOException {
        LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager();

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

        short portNum = 1;

        OFPortDesc ofPortDesc = createMockPort(portNum);

        OFPortStatus portStatus = factory10.buildPortStatus()
            .setDesc(ofPortDesc)
            .setReason(OFPortReason.ADD)
            .build();

        expect(sw.getPort(portNum)).andReturn(ofPortDesc).once();

        sw.write(matchOutPort(portNum),
                EasyMock.anyObject(FloodlightContext.class));
        sw.flush();

        replay(sw);

        linkDiscovery.handlePortStatus(sw, portStatus);

        verify(sw);
    }

    @Test
    public void testHandlePortStatusForExistingPort() {
        LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager();

        // 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(), EMPTY_PORT_STATE, EMPTY_PORT_STATE);
        linkDiscovery.addOrUpdateLink(lt, info);

        short portNum = 1;

        // Arbitrary states to test state changes
        Set<OFPortState> srcPortState =
                Collections.singleton(OFPortState.STP_FORWARD);
        Set<OFPortState> dstPortState =
                Collections.singleton(OFPortState.STP_LISTEN);

        OFPortDesc srcPortDesc = createMockPortWithState(portNum, srcPortState);
        OFPortDesc dstPortDesc = createMockPortWithState(portNum, dstPortState);

        OFPortStatus srcPortStatus = factory10.buildPortStatus()
                .setDesc(srcPortDesc)
                .setReason(OFPortReason.MODIFY)
                .build();

        OFPortStatus dstPortStatus = factory10.buildPortStatus()
                .setDesc(dstPortDesc)
                .setReason(OFPortReason.MODIFY)
                .build();

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

        LinkInfo newInfo = linkDiscovery.links.get(lt);
        assertEquals(srcPortState, newInfo.getSrcPortState());
        assertEquals(EMPTY_PORT_STATE, 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() {
        LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager();

        // 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(), EMPTY_PORT_STATE, EMPTY_PORT_STATE);
        linkDiscovery.addOrUpdateLink(lt, info);

        short portNum = 1;

        OFPortDesc srcPortDesc = createMockPort(portNum);
        OFPortStatus srcPortStatus = factory10.buildPortStatus()
                .setDesc(srcPortDesc)
                .setReason(OFPortReason.DELETE)
                .build();

        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() {
        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(DEFAULT_MAC_ADDRESS);
        ethPacket.setDestinationMACAddress(
                LinkDiscoveryManager.LLDP_STANDARD_DST_MAC_STRING);
        ethPacket.setPayload(lldpPacket);
        ethPacket.setPad(true);

        OFPacketIn pi = EasyMock.createMock(OFPacketIn.class);
        expect(pi.getData()).andReturn(ethPacket.serialize()).anyTimes();
        replay(pi);

        LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager();

        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, (short) 2);

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