/*
 * Copyright 2014 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.onlab.onos.sdnip.bgp;

import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;

import java.util.ArrayList;

import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;

/**
 * Unit tests for the BgpRouteEntry class.
 */
public class BgpRouteEntryTest {
    private BgpSession bgpSession;
    private static final Ip4Address BGP_SESSION_BGP_ID =
        Ip4Address.valueOf("10.0.0.1");
    private static final Ip4Address BGP_SESSION_IP_ADDRESS =
        Ip4Address.valueOf("20.0.0.1");

    private BgpSession bgpSession2;
    private static final Ip4Address BGP_SESSION_BGP_ID2 =
        Ip4Address.valueOf("10.0.0.2");
    private static final Ip4Address BGP_SESSION_IP_ADDRESS2 =
        Ip4Address.valueOf("20.0.0.1");

    private BgpSession bgpSession3;
    private static final Ip4Address BGP_SESSION_BGP_ID3 =
        Ip4Address.valueOf("10.0.0.1");
    private static final Ip4Address BGP_SESSION_IP_ADDRESS3 =
        Ip4Address.valueOf("20.0.0.2");

    @Before
    public void setUp() throws Exception {
        // Mock objects for testing
        bgpSession = createMock(BgpSession.class);
        bgpSession2 = createMock(BgpSession.class);
        bgpSession3 = createMock(BgpSession.class);

        // Setup the BGP Sessions
        expect(bgpSession.getRemoteBgpId())
            .andReturn(BGP_SESSION_BGP_ID).anyTimes();
        expect(bgpSession.getRemoteIp4Address())
            .andReturn(BGP_SESSION_IP_ADDRESS).anyTimes();
        //
        expect(bgpSession2.getRemoteBgpId())
            .andReturn(BGP_SESSION_BGP_ID2).anyTimes();
        expect(bgpSession2.getRemoteIp4Address())
            .andReturn(BGP_SESSION_IP_ADDRESS2).anyTimes();
        //
        expect(bgpSession3.getRemoteBgpId())
            .andReturn(BGP_SESSION_BGP_ID3).anyTimes();
        expect(bgpSession3.getRemoteIp4Address())
            .andReturn(BGP_SESSION_IP_ADDRESS3).anyTimes();

        replay(bgpSession);
        replay(bgpSession2);
        replay(bgpSession3);
    }

    /**
     * Generates a BGP Route Entry.
     *
     * @return a generated BGP Route Entry
     */
    private BgpRouteEntry generateBgpRouteEntry() {
        Ip4Prefix prefix = Ip4Prefix.valueOf("1.2.3.0/24");
        Ip4Address nextHop = Ip4Address.valueOf("5.6.7.8");
        byte origin = BgpConstants.Update.Origin.IGP;
        // Setup the AS Path
        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
        byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
        ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
        segmentAsNumbers1.add((long) 1);
        segmentAsNumbers1.add((long) 2);
        segmentAsNumbers1.add((long) 3);
        BgpRouteEntry.PathSegment pathSegment1 =
            new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
        pathSegments.add(pathSegment1);
        //
        byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
        ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
        segmentAsNumbers2.add((long) 4);
        segmentAsNumbers2.add((long) 5);
        segmentAsNumbers2.add((long) 6);
        BgpRouteEntry.PathSegment pathSegment2 =
            new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
        pathSegments.add(pathSegment2);
        //
        BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
        //
        long localPref = 100;
        long multiExitDisc = 20;

        BgpRouteEntry bgpRouteEntry =
            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
                              localPref);
        bgpRouteEntry.setMultiExitDisc(multiExitDisc);

        return bgpRouteEntry;
    }

    /**
     * Tests valid class constructor.
     */
    @Test
    public void testConstructor() {
        BgpRouteEntry bgpRouteEntry = generateBgpRouteEntry();

        String expectedString =
            "BgpRouteEntry{prefix=1.2.3.0/24, nextHop=5.6.7.8, " +
            "bgpId=10.0.0.1, origin=IGP, asPath=AsPath{pathSegments=" +
            "[PathSegment{type=AS_SEQUENCE, segmentAsNumbers=[1, 2, 3]}, " +
            "PathSegment{type=AS_SET, segmentAsNumbers=[4, 5, 6]}]}, " +
            "localPref=100, multiExitDisc=20}";
        assertThat(bgpRouteEntry.toString(), is(expectedString));
    }

    /**
     * Tests invalid class constructor for null BGP Session.
     */
    @Test(expected = NullPointerException.class)
    public void testInvalidConstructorNullBgpSession() {
        BgpSession bgpSessionNull = null;
        Ip4Prefix prefix = Ip4Prefix.valueOf("1.2.3.0/24");
        Ip4Address nextHop = Ip4Address.valueOf("5.6.7.8");
        byte origin = BgpConstants.Update.Origin.IGP;
        // Setup the AS Path
        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
        BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
        //
        long localPref = 100;

        new BgpRouteEntry(bgpSessionNull, prefix, nextHop, origin, asPath,
                    localPref);
    }

    /**
     * Tests invalid class constructor for null AS Path.
     */
    @Test(expected = NullPointerException.class)
    public void testInvalidConstructorNullAsPath() {
        Ip4Prefix prefix = Ip4Prefix.valueOf("1.2.3.0/24");
        Ip4Address nextHop = Ip4Address.valueOf("5.6.7.8");
        byte origin = BgpConstants.Update.Origin.IGP;
        BgpRouteEntry.AsPath asPath = null;
        long localPref = 100;

        new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
                    localPref);
    }

    /**
     * Tests getting the fields of a BGP route entry.
     */
    @Test
    public void testGetFields() {
        // Create the fields to compare against
        Ip4Prefix prefix = Ip4Prefix.valueOf("1.2.3.0/24");
        Ip4Address nextHop = Ip4Address.valueOf("5.6.7.8");
        byte origin = BgpConstants.Update.Origin.IGP;
        // Setup the AS Path
        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
        byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
        ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
        segmentAsNumbers1.add((long) 1);
        segmentAsNumbers1.add((long) 2);
        segmentAsNumbers1.add((long) 3);
        BgpRouteEntry.PathSegment pathSegment1 =
            new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
        pathSegments.add(pathSegment1);
        //
        byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
        ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
        segmentAsNumbers2.add((long) 4);
        segmentAsNumbers2.add((long) 5);
        segmentAsNumbers2.add((long) 6);
        BgpRouteEntry.PathSegment pathSegment2 =
            new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
        pathSegments.add(pathSegment2);
        //
        BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
        //
        long localPref = 100;
        long multiExitDisc = 20;

        // Generate the entry to test
        BgpRouteEntry bgpRouteEntry = generateBgpRouteEntry();

        assertThat(bgpRouteEntry.prefix(), is(prefix));
        assertThat(bgpRouteEntry.nextHop(), is(nextHop));
        assertThat(bgpRouteEntry.getBgpSession(), is(bgpSession));
        assertThat(bgpRouteEntry.getOrigin(), is(origin));
        assertThat(bgpRouteEntry.getAsPath(), is(asPath));
        assertThat(bgpRouteEntry.getLocalPref(), is(localPref));
        assertThat(bgpRouteEntry.getMultiExitDisc(), is(multiExitDisc));
    }

    /**
     * Tests whether a BGP route entry is a local route.
     */
    @Test
    public void testIsLocalRoute() {
        //
        // Test non-local route
        //
        BgpRouteEntry bgpRouteEntry = generateBgpRouteEntry();
        assertThat(bgpRouteEntry.isLocalRoute(), is(false));

        //
        // Test local route with AS Path that begins with AS_SET
        //
        Ip4Prefix prefix = Ip4Prefix.valueOf("1.2.3.0/24");
        Ip4Address nextHop = Ip4Address.valueOf("5.6.7.8");
        byte origin = BgpConstants.Update.Origin.IGP;
        // Setup the AS Path
        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
        byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SET;
        ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
        segmentAsNumbers1.add((long) 1);
        segmentAsNumbers1.add((long) 2);
        segmentAsNumbers1.add((long) 3);
        BgpRouteEntry.PathSegment pathSegment1 =
            new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
        pathSegments.add(pathSegment1);
        //
        byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
        ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
        segmentAsNumbers2.add((long) 4);
        segmentAsNumbers2.add((long) 5);
        segmentAsNumbers2.add((long) 6);
        BgpRouteEntry.PathSegment pathSegment2 =
            new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
        pathSegments.add(pathSegment2);
        //
        BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
        //
        long localPref = 100;
        long multiExitDisc = 20;
        //
        bgpRouteEntry =
            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
                              localPref);
        bgpRouteEntry.setMultiExitDisc(multiExitDisc);
        assertThat(bgpRouteEntry.isLocalRoute(), is(true));

        //
        // Test local route with empty AS Path
        //
        pathSegments = new ArrayList<>();
        asPath = new BgpRouteEntry.AsPath(pathSegments);
        bgpRouteEntry =
            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
                              localPref);
        bgpRouteEntry.setMultiExitDisc(multiExitDisc);
        assertThat(bgpRouteEntry.isLocalRoute(), is(true));
    }

    /**
     * Tests getting the BGP Neighbor AS number for a route.
     */
    @Test
    public void testGetNeighborAs() {
        //
        // Get neighbor AS for non-local route
        //
        BgpRouteEntry bgpRouteEntry = generateBgpRouteEntry();
        assertThat(bgpRouteEntry.getNeighborAs(), is((long) 1));

        //
        // Get neighbor AS for a local route
        //
        Ip4Prefix prefix = Ip4Prefix.valueOf("1.2.3.0/24");
        Ip4Address nextHop = Ip4Address.valueOf("5.6.7.8");
        byte origin = BgpConstants.Update.Origin.IGP;
        // Setup the AS Path
        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
        BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
        //
        long localPref = 100;
        long multiExitDisc = 20;
        //
        bgpRouteEntry =
            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
                              localPref);
        bgpRouteEntry.setMultiExitDisc(multiExitDisc);
        assertThat(bgpRouteEntry.getNeighborAs(), is(BgpConstants.BGP_AS_0));
    }

    /**
     * Tests whether a BGP route entry has AS Path loop.
     */
    @Test
    public void testHasAsPathLoop() {
        BgpRouteEntry bgpRouteEntry = generateBgpRouteEntry();

        // Test for loops: test each AS number in the interval [1, 6]
        for (int i = 1; i <= 6; i++) {
            assertThat(bgpRouteEntry.hasAsPathLoop(i), is(true));
        }

        // Test for non-loops
        assertThat(bgpRouteEntry.hasAsPathLoop(500), is(false));
    }

    /**
     * Tests the BGP Decision Process comparison of BGP routes.
     */
    @Test
    public void testBgpDecisionProcessComparison() {
        BgpRouteEntry bgpRouteEntry1 = generateBgpRouteEntry();
        BgpRouteEntry bgpRouteEntry2 = generateBgpRouteEntry();

        //
        // Compare two routes that are same
        //
        assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(true));
        assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(true));

        //
        // Compare two routes with different LOCAL_PREF
        //
        Ip4Prefix prefix = Ip4Prefix.valueOf("1.2.3.0/24");
        Ip4Address nextHop = Ip4Address.valueOf("5.6.7.8");
        byte origin = BgpConstants.Update.Origin.IGP;
        // Setup the AS Path
        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
        byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
        ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
        segmentAsNumbers1.add((long) 1);
        segmentAsNumbers1.add((long) 2);
        segmentAsNumbers1.add((long) 3);
        BgpRouteEntry.PathSegment pathSegment1 =
            new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
        pathSegments.add(pathSegment1);
        //
        byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
        ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
        segmentAsNumbers2.add((long) 4);
        segmentAsNumbers2.add((long) 5);
        segmentAsNumbers2.add((long) 6);
        BgpRouteEntry.PathSegment pathSegment2 =
            new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
        pathSegments.add(pathSegment2);
        //
        BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
        //
        long localPref = 50;                                    // Different
        long multiExitDisc = 20;
        bgpRouteEntry2 =
            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
                              localPref);
        bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
        //
        assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(true));
        assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(false));
        localPref = bgpRouteEntry1.getLocalPref();              // Restore

        //
        // Compare two routes with different AS_PATH length
        //
        ArrayList<BgpRouteEntry.PathSegment> pathSegments2 = new ArrayList<>();
        pathSegments2.add(pathSegment1);
        // Different AS Path
        BgpRouteEntry.AsPath asPath2 = new BgpRouteEntry.AsPath(pathSegments2);
        bgpRouteEntry2 =
            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath2,
                              localPref);
        bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
        //
        assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(false));
        assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(true));

        //
        // Compare two routes with different ORIGIN
        //
        origin = BgpConstants.Update.Origin.EGP;                // Different
        bgpRouteEntry2 =
            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
                              localPref);
        bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
        //
        assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(true));
        assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(false));
        origin = bgpRouteEntry1.getOrigin();                    // Restore

        //
        // Compare two routes with different MULTI_EXIT_DISC
        //
        multiExitDisc = 10;                                     // Different
        bgpRouteEntry2 =
            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
                              localPref);
        bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
        //
        assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(true));
        assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(false));
        multiExitDisc = bgpRouteEntry1.getMultiExitDisc();      // Restore

        //
        // Compare two routes with different BGP ID
        //
        bgpRouteEntry2 =
            new BgpRouteEntry(bgpSession2, prefix, nextHop, origin, asPath,
                              localPref);
        bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
        //
        assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(true));
        assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(false));

        //
        // Compare two routes with different BGP address
        //
        bgpRouteEntry2 =
            new BgpRouteEntry(bgpSession3, prefix, nextHop, origin, asPath,
                              localPref);
        bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
        //
        assertThat(bgpRouteEntry1.isBetterThan(bgpRouteEntry2), is(true));
        assertThat(bgpRouteEntry2.isBetterThan(bgpRouteEntry1), is(false));
    }

    /**
     * Tests equality of {@link BgpRouteEntry}.
     */
    @Test
    public void testEquality() {
        BgpRouteEntry bgpRouteEntry1 = generateBgpRouteEntry();
        BgpRouteEntry bgpRouteEntry2 = generateBgpRouteEntry();

        assertThat(bgpRouteEntry1, is(bgpRouteEntry2));
    }

    /**
     * Tests non-equality of {@link BgpRouteEntry}.
     */
    @Test
    public void testNonEquality() {
        BgpRouteEntry bgpRouteEntry1 = generateBgpRouteEntry();

        // Setup BGP Route 2
        Ip4Prefix prefix = Ip4Prefix.valueOf("1.2.3.0/24");
        Ip4Address nextHop = Ip4Address.valueOf("5.6.7.8");
        byte origin = BgpConstants.Update.Origin.IGP;
        // Setup the AS Path
        ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
        byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
        ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
        segmentAsNumbers1.add((long) 1);
        segmentAsNumbers1.add((long) 2);
        segmentAsNumbers1.add((long) 3);
        BgpRouteEntry.PathSegment pathSegment1 =
            new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
        pathSegments.add(pathSegment1);
        //
        byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
        ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
        segmentAsNumbers2.add((long) 4);
        segmentAsNumbers2.add((long) 5);
        segmentAsNumbers2.add((long) 6);
        BgpRouteEntry.PathSegment pathSegment2 =
            new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
        pathSegments.add(pathSegment2);
        //
        BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
        //
        long localPref = 500;                                   // Different
        long multiExitDisc = 20;
        BgpRouteEntry bgpRouteEntry2 =
            new BgpRouteEntry(bgpSession, prefix, nextHop, origin, asPath,
                              localPref);
        bgpRouteEntry2.setMultiExitDisc(multiExitDisc);

        assertThat(bgpRouteEntry1, is(not(bgpRouteEntry2)));
    }

    /**
     * Tests object string representation.
     */
    @Test
    public void testToString() {
        BgpRouteEntry bgpRouteEntry = generateBgpRouteEntry();

        String expectedString =
            "BgpRouteEntry{prefix=1.2.3.0/24, nextHop=5.6.7.8, " +
            "bgpId=10.0.0.1, origin=IGP, asPath=AsPath{pathSegments=" +
            "[PathSegment{type=AS_SEQUENCE, segmentAsNumbers=[1, 2, 3]}, " +
            "PathSegment{type=AS_SET, segmentAsNumbers=[4, 5, 6]}]}, " +
            "localPref=100, multiExitDisc=20}";
        assertThat(bgpRouteEntry.toString(), is(expectedString));
    }
}
