1   /*
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2026, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v2.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  
15  package ch.qos.logback.core.util;
16  
17  import static ch.qos.logback.core.util.DefaultInvocationGate.DEFAULT_MASK;
18  import static ch.qos.logback.core.util.DefaultInvocationGate.MASK_DECREASE_RIGHT_SHIFT_COUNT;
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertFalse;
21  import static org.junit.jupiter.api.Assertions.assertTrue;
22  
23  import org.junit.jupiter.api.Test;
24  
25  public class DefaultInvocationGateTest {
26  
27      @Test
28      public void smoke() {
29          long currentTime = 0;
30          long minDelayThreshold = 4;
31          long maxDelayThreshold = 8;
32  
33          DefaultInvocationGate gate = new DefaultInvocationGate(minDelayThreshold, maxDelayThreshold, currentTime);
34          assertTrue(gate.isTooSoon(0));
35      }
36  
37      @Test
38      public void closelyRepeatedCallsShouldCauseMaskToIncrease() {
39          long currentTime = 0;
40          long minDelayThreshold = 4;
41          long maxDelayThreshold = 8;
42  
43          DefaultInvocationGate gate = new DefaultInvocationGate(minDelayThreshold, maxDelayThreshold, currentTime);
44          for (int i = 0; i < DEFAULT_MASK; i++) {
45              assertTrue(gate.isTooSoon(0));
46          }
47          assertFalse(gate.isTooSoon(0));
48          assertTrue(gate.getMask() > DEFAULT_MASK);
49      }
50  
51      @Test
52      public void stableAtSteadyRate() {
53          long currentTime = 0;
54          long minDelayThreshold = DEFAULT_MASK;
55          long maxDelayThreshold = DEFAULT_MASK * 2;
56  
57          DefaultInvocationGate gate = new DefaultInvocationGate(minDelayThreshold, maxDelayThreshold, currentTime);
58  
59          for (int t = 0; t < 4 * minDelayThreshold; t++) {
60              gate.isTooSoon(currentTime++);
61              assertEquals(DEFAULT_MASK, gate.getMask());
62          }
63      }
64  
65      @Test
66      public void intermittentCallsShouldCauseMaskToDecrease() {
67          long currentTime = 0;
68          long minDelayThreshold = 4;
69          long maxDelayThreshold = 8;
70  
71          DefaultInvocationGate gate = new DefaultInvocationGate(minDelayThreshold, maxDelayThreshold, currentTime);
72          int currentMask = DEFAULT_MASK;
73  
74          currentTime += maxDelayThreshold + 1;
75          assertFalse(gate.isTooSoon(currentTime));
76          assertTrue(gate.getMask() < currentMask);
77      }
78  
79      @Test
80      public void maskCanDropToZeroForInfrequentInvocations() {
81          long currentTime = 0;
82          long minDelayThreshold = 4;
83          long maxDelayThreshold = 8;
84  
85          DefaultInvocationGate gate = new DefaultInvocationGate(minDelayThreshold, maxDelayThreshold, currentTime);
86          int currentMask = DEFAULT_MASK;
87  
88          do {
89              currentTime += maxDelayThreshold + 1;
90              assertFalse(gate.isTooSoon(currentTime));
91              assertTrue(gate.getMask() < currentMask);
92              currentMask = currentMask >> MASK_DECREASE_RIGHT_SHIFT_COUNT;
93          } while (currentMask > 0);
94  
95          assertEquals(0, gate.getMask());
96          assertFalse(gate.isTooSoon(currentTime));
97      }
98  }