/*
 * Copyright 2016-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.lisp.ctl.impl;

import com.google.common.collect.ImmutableList;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.IpAddress;
import org.onosproject.lisp.msg.protocols.DefaultLispMapRecord.DefaultMapRecordBuilder;
import org.onosproject.lisp.msg.protocols.LispEidRecord;
import org.onosproject.lisp.msg.protocols.LispLocatorRecord;
import org.onosproject.lisp.msg.protocols.LispMapRecord;
import org.onosproject.lisp.msg.protocols.DefaultLispLocatorRecord.DefaultLocatorRecordBuilder;
import org.onosproject.lisp.msg.protocols.LispMapRecord.MapRecordBuilder;
import org.onosproject.lisp.msg.types.LispIpv4Address;

import java.util.List;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;

/**
 * Tests for LISP EID RLOC Map class.
 */
public class LispMappingDatabaseTest {

    final LispMappingDatabase mapDb = LispMappingDatabase.getInstance();

    @Before
    public void setup() {

        byte cidr1 = (byte) 32;
        LispIpv4Address eid1 = new LispIpv4Address(IpAddress.valueOf("10.1.1.1"));
        LispEidRecord eidRecord1 = new LispEidRecord(cidr1, eid1);

        LispIpv4Address locator11 = new LispIpv4Address(IpAddress.valueOf("123.1.1.1"));
        LispIpv4Address locator12 = new LispIpv4Address(IpAddress.valueOf("123.1.1.2"));
        LispIpv4Address locator13 = new LispIpv4Address(IpAddress.valueOf("123.1.1.3"));

        LispLocatorRecord locatorRecord11 = new DefaultLocatorRecordBuilder()
                                            .withLocatorAfi(locator11).build();
        LispLocatorRecord locatorRecord12 = new DefaultLocatorRecordBuilder()
                                            .withLocatorAfi(locator12).build();
        LispLocatorRecord locatorRecord13 = new DefaultLocatorRecordBuilder()
                                            .withLocatorAfi(locator13).build();
        List<LispLocatorRecord> locatorRecords1 =
                ImmutableList.of(locatorRecord11, locatorRecord12, locatorRecord13);

        byte cidr2 = (byte) 24;
        LispIpv4Address eid2 = new LispIpv4Address(IpAddress.valueOf("10.1.2.0"));
        LispEidRecord eidRecord2 = new LispEidRecord(cidr2, eid2);

        LispIpv4Address locator21 = new LispIpv4Address(IpAddress.valueOf("123.2.1.1"));
        LispIpv4Address locator22 = new LispIpv4Address(IpAddress.valueOf("123.2.1.2"));

        LispLocatorRecord locatorRecord21 = new DefaultLocatorRecordBuilder()
                                            .withLocatorAfi(locator21).build();
        LispLocatorRecord locatorRecord22 = new DefaultLocatorRecordBuilder()
                                            .withLocatorAfi(locator22).build();

        List<LispLocatorRecord> locatorRecords2 =
                    ImmutableList.of(locatorRecord21, locatorRecord22);

        byte cidr3 = (byte) 16;
        LispIpv4Address eid3 = new LispIpv4Address(IpAddress.valueOf("10.2.0.0"));
        LispEidRecord eidRecord3 = new LispEidRecord(cidr3, eid3);

        LispIpv4Address locator31 = new LispIpv4Address(IpAddress.valueOf("123.3.1.1"));

        LispLocatorRecord locatorRecord31 = new DefaultLocatorRecordBuilder()
                                            .withLocatorAfi(locator31).build();

        List<LispLocatorRecord> locatorRecords3 = ImmutableList.of(locatorRecord31);

        MapRecordBuilder builder1 = new DefaultMapRecordBuilder();
        builder1.withMaskLength(cidr1);
        builder1.withEidPrefixAfi(eid1);
        builder1.withLocators(locatorRecords1);
        builder1.withRecordTtl(60);
        LispMapRecord mapRecord1 = builder1.build();

        MapRecordBuilder builder2 = new DefaultMapRecordBuilder();
        builder2.withMaskLength(cidr2);
        builder2.withEidPrefixAfi(eid2);
        builder2.withLocators(locatorRecords2);
        builder2.withRecordTtl(60);
        LispMapRecord mapRecord2 = builder2.build();

        MapRecordBuilder builder3 = new DefaultMapRecordBuilder();
        builder3.withMaskLength(cidr3);
        builder3.withEidPrefixAfi(eid3);
        builder3.withLocators(locatorRecords3);
        builder3.withRecordTtl(60);
        LispMapRecord mapRecord3 = builder3.build();

        mapDb.putMapRecord(eidRecord1, mapRecord1, true);
        mapDb.putMapRecord(eidRecord2, mapRecord2, true);
        mapDb.putMapRecord(eidRecord3, mapRecord3, true);
    }

    @Test
    public void test32MaskRange() {
        byte cidr32 = (byte) 32;
        LispIpv4Address eid = new LispIpv4Address(IpAddress.valueOf("10.1.1.1"));
        LispEidRecord record = new LispEidRecord(cidr32, eid);
        LispMapRecord mapRecord = mapDb.getMapRecordByEidRecord(record, true);

        assertThat("Failed to fetch the RLOCs with /32 EID record",
                    mapRecord.getLocatorCount(), is(3));
    }

    @Test
    public void test24MaskRange() {
        byte cidr32 = (byte) 32;
        LispIpv4Address eid = new LispIpv4Address(IpAddress.valueOf("10.1.2.1"));
        LispEidRecord record32 = new LispEidRecord(cidr32, eid);
        LispMapRecord mapRecord32 = mapDb.getMapRecordByEidRecord(record32, true);

        byte cidr24 = (byte) 24;
        LispIpv4Address eid24 = new LispIpv4Address(IpAddress.valueOf("10.1.2.0"));
        LispEidRecord record24 = new LispEidRecord(cidr24, eid24);
        LispMapRecord mapRecord24 = mapDb.getMapRecordByEidRecord(record24, true);

        assertThat("Failed to fetch the RLOCs with /32 EID record",
                    mapRecord32.getLocatorCount(), is(2));
        assertThat("Failed to fetch the RLOCs with /24 EID record",
                    mapRecord24.getLocatorCount(), is(2));
    }

    @Test
    public void test16MaskRange() {
        byte cidr32 = (byte) 32;
        LispIpv4Address eid = new LispIpv4Address(IpAddress.valueOf("10.2.1.1"));
        LispEidRecord record32 = new LispEidRecord(cidr32, eid);
        LispMapRecord mapRecord32 = mapDb.getMapRecordByEidRecord(record32, true);

        byte cidr24 = (byte) 24;
        LispIpv4Address eid24 = new LispIpv4Address(IpAddress.valueOf("10.2.1.0"));
        LispEidRecord record24 = new LispEidRecord(cidr24, eid24);
        LispMapRecord mapRecord24 = mapDb.getMapRecordByEidRecord(record24, true);

        byte cidr16 = (byte) 16;
        LispIpv4Address eid16 = new LispIpv4Address(IpAddress.valueOf("10.2.0.0"));
        LispEidRecord record16 = new LispEidRecord(cidr16, eid16);
        LispMapRecord mapRecord16 = mapDb.getMapRecordByEidRecord(record16, true);

        assertThat("Failed to fetch the RLOCs with /32 EID record",
                    mapRecord32.getLocatorCount(), is(1));
        assertThat("Failed to fetch the RLOCs with /24 EID record",
                    mapRecord24.getLocatorCount(), is(1));
        assertThat("Failed to fetch the RLOCs with /16 EID record",
                    mapRecord16.getLocatorCount(), is(1));
    }
}
