/**
 *    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.anyLong;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.anyShort;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.reportMatcher;
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.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) {
        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(anyShort())).andReturn(true).anyTimes();
        expect(mockSwitch.getFactory()).andReturn(factory10).anyTimes();
        return mockSwitch;
    }

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

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

        OFPortDesc ofPortDesc = 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 =
                createMock(IControllerRegistryService.class);
        expect(registry.hasControl(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),
                anyObject(FloodlightContext.class));
        expectLastCall().times(1);
        swTest.flush();
        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),
                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 = 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));
    }
}
