DefaultInvocationGateTest.java

/*
 * Logback: the reliable, generic, fast and flexible logging framework.
 * Copyright (C) 1999-2026, QOS.ch. All rights reserved.
 *
 * This program and the accompanying materials are dual-licensed under
 * either the terms of the Eclipse Public License v2.0 as published by
 * the Eclipse Foundation
 *
 *   or (per the licensee's choosing)
 *
 * under the terms of the GNU Lesser General Public License version 2.1
 * as published by the Free Software Foundation.
 */

package ch.qos.logback.core.util;

import static ch.qos.logback.core.util.DefaultInvocationGate.DEFAULT_MASK;
import static ch.qos.logback.core.util.DefaultInvocationGate.MASK_DECREASE_RIGHT_SHIFT_COUNT;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;

public class DefaultInvocationGateTest {

    @Test
    public void smoke() {
        long currentTime = 0;
        long minDelayThreshold = 4;
        long maxDelayThreshold = 8;

        DefaultInvocationGate gate = new DefaultInvocationGate(minDelayThreshold, maxDelayThreshold, currentTime);
        assertTrue(gate.isTooSoon(0));
    }

    @Test
    public void closelyRepeatedCallsShouldCauseMaskToIncrease() {
        long currentTime = 0;
        long minDelayThreshold = 4;
        long maxDelayThreshold = 8;

        DefaultInvocationGate gate = new DefaultInvocationGate(minDelayThreshold, maxDelayThreshold, currentTime);
        for (int i = 0; i < DEFAULT_MASK; i++) {
            assertTrue(gate.isTooSoon(0));
        }
        assertFalse(gate.isTooSoon(0));
        assertTrue(gate.getMask() > DEFAULT_MASK);
    }

    @Test
    public void stableAtSteadyRate() {
        long currentTime = 0;
        long minDelayThreshold = DEFAULT_MASK;
        long maxDelayThreshold = DEFAULT_MASK * 2;

        DefaultInvocationGate gate = new DefaultInvocationGate(minDelayThreshold, maxDelayThreshold, currentTime);

        for (int t = 0; t < 4 * minDelayThreshold; t++) {
            gate.isTooSoon(currentTime++);
            assertEquals(DEFAULT_MASK, gate.getMask());
        }
    }

    @Test
    public void intermittentCallsShouldCauseMaskToDecrease() {
        long currentTime = 0;
        long minDelayThreshold = 4;
        long maxDelayThreshold = 8;

        DefaultInvocationGate gate = new DefaultInvocationGate(minDelayThreshold, maxDelayThreshold, currentTime);
        int currentMask = DEFAULT_MASK;

        currentTime += maxDelayThreshold + 1;
        assertFalse(gate.isTooSoon(currentTime));
        assertTrue(gate.getMask() < currentMask);
    }

    @Test
    public void maskCanDropToZeroForInfrequentInvocations() {
        long currentTime = 0;
        long minDelayThreshold = 4;
        long maxDelayThreshold = 8;

        DefaultInvocationGate gate = new DefaultInvocationGate(minDelayThreshold, maxDelayThreshold, currentTime);
        int currentMask = DEFAULT_MASK;

        do {
            currentTime += maxDelayThreshold + 1;
            assertFalse(gate.isTooSoon(currentTime));
            assertTrue(gate.getMask() < currentMask);
            currentMask = currentMask >> MASK_DECREASE_RIGHT_SHIFT_COUNT;
        } while (currentMask > 0);

        assertEquals(0, gate.getMask());
        assertFalse(gate.isTooSoon(currentTime));
    }
}