View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  package org.apache.http.impl.client;
28  
29  import static org.junit.Assert.assertEquals;
30  import static org.junit.Assert.assertTrue;
31  
32  import java.util.Random;
33  
34  import org.apache.http.HttpHost;
35  import org.apache.http.client.BackoffManager;
36  import org.apache.http.conn.routing.HttpRoute;
37  import org.junit.Before;
38  import org.junit.Test;
39  
40  public class TestAIMDBackoffManager {
41  
42      private AIMDBackoffManager impl;
43      private MockConnPoolControl connPerRoute;
44      private HttpRoute route;
45      private MockClock clock;
46  
47      @Before
48      public void setUp() {
49          connPerRoute = new MockConnPoolControl();
50          route = new HttpRoute(new HttpHost("localhost", 80));
51          clock = new MockClock();
52          impl = new AIMDBackoffManager(connPerRoute, clock);
53          impl.setPerHostConnectionCap(10);
54      }
55  
56      @Test
57      public void isABackoffManager() {
58          assertTrue(impl instanceof BackoffManager);
59      }
60  
61      @Test
62      public void halvesConnectionsOnBackoff() {
63          connPerRoute.setMaxPerRoute(route, 4);
64          impl.backOff(route);
65          assertEquals(2, connPerRoute.getMaxPerRoute(route));
66      }
67  
68      @Test
69      public void doesNotBackoffBelowOneConnection() {
70          connPerRoute.setMaxPerRoute(route, 1);
71          impl.backOff(route);
72          assertEquals(1, connPerRoute.getMaxPerRoute(route));
73      }
74  
75      @Test
76      public void increasesByOneOnProbe() {
77          connPerRoute.setMaxPerRoute(route, 2);
78          impl.probe(route);
79          assertEquals(3, connPerRoute.getMaxPerRoute(route));
80      }
81  
82      @Test
83      public void doesNotIncreaseBeyondPerHostMaxOnProbe() {
84          connPerRoute.setDefaultMaxPerRoute(5);
85          connPerRoute.setMaxPerRoute(route, 5);
86          impl.setPerHostConnectionCap(5);
87          impl.probe(route);
88          assertEquals(5, connPerRoute.getMaxPerRoute(route));
89      }
90  
91      @Test
92      public void backoffDoesNotAdjustDuringCoolDownPeriod() {
93          connPerRoute.setMaxPerRoute(route, 4);
94          final long now = System.currentTimeMillis();
95          clock.setCurrentTime(now);
96          impl.backOff(route);
97          final long max = connPerRoute.getMaxPerRoute(route);
98          clock.setCurrentTime(now + 1);
99          impl.backOff(route);
100         assertEquals(max, connPerRoute.getMaxPerRoute(route));
101     }
102 
103     @Test
104     public void backoffStillAdjustsAfterCoolDownPeriod() {
105         connPerRoute.setMaxPerRoute(route, 8);
106         final long now = System.currentTimeMillis();
107         clock.setCurrentTime(now);
108         impl.backOff(route);
109         final long max = connPerRoute.getMaxPerRoute(route);
110         clock.setCurrentTime(now + 10 * 1000L);
111         impl.backOff(route);
112         assertTrue(max == 1 || max > connPerRoute.getMaxPerRoute(route));
113     }
114 
115     @Test
116     public void probeDoesNotAdjustDuringCooldownPeriod() {
117         connPerRoute.setMaxPerRoute(route, 4);
118         final long now = System.currentTimeMillis();
119         clock.setCurrentTime(now);
120         impl.probe(route);
121         final long max = connPerRoute.getMaxPerRoute(route);
122         clock.setCurrentTime(now + 1);
123         impl.probe(route);
124         assertEquals(max, connPerRoute.getMaxPerRoute(route));
125     }
126 
127     @Test
128     public void probeStillAdjustsAfterCoolDownPeriod() {
129         connPerRoute.setMaxPerRoute(route, 8);
130         final long now = System.currentTimeMillis();
131         clock.setCurrentTime(now);
132         impl.probe(route);
133         final long max = connPerRoute.getMaxPerRoute(route);
134         clock.setCurrentTime(now + 10 * 1000L);
135         impl.probe(route);
136         assertTrue(max < connPerRoute.getMaxPerRoute(route));
137     }
138 
139     @Test
140     public void willBackoffImmediatelyEvenAfterAProbe() {
141         connPerRoute.setMaxPerRoute(route, 8);
142         final long now = System.currentTimeMillis();
143         clock.setCurrentTime(now);
144         impl.probe(route);
145         final long max = connPerRoute.getMaxPerRoute(route);
146         clock.setCurrentTime(now + 1);
147         impl.backOff(route);
148         assertTrue(connPerRoute.getMaxPerRoute(route) < max);
149     }
150 
151     @Test
152     public void backOffFactorIsConfigurable() {
153         connPerRoute.setMaxPerRoute(route, 10);
154         impl.setBackoffFactor(0.9);
155         impl.backOff(route);
156         assertEquals(9, connPerRoute.getMaxPerRoute(route));
157     }
158 
159     @Test
160     public void coolDownPeriodIsConfigurable() {
161         long cd = new Random().nextLong() / 2;
162         if (cd < 0) {
163             cd *= -1;
164         }
165         if (cd < 1) {
166             cd++;
167         }
168         final long now = System.currentTimeMillis();
169         impl.setCooldownMillis(cd);
170         clock.setCurrentTime(now);
171         impl.probe(route);
172         final int max0 = connPerRoute.getMaxPerRoute(route);
173         clock.setCurrentTime(now);
174         impl.probe(route);
175         assertEquals(max0, connPerRoute.getMaxPerRoute(route));
176         clock.setCurrentTime(now + cd + 1);
177         impl.probe(route);
178         assertTrue(max0 < connPerRoute.getMaxPerRoute(route));
179     }
180 }