/*
 * Copyright 2017-present Open Networking Foundation
 *
 * 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.net.behaviour.trafficcontrol;

import com.google.common.collect.ImmutableList;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.onosproject.TestApplicationId;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.DeviceId;

import static org.hamcrest.Matchers.is;
import static org.junit.Assert.*;
import static org.onosproject.net.behaviour.trafficcontrol.Policer.Unit.KB_PER_SEC;
import static org.onosproject.net.behaviour.trafficcontrol.Policer.Unit.MB_PER_SEC;
import static org.onosproject.net.behaviour.trafficcontrol.TokenBucket.Action.DROP;
import static org.onosproject.net.behaviour.trafficcontrol.TokenBucket.Action.DSCP_CLASS;
import static org.onosproject.net.behaviour.trafficcontrol.TokenBucket.Action.DSCP_PRECEDENCE;

/**
 * Test class for policer implementation.
 */
public class PolicerTest {

    // Fake Application Id
    private static final ApplicationId FOO_APP_ID = new TestApplicationId("foo");
    // Connect points
    private static final String SDID1 = "of:00000000000001";
    private static final DeviceId DID1 = DeviceId.deviceId(SDID1);
    // OpenFlow scheme
    private static final String OF_SCHEME = "of";
    // Policers identifiers
    private static final String SID1 = OF_SCHEME + ":" + Integer.toHexString(1);
    private static final PolicerId ID1 = PolicerId.policerId(SID1);
    private static final String SID2 = OF_SCHEME + ":" + Integer.toHexString(2);
    private static final PolicerId ID2 = PolicerId.policerId(SID2);
    private static final String SID3 = OF_SCHEME + ":" + Integer.toHexString(3);
    private static final PolicerId ID3 = PolicerId.policerId(SID3);
    private static final String SID4 = OF_SCHEME + ":" + Integer.toHexString(4);
    private static final PolicerId ID4 = PolicerId.policerId(SID4);
    private static final String SID5 = OF_SCHEME + ":" + Integer.toHexString(5);
    private static final PolicerId ID5 = PolicerId.policerId(SID5);
    private static final String SID6 = OF_SCHEME + ":" + Integer.toHexString(6);
    private static final PolicerId ID6 = PolicerId.policerId(SID6);
    private static final String SID7 = OF_SCHEME + ":" + Integer.toHexString(7);
    private static final PolicerId ID7 = PolicerId.policerId(SID7);
    private static final String SID8 = OF_SCHEME + ":" + Integer.toHexString(8);
    private static final PolicerId ID8 = PolicerId.policerId(SID8);
    private static final String SID9 = OF_SCHEME + ":" + Integer.toHexString(9);
    private static final PolicerId ID9 = PolicerId.policerId(SID9);

    /**
     * Test block traffic policer.
     */
    @Test
    public void testBlockCreation() {
        // Create a block traffic token bucket
        TokenBucket tokenBucket = DefaultTokenBucket.builder()
                .withBurstSize(0)
                .withAction(DROP)
                .build();
        // Create a policer with above token bucket
        Policer policer = DefaultPolicer.builder()
                .forDeviceId(DID1)
                .fromApp(FOO_APP_ID)
                .withId(ID1)
                .withTokenBuckets(ImmutableList.of(tokenBucket))
                .build();
        // Assert on device id
        assertThat(policer.deviceId(), is(DID1));
        // Assert on app id
        assertThat(policer.applicationId(), is(FOO_APP_ID));
        // Assert on policer id
        assertThat(policer.policerId(), is(ID1));
        // It is not color aware
        assertFalse(policer.isColorAware());
        // Unit is Mbps
        assertThat(policer.unit(), is(MB_PER_SEC));
        // One token bucket
        assertThat(policer.tokenBuckets().size(), is(1));
        // One token bucket equals to tokenBucket
        assertTrue(policer.tokenBuckets().contains(tokenBucket));
    }

    /**
     * Test simple drop policer.
     */
    @Test
    public void testDropCreation() {
        // Create a drop traffic token bucket at 1MB/s
        TokenBucket tokenBucket = DefaultTokenBucket.builder()
                .withRate(1)
                .withAction(DROP)
                .build();
        // Create a policer with above token bucket
        Policer policer = DefaultPolicer.builder()
                .forDeviceId(DID1)
                .fromApp(FOO_APP_ID)
                .withId(ID2)
                .withTokenBuckets(ImmutableList.of(tokenBucket))
                .build();
        // Assert on device id
        assertThat(policer.deviceId(), is(DID1));
        // Assert on app id
        assertThat(policer.applicationId(), is(FOO_APP_ID));
        // Assert on policer id
        assertThat(policer.policerId(), is(ID2));
        // It is not color aware
        assertFalse(policer.isColorAware());
        // Unit is Mbps
        assertThat(policer.unit(), is(MB_PER_SEC));
        // One token bucket
        assertThat(policer.tokenBuckets().size(), is(1));
        // One token bucket equals to tokenBucket
        assertTrue(policer.tokenBuckets().contains(tokenBucket));
    }

    /**
     * Test simple mark policer.
     */
    @Test
    public void testMarkCreation() {
        // Create a drop traffic token bucket at 1MB/s
        TokenBucket tokenBucket = DefaultTokenBucket.builder()
                .withRate(1)
                .withAction(DSCP_PRECEDENCE)
                .withDscp((short) 2)
                .build();
        // Create a policer with above token bucket
        Policer policer = DefaultPolicer.builder()
                .forDeviceId(DID1)
                .fromApp(FOO_APP_ID)
                .withId(ID3)
                .withTokenBuckets(ImmutableList.of(tokenBucket))
                .build();
        // Assert on device id
        assertThat(policer.deviceId(), is(DID1));
        // Assert on app id
        assertThat(policer.applicationId(), is(FOO_APP_ID));
        // Assert on policer id
        assertThat(policer.policerId(), is(ID3));
        // It is not color aware
        assertFalse(policer.isColorAware());
        // Unit is Mbps
        assertThat(policer.unit(), is(MB_PER_SEC));
        // One token bucket
        assertThat(policer.tokenBuckets().size(), is(1));
        // One token bucket equals to tokenBucket
        assertTrue(policer.tokenBuckets().contains(tokenBucket));
    }

    /**
     * Test single rate three colors scenario (RFC 2697).
     */
    @Test
    public void testSingleRateThreeColors() {
        // Create token bucket for committed rate
        TokenBucket crTokenBucket = DefaultTokenBucket.builder()
                .withRate(1)
                .withAction(DSCP_PRECEDENCE)
                .withDscp((short) 2)
                .build();
        // Create token bucket for excess rate
        TokenBucket erTokenBucket = DefaultTokenBucket.builder()
                .withRate(1)
                .withBurstSize(4 * 1500)
                .withAction(DROP)
                .build();
        // Create a policer with above token buckets
        Policer policer = DefaultPolicer.builder()
                .forDeviceId(DID1)
                .fromApp(FOO_APP_ID)
                .withId(ID4)
                // The order is important
                .withTokenBuckets(ImmutableList.of(crTokenBucket, erTokenBucket))
                .build();
        // Assert on device id
        assertThat(policer.deviceId(), is(DID1));
        // Assert on app id
        assertThat(policer.applicationId(), is(FOO_APP_ID));
        // Assert on policer id
        assertThat(policer.policerId(), is(ID4));
        // It is not color aware
        assertFalse(policer.isColorAware());
        // Unit is Mbps
        assertThat(policer.unit(), is(MB_PER_SEC));
        // Two token buckets
        assertThat(policer.tokenBuckets().size(), is(2));
        // One token bucket equals to crTokenBucket
        assertTrue(policer.tokenBuckets().contains(crTokenBucket));
        // One token bucket equals to erTokenBucket
        assertTrue(policer.tokenBuckets().contains(erTokenBucket));
    }

    /**
     * Test two rates three colors scenario (RFC 2698 and P4 meter).
     */
    @Test
    public void testTwoRatesThreeColors() {
        // Create token bucket for peak rate at 10Mb/s
        TokenBucket prTokenBucket = DefaultTokenBucket.builder()
                // (10 * 1000)/8 ---> 1250KB/s
                .withRate(1250)
                .withBurstSize(10 * 1500)
                .withAction(DROP)
                .build();
        // Create token bucket for committed rate at 1Mb/s
        TokenBucket crTokenBucket = DefaultTokenBucket.builder()
                // (1 * 1000)/8 ---> 125KB/s
                .withRate(125)
                .withAction(DSCP_CLASS)
                .withDscp((short) 10)
                .build();
        // Create a policer with above token buckets
        Policer policer = DefaultPolicer.builder()
                .forDeviceId(DID1)
                .fromApp(FOO_APP_ID)
                .withId(ID5)
                .withUnit(KB_PER_SEC)
                // The order is important
                .withTokenBuckets(ImmutableList.of(prTokenBucket, crTokenBucket))
                .build();
        // Assert on device id
        assertThat(policer.deviceId(), is(DID1));
        // Assert on app id
        assertThat(policer.applicationId(), is(FOO_APP_ID));
        // Assert on policer id
        assertThat(policer.policerId(), is(ID5));
        // It is not color aware
        assertFalse(policer.isColorAware());
        // Unit is Mbps
        assertThat(policer.unit(), is(KB_PER_SEC));
        // Two token buckets
        assertThat(policer.tokenBuckets().size(), is(2));
        // One token bucket equals to prTokenBucket
        assertTrue(policer.tokenBuckets().contains(prTokenBucket));
        // One token bucket equals to crTokenBucket
        assertTrue(policer.tokenBuckets().contains(crTokenBucket));
    }

    /**
     * Exception expected to raise when creating a policer with null params.
     */
    @Rule
    public ExpectedException exceptionNullParam = ExpectedException.none();

    /**
     * Test creation with null parameters.
     */
    @Test
    public void testNullParam() {
        // Define expected exception
        exceptionNullParam.expect(NullPointerException.class);
        // Invalid policer, device id is not defined
        DefaultPolicer.builder()
                .fromApp(FOO_APP_ID)
                .withId(ID6)
                .build();
    }

    /**
     * Exception expected to raise when creating a policer without token buckets.
     */
    @Rule
    public ExpectedException exceptionNoTokenBuckets = ExpectedException.none();

    /**
     * Test creation without token buckets.
     */
    @Test
    public void testNoTokenBuckets() {
        // Define expected exception
        exceptionNoTokenBuckets.expect(IllegalArgumentException.class);
        // Invalid policer, no token buckets
        DefaultPolicer.builder()
                .fromApp(FOO_APP_ID)
                .withId(ID7)
                .forDeviceId(DID1)
                .withTokenBuckets(ImmutableList.of())
                .build();
    }

    /**
     * Test equality between policers.
     */
    @Test
    public void testEqualilty() {
        // Create a block traffic token bucket
        TokenBucket blockTokenBucket = DefaultTokenBucket.builder()
                .withBurstSize(0)
                .withAction(DROP)
                .build();
        // Create a mark traffic token bucket
        TokenBucket markTokenBucket = DefaultTokenBucket.builder()
                .withBurstSize(0)
                .withAction(DSCP_CLASS)
                .withDscp((short) 10)
                .build();
        // Create first policer
        Policer policerOne = DefaultPolicer.builder()
                .forDeviceId(DID1)
                .fromApp(FOO_APP_ID)
                .withId(ID8)
                .withTokenBuckets(ImmutableList.of(blockTokenBucket))
                .build();
        // Create second policer
        Policer policerTwo = DefaultPolicer.builder()
                .forDeviceId(DID1)
                .fromApp(FOO_APP_ID)
                .withId(ID9)
                .withTokenBuckets(ImmutableList.of(markTokenBucket))
                .build();
        // Create third policer copy of one
        // Create first policer
        Policer policerThree = DefaultPolicer.builder()
                .forDeviceId(DID1)
                .fromApp(FOO_APP_ID)
                .withId(ID8)
                .withTokenBuckets(ImmutableList.of(blockTokenBucket))
                .build();
        // One and Three are equal
        assertEquals(policerOne, policerThree);
        // Two is different due to the different id
        assertNotEquals(policerOne, policerTwo);
        assertNotEquals(policerThree, policerTwo);
    }

}
