/*
 * Copyright 2015-present 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 com.google.common.collect.Sets;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.Ip6Prefix;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.core.CoreService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultHost;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.PortNumber;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.host.HostService;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.routing.RouteSourceService;
import org.onosproject.routing.FibEntry;
import org.onosproject.routing.FibListener;
import org.onosproject.routing.FibUpdate;
import org.onosproject.routing.RouteEntry;
import org.onosproject.routing.RouteListener;
import org.onosproject.routing.RouteUpdate;
import org.onosproject.routing.config.RoutingConfigurationService;

import java.util.Collections;

import static org.easymock.EasyMock.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

/**
 * This class tests adding a route, updating a route, deleting a route,
 * and adding a route whose next hop is the local BGP speaker.
 * <p/>
 * The HostService answers requests synchronously.
 */
public class RouterTest {

    private HostService hostService;
    private RoutingConfigurationService routingConfigurationService;

    private FibListener fibListener;

    private static final ConnectPoint SW1_ETH1 = new ConnectPoint(
            DeviceId.deviceId("of:0000000000000001"),
            PortNumber.portNumber(1));

    private static final ConnectPoint SW2_ETH1 = new ConnectPoint(
            DeviceId.deviceId("of:0000000000000002"),
            PortNumber.portNumber(1));

    private static final ConnectPoint SW3_ETH1 = new ConnectPoint(
            DeviceId.deviceId("of:0000000000000003"),
            PortNumber.portNumber(1));

    private static final ConnectPoint SW4_ETH1 = new ConnectPoint(
            DeviceId.deviceId("of:0000000000000004"),
            PortNumber.portNumber(1));

    private static final ConnectPoint SW5_ETH1 = new ConnectPoint(
            DeviceId.deviceId("of:0000000000000005"),
            PortNumber.portNumber(1));

    private static final ConnectPoint SW6_ETH1 = new ConnectPoint(
            DeviceId.deviceId("of:0000000000000006"),
            PortNumber.portNumber(1));
    private DefaultRouter router;

    @Before
    public void setUp() throws Exception {
        setUpHostService();
        routingConfigurationService =
                createMock(RoutingConfigurationService.class);

        RouteSourceService routeSourceService = createMock(RouteSourceService.class);
        routeSourceService.start(anyObject(RouteListener.class));
        routeSourceService.stop();
        replay(routeSourceService);

        fibListener = createMock(FibListener.class);

        router = new DefaultRouter();
        router.coreService = createNiceMock(CoreService.class);
        router.hostService = hostService;
        router.routingConfigurationService = routingConfigurationService;
        router.routeSourceService = routeSourceService;
        router.activate();

        router.addFibListener(fibListener);
        router.start();
    }

    @After
    public void tearDown() {
        router.stop();
    }

    /**
     * Sets up the host service with details of some hosts.
     */
    private void setUpHostService() {
        hostService = createMock(HostService.class);

        hostService.addListener(anyObject(HostListener.class));
        expectLastCall().anyTimes();

        IpAddress host1Address = IpAddress.valueOf("192.168.10.1");
        Host host1 = new DefaultHost(ProviderId.NONE, HostId.NONE,
                MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE,
                new HostLocation(SW1_ETH1, 1),
                Sets.newHashSet(host1Address));

        expect(hostService.getHostsByIp(host1Address))
                .andReturn(Sets.newHashSet(host1)).anyTimes();
        hostService.startMonitoringIp(host1Address);
        expectLastCall().anyTimes();

        IpAddress host2Address = IpAddress.valueOf("192.168.20.1");
        Host host2 = new DefaultHost(ProviderId.NONE, HostId.NONE,
                MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE,
                new HostLocation(SW2_ETH1, 1),
                Sets.newHashSet(host2Address));

        expect(hostService.getHostsByIp(host2Address))
                .andReturn(Sets.newHashSet(host2)).anyTimes();
        hostService.startMonitoringIp(host2Address);
        expectLastCall().anyTimes();

        // Next hop on a VLAN
        IpAddress host3Address = IpAddress.valueOf("192.168.40.1");
        Host host3 = new DefaultHost(ProviderId.NONE, HostId.NONE,
                MacAddress.valueOf("00:00:00:00:00:03"), VlanId.vlanId((short) 1),
                new HostLocation(SW3_ETH1, 1),
                Sets.newHashSet(host3Address));

        expect(hostService.getHostsByIp(host3Address))
                .andReturn(Sets.newHashSet(host3)).anyTimes();
        hostService.startMonitoringIp(host3Address);
        expectLastCall().anyTimes();

        IpAddress host4Address = IpAddress.valueOf("1000::1");
        Host host4 = new DefaultHost(ProviderId.NONE, HostId.NONE,
                 MacAddress.valueOf("00:00:00:00:00:04"), VlanId.NONE,
                 new HostLocation(SW4_ETH1, 1),
                 Sets.newHashSet(host4Address));

        expect(hostService.getHostsByIp(host4Address))
                .andReturn(Sets.newHashSet(host4)).anyTimes();
        hostService.startMonitoringIp(host4Address);
        expectLastCall().anyTimes();

        IpAddress host5Address = IpAddress.valueOf("2000::1");
        Host host5 = new DefaultHost(ProviderId.NONE, HostId.NONE,
                 MacAddress.valueOf("00:00:00:00:00:05"), VlanId.NONE,
                 new HostLocation(SW5_ETH1, 1),
                 Sets.newHashSet(host5Address));

        expect(hostService.getHostsByIp(host5Address))
                .andReturn(Sets.newHashSet(host5)).anyTimes();
        hostService.startMonitoringIp(host5Address);
        expectLastCall().anyTimes();

        // Next hop on a VLAN
        IpAddress host6Address = IpAddress.valueOf("3000::1");
        Host host6 = new DefaultHost(ProviderId.NONE, HostId.NONE,
                 MacAddress.valueOf("00:00:00:00:00:06"), VlanId.vlanId((short) 1),
                 new HostLocation(SW6_ETH1, 1),
                 Sets.newHashSet(host6Address));

        expect(hostService.getHostsByIp(host6Address))
                .andReturn(Sets.newHashSet(host6)).anyTimes();
        hostService.startMonitoringIp(host6Address);
        expectLastCall().anyTimes();


        // Called during shutdown
        hostService.removeListener(anyObject(HostListener.class));

        replay(hostService);
    }

    /**
     * Tests adding a IPv4 route entry.
     */
    @Test
    public void testIpv4RouteAdd() {
        // Construct a route entry
        IpPrefix prefix = Ip4Prefix.valueOf("1.1.1.0/24");
        IpAddress nextHopIp = Ip4Address.valueOf("192.168.10.1");

        RouteEntry routeEntry = new RouteEntry(prefix, nextHopIp);

        // Expected FIB entry
        FibEntry fibEntry = new FibEntry(prefix, nextHopIp,
                MacAddress.valueOf("00:00:00:00:00:01"));

        fibListener.update(Collections.singletonList(new FibUpdate(
                FibUpdate.Type.UPDATE, fibEntry)), Collections.emptyList());

        replay(fibListener);

        router.processRouteUpdates(Collections.singletonList(
                new RouteUpdate(RouteUpdate.Type.UPDATE, routeEntry)));

        verify(fibListener);
    }


    /**
     * Tests adding a IPv6 route entry.
     */
    @Test
    public void testIpv6RouteAdd() {
        // Construct a route entry
        IpPrefix prefix = Ip6Prefix.valueOf("4000::/64");
        IpAddress nextHopIp = Ip6Address.valueOf("1000::1");

        RouteEntry routeEntry = new RouteEntry(prefix, nextHopIp);

        // Expected FIB entry
        FibEntry fibEntry = new FibEntry(prefix, nextHopIp,
                MacAddress.valueOf("00:00:00:00:00:04"));

        fibListener.update(Collections.singletonList(new FibUpdate(
                FibUpdate.Type.UPDATE, fibEntry)), Collections.emptyList());

        replay(fibListener);

        router.processRouteUpdates(Collections.singletonList(
                new RouteUpdate(RouteUpdate.Type.UPDATE, routeEntry)));

        verify(fibListener);
    }


    /**
     * Tests updating a IPv4 route entry.
     */
    @Test
    public void testRouteUpdate() {
        // Firstly add a route
        testIpv4RouteAdd();

        // Route entry with updated next hop for the original prefix
        RouteEntry routeEntryUpdate = new RouteEntry(
                Ip4Prefix.valueOf("1.1.1.0/24"),
                Ip4Address.valueOf("192.168.20.1"));

        // The old FIB entry will be withdrawn
        FibEntry withdrawFibEntry = new FibEntry(
                Ip4Prefix.valueOf("1.1.1.0/24"), null, null);

        // A new FIB entry will be added
        FibEntry updateFibEntry = new FibEntry(
                Ip4Prefix.valueOf("1.1.1.0/24"),
                Ip4Address.valueOf("192.168.20.1"),
                MacAddress.valueOf("00:00:00:00:00:02"));

        reset(fibListener);
        fibListener.update(Collections.singletonList(new FibUpdate(
                                    FibUpdate.Type.UPDATE, updateFibEntry)),
                           Collections.singletonList(new FibUpdate(
                                    FibUpdate.Type.DELETE, withdrawFibEntry)));
        replay(fibListener);

        reset(routingConfigurationService);
        expect(routingConfigurationService.isIpPrefixLocal(
                anyObject(IpPrefix.class))).andReturn(false);
        replay(routingConfigurationService);

        router.processRouteUpdates(Collections.singletonList(new RouteUpdate(
                RouteUpdate.Type.UPDATE, routeEntryUpdate)));

        verify(fibListener);
    }

    /**
     * Tests updating a IPv6 route entry.
     */
    @Test
    public void testIpv6RouteUpdate() {
        // Firstly add a route
        testIpv6RouteAdd();

        // Route entry with updated next hop for the original prefix
        RouteEntry routeEntryUpdate = new RouteEntry(
                Ip6Prefix.valueOf("4000::/64"),
                Ip6Address.valueOf("2000::1"));

        // The old FIB entry will be withdrawn
        FibEntry withdrawFibEntry = new FibEntry(
                Ip6Prefix.valueOf("4000::/64"), null, null);

        // A new FIB entry will be added
        FibEntry updateFibEntry = new FibEntry(
                Ip6Prefix.valueOf("4000::/64"),
                Ip6Address.valueOf("2000::1"),
                MacAddress.valueOf("00:00:00:00:00:05"));

        reset(fibListener);
        fibListener.update(Collections.singletonList(new FibUpdate(
                                   FibUpdate.Type.UPDATE, updateFibEntry)),
                           Collections.singletonList(new FibUpdate(
                                   FibUpdate.Type.DELETE, withdrawFibEntry)));
        replay(fibListener);

        reset(routingConfigurationService);
        expect(routingConfigurationService.isIpPrefixLocal(
                anyObject(IpPrefix.class))).andReturn(false);
        replay(routingConfigurationService);

        router.processRouteUpdates(Collections.singletonList(new RouteUpdate(
                RouteUpdate.Type.UPDATE, routeEntryUpdate)));

        verify(fibListener);
    }

    /**
     * Tests deleting a IPv4 route entry.
     */
    @Test
    public void testIpv4RouteDelete() {
        // Firstly add a route
        testIpv4RouteAdd();

        RouteEntry deleteRouteEntry = new RouteEntry(
                Ip4Prefix.valueOf("1.1.1.0/24"),
                Ip4Address.valueOf("192.168.10.1"));

        FibEntry deleteFibEntry = new FibEntry(
                Ip4Prefix.valueOf("1.1.1.0/24"), null, null);

        reset(fibListener);
        fibListener.update(Collections.emptyList(), Collections.singletonList(
                new FibUpdate(FibUpdate.Type.DELETE, deleteFibEntry)));

        replay(fibListener);

        router.processRouteUpdates(Collections.singletonList(
                new RouteUpdate(RouteUpdate.Type.DELETE, deleteRouteEntry)));

        verify(fibListener);
    }

    /**
     * Tests deleting a IPv6 route entry.
     */
    @Test
    public void testIpv6RouteDelete() {
        // Firstly add a route
        testIpv6RouteAdd();

        RouteEntry deleteRouteEntry = new RouteEntry(
                Ip6Prefix.valueOf("4000::/64"),
                Ip6Address.valueOf("1000::1"));

        FibEntry deleteFibEntry = new FibEntry(
                Ip6Prefix.valueOf("4000::/64"), null, null);

        reset(fibListener);
        fibListener.update(Collections.emptyList(), Collections.singletonList(
                new FibUpdate(FibUpdate.Type.DELETE, deleteFibEntry)));

        replay(fibListener);

        router.processRouteUpdates(Collections.singletonList(
                new RouteUpdate(RouteUpdate.Type.DELETE, deleteRouteEntry)));

        verify(fibListener);
    }

    /**
     * Tests adding a IPv4 route whose next hop is the local BGP speaker.
     */
    @Test
    public void testIpv4LocalRouteAdd() {
        // Construct a route entry, the next hop is the local BGP speaker
        RouteEntry routeEntry = new RouteEntry(
                Ip4Prefix.valueOf("1.1.1.0/24"),
                Ip4Address.valueOf("0.0.0.0"));

        // No methods on the FIB listener should be called
        replay(fibListener);

        reset(routingConfigurationService);
        expect(routingConfigurationService.isIpPrefixLocal(
                anyObject(IpPrefix.class))).andReturn(true);
        replay(routingConfigurationService);

        // Call the processRouteUpdates() method in Router class
        RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
                                                  routeEntry);
        router.processRouteUpdates(Collections.singletonList(routeUpdate));

        // Verify
        assertEquals(1, router.getRoutes4().size());
        assertTrue(router.getRoutes4().contains(routeEntry));
        verify(fibListener);
    }

    /**
     * Tests adding a IPv6 route whose next hop is the local BGP speaker.
     */
    @Test
    public void testIpv6LocalRouteAdd() {
        // Construct a route entry, the next hop is the local BGP speaker
        RouteEntry routeEntry = new RouteEntry(
                Ip6Prefix.valueOf("4000::/64"),
                Ip6Address.valueOf("::"));

        // No methods on the FIB listener should be called
        replay(fibListener);

        reset(routingConfigurationService);
        expect(routingConfigurationService.isIpPrefixLocal(
                anyObject(IpPrefix.class))).andReturn(true);
        replay(routingConfigurationService);

        // Call the processRouteUpdates() method in Router class
        RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
                                                  routeEntry);
        router.processRouteUpdates(Collections.singletonList(routeUpdate));

        // Verify
        assertEquals(1, router.getRoutes6().size());
        assertTrue(router.getRoutes6().contains(routeEntry));
        verify(fibListener);
    }
}
