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 org.apache.hc.client5.http.impl.routing.DistributedProxySelector;
31 import org.junit.jupiter.api.Test;
32
33 import java.io.IOException;
34 import java.net.InetSocketAddress;
35 import java.net.Proxy;
36 import java.net.ProxySelector;
37 import java.net.SocketAddress;
38 import java.net.URI;
39 import java.util.Arrays;
40 import java.util.Collections;
41 import java.util.List;
42
43 import static org.junit.jupiter.api.Assertions.assertEquals;
44 import static org.junit.jupiter.api.Assertions.assertThrows;
45 import static org.mockito.ArgumentMatchers.any;
46 import static org.mockito.Mockito.mock;
47 import static org.mockito.Mockito.never;
48 import static org.mockito.Mockito.verify;
49 import static org.mockito.Mockito.when;
50
51 class DistributedProxySelectorTest {
52
53 @Test
54 void testConstructorThrowsExceptionWhenNullSelectors() {
55 assertThrows(IllegalArgumentException.class, () -> new DistributedProxySelector(null));
56 }
57
58 @Test
59 void testConstructorThrowsExceptionWhenEmptySelectors() {
60 assertThrows(IllegalArgumentException.class, () -> new DistributedProxySelector(Collections.emptyList()));
61 }
62
63 @Test
64 void testSelectReturnsProxyFromFirstSelector() {
65 final ProxySelector selector1 = new ProxySelector() {
66 @Override
67 public List<Proxy> select(final URI uri) {
68 return Arrays.asList(
69 new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy1.example.com", 8080)),
70 new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy2.example.com", 8080))
71 );
72 }
73
74 @Override
75 public void connectFailed(final URI uri, final SocketAddress sa, final IOException ioe) {
76 }
77 };
78
79 final ProxySelector selector2 = new ProxySelector() {
80 @Override
81 public List<Proxy> select(final URI uri) {
82 return Collections.singletonList(
83 new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy3.example.com", 8080))
84 );
85 }
86
87 @Override
88 public void connectFailed(final URI uri, final SocketAddress sa, final IOException ioe) {
89 }
90 };
91
92 final DistributedProxySelector failoverSelector = new DistributedProxySelector(Arrays.asList(selector1, selector2));
93
94 final URI uri = URI.create("http://example.com");
95 final List<Proxy> proxies = failoverSelector.select(uri);
96 assertEquals(2, proxies.size());
97 assertEquals("proxy1.example.com", ((InetSocketAddress) proxies.get(0).address()).getHostName());
98 assertEquals("proxy2.example.com", ((InetSocketAddress) proxies.get(1).address()).getHostName());
99 }
100
101 @Test
102 void testSelectReturnsProxyFromSecondSelector() {
103 final ProxySelector selector1 = new ProxySelector() {
104 @Override
105 public List<Proxy> select(final URI uri) {
106 return Collections.emptyList();
107 }
108
109 @Override
110 public void connectFailed(final URI uri, final SocketAddress sa, final IOException ioe) {
111 }
112 };
113
114 final ProxySelector selector2 = new ProxySelector() {
115 @Override
116 public List<Proxy> select(final URI uri) {
117 return Collections.singletonList(
118 new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy3.example.com", 8080))
119 );
120 }
121
122 @Override
123 public void connectFailed(final URI uri, final SocketAddress sa, final IOException ioe) {
124 }
125 };
126
127 final DistributedProxySelector failoverSelector = new DistributedProxySelector(Arrays.asList(selector1, selector2));
128
129 final URI uri = URI.create("http://example.com");
130 final List<Proxy> proxies = failoverSelector.select(uri);
131 assertEquals(1, proxies.size());
132 assertEquals("proxy3.example.com", ((InetSocketAddress) proxies.get(0).address()).getHostName());
133 }
134
135 @Test
136 void testSelectReturnsProxyFromThirdSelector() {
137 final ProxySelector selector1 = new ProxySelector() {
138 @Override
139 public List<Proxy> select(final URI uri) {
140 return Collections.emptyList();
141 }
142
143 @Override
144 public void connectFailed(final URI uri, final SocketAddress sa, final IOException ioe) {
145 }
146 };
147
148 final ProxySelector selector2 = mock(ProxySelector.class);
149
150 when(selector2.select(any(URI.class))).thenReturn(Collections.singletonList(
151 new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy3.example.com", 8080))
152 ));
153
154 final DistributedProxySelector proxySelector = new DistributedProxySelector(Arrays.asList(selector1, selector2));
155
156 final URI uri = URI.create("http://example.com");
157 final List<Proxy> proxies = proxySelector.select(uri);
158
159
160 assertEquals(1, proxies.size(), "Expecting one proxy to be returned");
161 assertEquals("proxy3.example.com", ((InetSocketAddress) proxies.get(0).address()).getHostName(), "Expecting proxy3.example.com to be returned");
162
163
164 final SocketAddress sa = new InetSocketAddress("proxy3.example.com", 8080);
165 final IOException ioe = new IOException("Connection refused");
166 proxySelector.connectFailed(uri, sa, ioe);
167 verify(selector2, never()).connectFailed(uri, sa, ioe);
168 }
169
170 @Test
171 void testSelectReturnsProxyFromSecondSelectorWhenFirstSelectorReturnsEmptyList() {
172 final ProxySelector selector1 = new ProxySelector() {
173 @Override
174 public List<Proxy> select(final URI uri) {
175 return Collections.emptyList();
176 }
177
178 @Override
179 public void connectFailed(final URI uri, final SocketAddress sa, final IOException ioe) {
180 }
181 };
182
183 final ProxySelector selector2 = new ProxySelector() {
184 @Override
185 public List<Proxy> select(final URI uri) {
186 return Collections.singletonList(
187 new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy3.example.com", 8080))
188 );
189 }
190
191 @Override
192 public void connectFailed(final URI uri, final SocketAddress sa, final IOException ioe) {
193 }
194 };
195
196 final DistributedProxySelector failoverSelector = new DistributedProxySelector(Arrays.asList(selector1, selector2));
197
198 final URI uri = URI.create("http://example.com");
199 final List<Proxy> proxies = failoverSelector.select(uri);
200 assertEquals(1, proxies.size());
201 assertEquals("proxy3.example.com", ((InetSocketAddress) proxies.get(0).address()).getHostName());
202 }
203
204 @Test
205 void testSelectHandlesException() {
206 final ProxySelector exceptionThrowingSelector = new ProxySelector() {
207 @Override
208 public List<Proxy> select(final URI uri) {
209 throw new RuntimeException("Exception for testing");
210 }
211
212 @Override
213 public void connectFailed(final URI uri, final SocketAddress sa, final IOException ioe) {
214 }
215 };
216
217 final ProxySelector workingSelector = new ProxySelector() {
218 @Override
219 public List<Proxy> select(final URI uri) {
220 return Collections.singletonList(
221 new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy.example.com", 8080))
222 );
223 }
224
225 @Override
226 public void connectFailed(final URI uri, final SocketAddress sa, final IOException ioe) {
227 }
228 };
229
230 final DistributedProxySelector distributedSelector = new DistributedProxySelector(Arrays.asList(exceptionThrowingSelector, workingSelector));
231
232 final URI uri = URI.create("http://example.com");
233 final List<Proxy> proxies = distributedSelector.select(uri);
234 assertEquals(1, proxies.size());
235 assertEquals("proxy.example.com", ((InetSocketAddress) proxies.get(0).address()).getHostName());
236 }
237 }