1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.apache.hc.client5.http.impl.classic;
28
29
30 import static org.junit.jupiter.api.Assertions.assertEquals;
31 import static org.junit.jupiter.api.Assertions.assertTrue;
32
33 import java.time.Instant;
34 import java.util.Map;
35
36 import org.apache.hc.client5.http.HttpRoute;
37 import org.apache.hc.core5.http.HttpHost;
38 import org.apache.hc.core5.util.TimeValue;
39 import org.junit.jupiter.api.BeforeEach;
40 import org.junit.jupiter.api.Test;
41
42 class TestLinearBackoffManager {
43
44 private LinearBackoffManager impl;
45 private MockConnPoolControl connPerRoute;
46 private HttpRoute route;
47 private static final long DEFAULT_COOL_DOWN_MS = 10;
48
49 @BeforeEach
50 void setUp() {
51 connPerRoute = new MockConnPoolControl();
52 route = new HttpRoute(new HttpHost("localhost", 80));
53 impl = new LinearBackoffManager(connPerRoute);
54 impl.setCoolDown(TimeValue.ofMilliseconds(DEFAULT_COOL_DOWN_MS));
55 }
56
57 @Test
58 void incrementsConnectionsOnBackoff() {
59 final LinearBackoffManager impl = new LinearBackoffManager(connPerRoute);
60 impl.setCoolDown(TimeValue.ofMilliseconds(DEFAULT_COOL_DOWN_MS));
61 connPerRoute.setMaxPerRoute(route, 4);
62 impl.backOff(route);
63 assertEquals(5, connPerRoute.getMaxPerRoute(route));
64 }
65
66 @Test
67 void decrementsConnectionsOnProbe() {
68 connPerRoute.setMaxPerRoute(route, 4);
69 impl.probe(route);
70 assertEquals(3, connPerRoute.getMaxPerRoute(route));
71 }
72
73 @Test
74 void backoffDoesNotAdjustDuringCoolDownPeriod() {
75
76 connPerRoute.setMaxPerRoute(route, 4);
77 impl.backOff(route);
78 final long max = connPerRoute.getMaxPerRoute(route);
79
80
81 final Map<HttpRoute, Instant> lastRouteBackoffs = impl.getLastRouteBackoffs();
82 lastRouteBackoffs.put(route, Instant.now().minusMillis(DEFAULT_COOL_DOWN_MS - 1));
83
84
85 impl.backOff(route);
86
87
88 assertEquals(max, connPerRoute.getMaxPerRoute(route));
89 }
90 @Test
91 void backoffStillAdjustsAfterCoolDownPeriod() {
92
93 final LinearBackoffManager impl = new LinearBackoffManager(connPerRoute);
94 impl.setCoolDown(TimeValue.ofMilliseconds(DEFAULT_COOL_DOWN_MS));
95 connPerRoute.setMaxPerRoute(route, 4);
96 impl.backOff(route);
97 final int max1 = connPerRoute.getMaxPerRoute(route);
98
99
100 final Map<HttpRoute, Instant> lastRouteBackoffs = impl.getLastRouteBackoffs();
101 lastRouteBackoffs.put(route, Instant.now().minusMillis(DEFAULT_COOL_DOWN_MS + 1));
102
103
104 impl.backOff(route);
105 final int max2 = connPerRoute.getMaxPerRoute(route);
106
107
108 assertTrue(max2 > max1);
109 }
110
111 @Test
112 void probeDoesNotAdjustDuringCooldownPeriod() {
113
114 connPerRoute.setMaxPerRoute(route, 4);
115 impl.probe(route);
116 final long max = connPerRoute.getMaxPerRoute(route);
117
118
119 final Map<HttpRoute, Instant> lastRouteProbes = impl.getLastRouteProbes();
120 lastRouteProbes.put(route, Instant.now());
121
122
123 impl.probe(route);
124
125
126 assertEquals(max, connPerRoute.getMaxPerRoute(route));
127 }
128
129 @Test
130 void probeStillAdjustsAfterCoolDownPeriod() {
131
132 connPerRoute.setMaxPerRoute(route, 4);
133 impl.probe(route);
134
135
136 final Map<HttpRoute, Instant> lastRouteProbes = impl.getLastRouteProbes();
137 lastRouteProbes.put(route, Instant.now().minusMillis(DEFAULT_COOL_DOWN_MS + 1));
138
139
140 impl.probe(route);
141 final long newMax = connPerRoute.getMaxPerRoute(route);
142
143
144 assertEquals(2, newMax);
145 }
146
147
148 @Test
149 void testSetPerHostConnectionCap() {
150 connPerRoute.setMaxPerRoute(route, 5);
151 impl.setPerHostConnectionCap(10);
152 impl.backOff(route);
153 assertEquals(6, connPerRoute.getMaxPerRoute(route));
154 }
155
156
157 public void probeUpdatesRemainingAttemptsIndirectly() {
158
159 connPerRoute.setMaxPerRoute(route, 4);
160
161
162 impl.backOff(route);
163
164
165 final Map<HttpRoute, Instant> lastRouteBackoffs = impl.getLastRouteBackoffs();
166 lastRouteBackoffs.put(route, Instant.now().minusMillis(DEFAULT_COOL_DOWN_MS + 1));
167
168 impl.backOff(route);
169
170
171 assertEquals(6, connPerRoute.getMaxPerRoute(route));
172
173
174 impl.probe(route);
175
176
177 final Map<HttpRoute, Instant> lastRouteProbes = impl.getLastRouteProbes();
178 lastRouteProbes.put(route, Instant.now().minusMillis(DEFAULT_COOL_DOWN_MS * 2));
179
180
181 impl.probe(route);
182
183
184 assertEquals(5, connPerRoute.getMaxPerRoute(route));
185 }
186
187 @Test
188 void linearIncrementTest() {
189 final int initialMax = 4;
190 connPerRoute.setMaxPerRoute(route, initialMax);
191
192
193 final Map<HttpRoute, Instant> lastRouteBackoffs = impl.getLastRouteBackoffs();
194
195 for (int i = 1; i <= 5; i++) {
196
197 lastRouteBackoffs.put(route, Instant.now().minusMillis(DEFAULT_COOL_DOWN_MS + 1));
198
199
200 impl.backOff(route);
201
202
203 assertEquals(initialMax + i, connPerRoute.getMaxPerRoute(route));
204 }
205 }
206
207 }