/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.distributedlog.service.stream.limiter;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import org.apache.distributedlog.DistributedLogConfiguration;
import org.apache.distributedlog.common.config.ConcurrentConstConfiguration;
import org.apache.distributedlog.config.DynamicDistributedLogConfiguration;
import org.apache.distributedlog.exceptions.OverCapacityException;
import org.apache.distributedlog.limiter.ChainedRequestLimiter;
import org.apache.distributedlog.limiter.ComposableRequestLimiter;
import org.apache.distributedlog.limiter.ComposableRequestLimiter.CostFunction;
import org.apache.distributedlog.limiter.ComposableRequestLimiter.OverlimitFunction;
import org.apache.distributedlog.limiter.GuavaRateLimiter;
import org.apache.distributedlog.limiter.RateLimiter;
import org.apache.distributedlog.limiter.RequestLimiter;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.bookkeeper.feature.SettableFeature;
import org.apache.bookkeeper.stats.NullStatsLogger;
import org.junit.Test;

/**
 * Test Case for {@link ServiceRequestLimiter}.
 */
public class TestServiceRequestLimiter {

    /**
     * Mock Request.
     */
    class MockRequest {
        int size;
        MockRequest() {
            this(1);
        }
        MockRequest(int size) {
            this.size = size;
        }
        int getSize() {
            return size;
        }
    }

    /**
     * Mock request limiter.
     */
    class MockRequestLimiter implements RequestLimiter<MockRequest> {
        public void apply(MockRequest request) {
        }
    }

    /**
     * Counter based limiter.
     */
    static class CounterLimiter implements RateLimiter {
        final int limit;
        int count;

        public CounterLimiter(int limit) {
            this.limit = limit;
            this.count = 0;
        }

        @Override
        public boolean acquire(int permits) {
            if (++count > limit) {
                return false;
            }
            return true;
        }
    }

    /**
     * Mock hard request limiter.
     */
    class MockHardRequestLimiter implements RequestLimiter<MockRequest> {

        RequestLimiter<MockRequest> limiter;
        int limitHitCount;

        MockHardRequestLimiter(int limit) {
            this(GuavaRateLimiter.of(limit));
        }

        MockHardRequestLimiter(RateLimiter limiter) {
            this.limiter = new ComposableRequestLimiter<MockRequest>(
                limiter,
                new OverlimitFunction<MockRequest>() {
                    public void apply(MockRequest request) throws OverCapacityException {
                        limitHitCount++;
                        throw new OverCapacityException("Limit exceeded");
                    }
                },
                new CostFunction<MockRequest>() {
                    public int apply(MockRequest request) {
                        return request.getSize();
                    }
                },
                NullStatsLogger.INSTANCE);
        }

        @Override
        public void apply(MockRequest op) throws OverCapacityException {
            limiter.apply(op);
        }

        public int getLimitHitCount() {
            return limitHitCount;
        }
    }

    /**
     * Mock soft request limiter.
     */
    class MockSoftRequestLimiter implements RequestLimiter<MockRequest> {

        RequestLimiter<MockRequest> limiter;
        int limitHitCount;

        MockSoftRequestLimiter(int limit) {
            this(GuavaRateLimiter.of(limit));
        }

        MockSoftRequestLimiter(RateLimiter limiter) {
            this.limiter = new ComposableRequestLimiter<MockRequest>(
                limiter,
                new OverlimitFunction<MockRequest>() {
                    public void apply(MockRequest request) throws OverCapacityException {
                        limitHitCount++;
                    }
                },
                new CostFunction<MockRequest>() {
                    public int apply(MockRequest request) {
                        return request.getSize();
                    }
                },
                NullStatsLogger.INSTANCE);
        }

        @Override
        public void apply(MockRequest op) throws OverCapacityException {
            limiter.apply(op);
        }

        public int getLimitHitCount() {
            return limitHitCount;
        }
    }

    @Test(timeout = 60000)
    public void testDynamicLimiter() throws Exception {
        final AtomicInteger id = new AtomicInteger(0);
        final DynamicDistributedLogConfiguration dynConf = new DynamicDistributedLogConfiguration(
                new ConcurrentConstConfiguration(new DistributedLogConfiguration()));
        DynamicRequestLimiter<MockRequest> limiter = new DynamicRequestLimiter<MockRequest>(
                dynConf, NullStatsLogger.INSTANCE, new SettableFeature("", 0)) {
            @Override
            public RequestLimiter<MockRequest> build() {
                id.getAndIncrement();
                return new MockRequestLimiter();
            }
        };
        limiter.initialize();
        assertEquals(1, id.get());
        dynConf.setProperty("test1", 1);
        assertEquals(2, id.get());
        dynConf.setProperty("test2", 2);
        assertEquals(3, id.get());
    }

    @Test(timeout = 60000)
    public void testDynamicLimiterWithDisabledFeature() throws Exception {
        final DynamicDistributedLogConfiguration dynConf = new DynamicDistributedLogConfiguration(
                new ConcurrentConstConfiguration(new DistributedLogConfiguration()));
        final MockSoftRequestLimiter rateLimiter = new MockSoftRequestLimiter(0);
        final SettableFeature disabledFeature = new SettableFeature("", 0);
        DynamicRequestLimiter<MockRequest> limiter = new DynamicRequestLimiter<MockRequest>(
                dynConf, NullStatsLogger.INSTANCE, disabledFeature) {
            @Override
            public RequestLimiter<MockRequest> build() {
                return rateLimiter;
            }
        };
        limiter.initialize();
        assertEquals(0, rateLimiter.getLimitHitCount());

        // Not disabled, rate limiter was invoked
        limiter.apply(new MockRequest(Integer.MAX_VALUE));
        assertEquals(1, rateLimiter.getLimitHitCount());

        // Disabled, rate limiter not invoked
        disabledFeature.set(1);
        limiter.apply(new MockRequest(Integer.MAX_VALUE));
        assertEquals(1, rateLimiter.getLimitHitCount());
    }

    @Test(timeout = 60000)
    public void testDynamicLimiterWithException() throws Exception {
        final AtomicInteger id = new AtomicInteger(0);
        final DynamicDistributedLogConfiguration dynConf = new DynamicDistributedLogConfiguration(
                new ConcurrentConstConfiguration(new DistributedLogConfiguration()));
        DynamicRequestLimiter<MockRequest> limiter = new DynamicRequestLimiter<MockRequest>(
                dynConf, NullStatsLogger.INSTANCE, new SettableFeature("", 0)) {
            @Override
            public RequestLimiter<MockRequest> build() {
                if (id.incrementAndGet() >= 2) {
                    throw new RuntimeException("exception in dynamic limiter build()");
                }
                return new MockRequestLimiter();
            }
        };
        limiter.initialize();
        assertEquals(1, id.get());
        try {
            dynConf.setProperty("test1", 1);
            fail("should have thrown on config failure");
        } catch (RuntimeException ex) {
        }
        assertEquals(2, id.get());
    }

    @Test(timeout = 60000)
    public void testServiceRequestLimiter() throws Exception {
        MockHardRequestLimiter limiter = new MockHardRequestLimiter(new CounterLimiter(1));
        limiter.apply(new MockRequest());
        try {
            limiter.apply(new MockRequest());
        } catch (OverCapacityException ex) {
        }
        assertEquals(1, limiter.getLimitHitCount());
    }

    @Test(timeout = 60000)
    public void testServiceRequestLimiterWithDefaultRate() throws Exception {
        MockHardRequestLimiter limiter = new MockHardRequestLimiter(-1);
        limiter.apply(new MockRequest(Integer.MAX_VALUE));
        limiter.apply(new MockRequest(Integer.MAX_VALUE));
        assertEquals(0, limiter.getLimitHitCount());
    }

    @Test(timeout = 60000)
    public void testServiceRequestLimiterWithZeroRate() throws Exception {
        MockHardRequestLimiter limiter = new MockHardRequestLimiter(0);
        try {
            limiter.apply(new MockRequest(1));
            fail("should have failed with overcap");
        } catch (OverCapacityException ex) {
        }
        assertEquals(1, limiter.getLimitHitCount());
    }

    @Test(timeout = 60000)
    public void testChainedServiceRequestLimiter() throws Exception {
        MockSoftRequestLimiter softLimiter = new MockSoftRequestLimiter(new CounterLimiter(1));
        MockHardRequestLimiter hardLimiter = new MockHardRequestLimiter(new CounterLimiter(3));

        RequestLimiter<MockRequest> limiter =
                new ChainedRequestLimiter.Builder<MockRequest>()
                .addLimiter(softLimiter)
                .addLimiter(hardLimiter)
                .build();

        assertEquals(0, softLimiter.getLimitHitCount());
        assertEquals(0, hardLimiter.getLimitHitCount());

        limiter.apply(new MockRequest());
        assertEquals(0, softLimiter.getLimitHitCount());
        assertEquals(0, hardLimiter.getLimitHitCount());

        limiter.apply(new MockRequest());
        assertEquals(1, softLimiter.getLimitHitCount());
        assertEquals(0, hardLimiter.getLimitHitCount());

        limiter.apply(new MockRequest());
        assertEquals(2, softLimiter.getLimitHitCount());
        assertEquals(0, hardLimiter.getLimitHitCount());

        try {
            limiter.apply(new MockRequest());
        } catch (OverCapacityException ex) {
        }
        assertEquals(3, softLimiter.getLimitHitCount());
        assertEquals(1, hardLimiter.getLimitHitCount());
    }
}
