• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017 The gRPC Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.grpc.netty;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import java.util.concurrent.TimeUnit;
22 import org.junit.Test;
23 import org.junit.runner.RunWith;
24 import org.junit.runners.JUnit4;
25 
26 /** Unit tests for {@link KeepAliveEnforcer}. */
27 @RunWith(JUnit4.class)
28 public class KeepAliveEnforcerTest {
29   private static final int LARGE_NUMBER = KeepAliveEnforcer.MAX_PING_STRIKES * 5;
30 
31   private FakeTicker ticker = new FakeTicker();
32 
33   @Test(expected = IllegalArgumentException.class)
negativeTime()34   public void negativeTime() {
35     new KeepAliveEnforcer(true, -1, TimeUnit.NANOSECONDS);
36   }
37 
38   @Test(expected = NullPointerException.class)
nullTimeUnit()39   public void nullTimeUnit() {
40     new KeepAliveEnforcer(true, 1, null);
41   }
42 
43   @Test
permitLimitless()44   public void permitLimitless() {
45     KeepAliveEnforcer enforcer = new KeepAliveEnforcer(true, 0, TimeUnit.NANOSECONDS, ticker);
46     for (int i = 0; i < LARGE_NUMBER; i++) {
47       assertThat(enforcer.pingAcceptable()).isTrue();
48     }
49     enforcer.onTransportActive();
50     for (int i = 0; i < LARGE_NUMBER; i++) {
51       assertThat(enforcer.pingAcceptable()).isTrue();
52     }
53     enforcer.onTransportIdle();
54     for (int i = 0; i < LARGE_NUMBER; i++) {
55       assertThat(enforcer.pingAcceptable()).isTrue();
56     }
57     enforcer.resetCounters();
58     for (int i = 0; i < LARGE_NUMBER; i++) {
59       assertThat(enforcer.pingAcceptable()).isTrue();
60     }
61   }
62 
63   @Test
strikeOutBecauseNoOutstandingCalls()64   public void strikeOutBecauseNoOutstandingCalls() {
65     KeepAliveEnforcer enforcer = new KeepAliveEnforcer(false, 0, TimeUnit.NANOSECONDS, ticker);
66     enforcer.onTransportIdle();
67     for (int i = 0; i < KeepAliveEnforcer.MAX_PING_STRIKES; i++) {
68       assertThat(enforcer.pingAcceptable()).isTrue();
69     }
70     assertThat(enforcer.pingAcceptable()).isFalse();
71   }
72 
73   @Test
startsIdle()74   public void startsIdle() {
75     KeepAliveEnforcer enforcer = new KeepAliveEnforcer(false, 0, TimeUnit.NANOSECONDS, ticker);
76     for (int i = 0; i < KeepAliveEnforcer.MAX_PING_STRIKES; i++) {
77       assertThat(enforcer.pingAcceptable()).isTrue();
78     }
79     assertThat(enforcer.pingAcceptable()).isFalse();
80   }
81 
82   @Test
strikeOutBecauseRateTooHighWhileActive()83   public void strikeOutBecauseRateTooHighWhileActive() {
84     KeepAliveEnforcer enforcer = new KeepAliveEnforcer(true, 1, TimeUnit.NANOSECONDS, ticker);
85     enforcer.onTransportActive();
86     for (int i = 0; i < KeepAliveEnforcer.MAX_PING_STRIKES; i++) {
87       assertThat(enforcer.pingAcceptable()).isTrue();
88     }
89     assertThat(enforcer.pingAcceptable()).isFalse();
90   }
91 
92   @Test
strikeOutBecauseRateTooHighWhileIdle()93   public void strikeOutBecauseRateTooHighWhileIdle() {
94     KeepAliveEnforcer enforcer = new KeepAliveEnforcer(true, 1, TimeUnit.NANOSECONDS, ticker);
95     enforcer.onTransportIdle();
96     for (int i = 0; i < KeepAliveEnforcer.MAX_PING_STRIKES; i++) {
97       assertThat(enforcer.pingAcceptable()).isTrue();
98     }
99     assertThat(enforcer.pingAcceptable()).isFalse();
100   }
101 
102   @Test
permitInRateWhileActive()103   public void permitInRateWhileActive() {
104     KeepAliveEnforcer enforcer = new KeepAliveEnforcer(false, 1, TimeUnit.NANOSECONDS, ticker);
105     enforcer.onTransportActive();
106     for (int i = 0; i < LARGE_NUMBER; i++) {
107       assertThat(enforcer.pingAcceptable()).isTrue();
108       ticker.nanoTime += 1;
109     }
110   }
111 
112   @Test
permitInRateWhileIdle()113   public void permitInRateWhileIdle() {
114     KeepAliveEnforcer enforcer = new KeepAliveEnforcer(true, 1, TimeUnit.NANOSECONDS, ticker);
115     enforcer.onTransportIdle();
116     for (int i = 0; i < LARGE_NUMBER; i++) {
117       assertThat(enforcer.pingAcceptable()).isTrue();
118       ticker.nanoTime += 1;
119     }
120   }
121 
122   @Test
implicitPermittedWhileIdle()123   public void implicitPermittedWhileIdle() {
124     KeepAliveEnforcer enforcer = new KeepAliveEnforcer(
125         false, KeepAliveEnforcer.IMPLICIT_PERMIT_TIME_NANOS * 10, TimeUnit.NANOSECONDS, ticker);
126     enforcer.onTransportIdle();
127     for (int i = 0; i < LARGE_NUMBER; i++) {
128       assertThat(enforcer.pingAcceptable()).isTrue();
129       ticker.nanoTime += KeepAliveEnforcer.IMPLICIT_PERMIT_TIME_NANOS;
130     }
131   }
132 
133   @Test
implicitOverridesWhileActive()134   public void implicitOverridesWhileActive() {
135     KeepAliveEnforcer enforcer = new KeepAliveEnforcer(
136         false, KeepAliveEnforcer.IMPLICIT_PERMIT_TIME_NANOS * 10, TimeUnit.NANOSECONDS, ticker);
137     enforcer.onTransportActive();
138     for (int i = 0; i < LARGE_NUMBER; i++) {
139       assertThat(enforcer.pingAcceptable()).isTrue();
140       ticker.nanoTime += KeepAliveEnforcer.IMPLICIT_PERMIT_TIME_NANOS;
141     }
142   }
143 
144   @Test
implicitOverridesWhileIdle()145   public void implicitOverridesWhileIdle() {
146     KeepAliveEnforcer enforcer = new KeepAliveEnforcer(
147         true, KeepAliveEnforcer.IMPLICIT_PERMIT_TIME_NANOS * 10, TimeUnit.NANOSECONDS, ticker);
148     enforcer.onTransportIdle();
149     for (int i = 0; i < LARGE_NUMBER; i++) {
150       assertThat(enforcer.pingAcceptable()).isTrue();
151       ticker.nanoTime += KeepAliveEnforcer.IMPLICIT_PERMIT_TIME_NANOS;
152     }
153   }
154 
155   @Test
permitsWhenTimeOverflows()156   public void permitsWhenTimeOverflows() {
157     ticker.nanoTime = Long.MAX_VALUE;
158     KeepAliveEnforcer enforcer = new KeepAliveEnforcer(false, 1, TimeUnit.NANOSECONDS, ticker);
159     enforcer.onTransportActive();
160     for (int i = 0; i < KeepAliveEnforcer.MAX_PING_STRIKES; i++) {
161       assertThat(enforcer.pingAcceptable()).isTrue();
162     }
163     // Should have the maximum number of strikes now
164     ticker.nanoTime++;
165     assertThat(enforcer.pingAcceptable()).isTrue();
166   }
167 
168   @Test
resetCounters_resetsStrikes()169   public void resetCounters_resetsStrikes() {
170     KeepAliveEnforcer enforcer = new KeepAliveEnforcer(false, 1, TimeUnit.NANOSECONDS, ticker);
171     enforcer.onTransportActive();
172     for (int i = 0; i < KeepAliveEnforcer.MAX_PING_STRIKES; i++) {
173       assertThat(enforcer.pingAcceptable()).isTrue();
174     }
175     // Should have the maximum number of strikes now
176     enforcer.resetCounters();
177     for (int i = 0; i < KeepAliveEnforcer.MAX_PING_STRIKES; i++) {
178       assertThat(enforcer.pingAcceptable()).isTrue();
179     }
180     assertThat(enforcer.pingAcceptable()).isFalse();
181   }
182 
183   @Test
resetCounters_resetsPingTime()184   public void resetCounters_resetsPingTime() {
185     KeepAliveEnforcer enforcer = new KeepAliveEnforcer(false, 1, TimeUnit.NANOSECONDS, ticker);
186     enforcer.onTransportActive();
187     ticker.nanoTime += 1;
188     assertThat(enforcer.pingAcceptable()).isTrue();
189     enforcer.resetCounters();
190     // Should not cause a strike
191     assertThat(enforcer.pingAcceptable()).isTrue();
192     for (int i = 0; i < KeepAliveEnforcer.MAX_PING_STRIKES; i++) {
193       assertThat(enforcer.pingAcceptable()).isTrue();
194     }
195   }
196 
197   @Test
systemTickerIsSystemNanoTime()198   public void systemTickerIsSystemNanoTime() {
199     long before = System.nanoTime();
200     long returned = KeepAliveEnforcer.SystemTicker.INSTANCE.nanoTime();
201     long after = System.nanoTime();
202     assertThat(returned).isAtLeast(before);
203     assertThat(returned).isAtMost(after);
204   }
205 
206   private static class FakeTicker implements KeepAliveEnforcer.Ticker {
207     long nanoTime;
208 
209     @Override
nanoTime()210     public long nanoTime() {
211       return nanoTime;
212     }
213   }
214 }
215