/*
 * 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 org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.*;
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 TokenBucket.
 */
public class TokenBucketTest {

    // Test rate
    private static final long RATE = 1;
    // Test dscp drop precedence
    private static final short DSCP_PREC = 2;
    // Test dscp class
    private static final short DSCP_CL = 250;
    // Test wrong dscp
    private static final short WRONG_DSCP = -1;

    /**
     * Test creation of a drop token bucket.
     */
    @Test
    public void testDropCreation() {
        // Create a drop token bucket
        TokenBucket drop = DefaultTokenBucket.builder()
                .withRate(RATE)
                .withAction(DROP)
                .build();
        // Not null
        assertThat(drop, notNullValue());
        // Rate should be equal to RATE
        assertThat(drop.rate(), is(RATE));
        // Burst size should be equal to 2xMTU
        assertThat(drop.burstSize(), is(2 * 1500L));
        // Action should be drop
        assertThat(drop.action(), is(DROP));
    }

    /**
     * Test creation of a dscp precedence token bucket.
     */
    @Test
    public void testDscpPrecCreation() {
        // Create a dscp precedence token bucket
        TokenBucket drop = DefaultTokenBucket.builder()
                .withRate(RATE)
                .withAction(DSCP_PRECEDENCE)
                .withBurstSize(6 * 1500)
                .withDscp(DSCP_PREC)
                .build();
        // Not null
        assertThat(drop, notNullValue());
        // Rate should be equal to RATE
        assertThat(drop.rate(), is(RATE));
        // Burst size should be equal to 6xMTU
        assertThat(drop.burstSize(), is(6 * 1500L));
        // Action should increase dscp drop precedence
        assertThat(drop.action(), is(DSCP_PRECEDENCE));
        // Dcsp drop precedence should be increased of 2
        assertThat(drop.dscp(), is(DSCP_PREC));
    }

    /**
     * Test creation of a dscp class token bucket.
     */
    @Test
    public void testDscpClassCreation() {
        // Create a dscp class token bucket
        TokenBucket drop = DefaultTokenBucket.builder()
                .withRate(RATE)
                .withAction(DSCP_CLASS)
                .withDscp(DSCP_CL)
                .build();
        // Not null
        assertThat(drop, notNullValue());
        // Rate should be equal to RATE
        assertThat(drop.rate(), is(RATE));
        // Burst size should be equal to 2xMTU
        assertThat(drop.burstSize(), is(2 * 1500L));
        // Action should be drop
        assertThat(drop.action(), is(DSCP_CLASS));
        // Dcsp drop precedence should be increased of 2
        assertThat(drop.dscp(), is(DSCP_CL));
    }

    /**
     * Exception expected to raise when creating a token bucket with null action.
     */
    @Rule
    public ExpectedException exceptionNullAction = ExpectedException.none();

    /**
     * Test creation of a token bucket with null action.
     */
    @Test
    public void testNullActionCreation() {
        // Define expected exception
        exceptionNullAction.expect(NullPointerException.class);
        // Create a token bucket without action
        TokenBucket drop = DefaultTokenBucket.builder()
                .withRate(RATE)
                .build();
    }

    /**
     * Exception expected to raise when creating a token bucket with wrong dscp.
     */
    @Rule
    public ExpectedException exceptionWrongDscp = ExpectedException.none();

    /**
     * Test creation of a token bucket with wrong dscp.
     */
    @Test
    public void testWrongDscpCreation() {
        // Define expected exception
        exceptionWrongDscp.expect(IllegalArgumentException.class);
        // Create a token bucket with wrong dscp
        TokenBucket drop = DefaultTokenBucket.builder()
                .withRate(RATE)
                .withAction(DSCP_PRECEDENCE)
                .withDscp(WRONG_DSCP)
                .build();
    }

    /**
     * Test equality between policer ids.
     */
    @Test
    public void testEqualilty() {
        // Create a drop token bucket
        TokenBucket drop = DefaultTokenBucket.builder()
                .withRate(RATE)
                .withAction(DROP)
                .build();
        // Create a mark token bucket
        TokenBucket mark = DefaultTokenBucket.builder()
                .withRate(RATE)
                .withAction(DSCP_PRECEDENCE)
                .withDscp(DSCP_PREC)
                .build();
        // Create a copy of the drop token bucket
        TokenBucket copyDrop = DefaultTokenBucket.builder()
                .withRate(RATE)
                .withAction(DROP)
                .build();
        // Verify equality
        assertEquals(drop, copyDrop);
        // Verify not equals
        assertNotEquals(mark, drop);
        assertNotEquals(mark, copyDrop);
    }

}
