Skip to content

Commit ead5823

Browse files
committed
Additional tests
1 parent dad59ec commit ead5823

1 file changed

Lines changed: 143 additions & 28 deletions

File tree

src/test/java/io/split/android/client/network/SslProxyTunnelEstablisherTest.java

Lines changed: 143 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import static org.junit.Assert.assertEquals;
44
import static org.junit.Assert.assertNotNull;
5+
import static org.junit.Assert.assertThrows;
56
import static org.junit.Assert.assertTrue;
67
import static org.junit.Assert.fail;
78
import static org.mockito.Mockito.mock;
@@ -18,6 +19,7 @@
1819
import java.io.IOException;
1920
import java.io.InputStreamReader;
2021
import java.io.PrintWriter;
22+
import java.net.HttpRetryException;
2123
import java.net.Socket;
2224
import java.security.KeyStore;
2325
import java.util.concurrent.CountDownLatch;
@@ -39,11 +41,9 @@ public class SslProxyTunnelEstablisherTest {
3941

4042
private TestSslProxy testProxy;
4143
private SSLSocketFactory clientSslSocketFactory;
42-
private ProxyCredentialsProvider mProxyCredentialsProvider;
4344

4445
@Before
4546
public void setUp() throws Exception {
46-
mProxyCredentialsProvider = mock(ProxyCredentialsProvider.class);
4747
// Create test certificates
4848
HeldCertificate proxyCa = new HeldCertificate.Builder()
4949
.commonName("Test Proxy CA")
@@ -87,14 +87,15 @@ public void establishTunnelWithValidSslProxySucceeds() throws Exception {
8787
SslProxyTunnelEstablisher establisher = new SslProxyTunnelEstablisher();
8888
String targetHost = "example.com";
8989
int targetPort = 443;
90+
ProxyCredentialsProvider proxyCredentialsProvider = mock(ProxyCredentialsProvider.class);
9091

9192
Socket tunnelSocket = establisher.establishTunnel(
9293
"localhost",
9394
testProxy.getPort(),
9495
targetHost,
9596
targetPort,
9697
clientSslSocketFactory,
97-
mProxyCredentialsProvider);
98+
proxyCredentialsProvider);
9899

99100
assertNotNull("Tunnel socket should not be null", tunnelSocket);
100101
assertTrue("Tunnel socket should be connected", tunnelSocket.isConnected());
@@ -112,6 +113,7 @@ public void establishTunnelWithNotTrustedCertificatedThrows() throws Exception {
112113
SSLContext untrustedContext = SSLContext.getInstance("TLS");
113114
untrustedContext.init(null, null, null);
114115
SSLSocketFactory untrustedSocketFactory = untrustedContext.getSocketFactory();
116+
ProxyCredentialsProvider proxyCredentialsProvider = mock(ProxyCredentialsProvider.class);
115117

116118
SslProxyTunnelEstablisher establisher = new SslProxyTunnelEstablisher();
117119

@@ -122,7 +124,7 @@ public void establishTunnelWithNotTrustedCertificatedThrows() throws Exception {
122124
"example.com",
123125
443,
124126
untrustedSocketFactory,
125-
mProxyCredentialsProvider);
127+
proxyCredentialsProvider);
126128
fail("Should have thrown exception for untrusted certificate");
127129
} catch (IOException e) {
128130
assertTrue("Exception should be SSL-related", e.getMessage().contains("certification"));
@@ -132,6 +134,7 @@ public void establishTunnelWithNotTrustedCertificatedThrows() throws Exception {
132134
@Test
133135
public void establishTunnelWithFailingProxyConnectionThrows() {
134136
SslProxyTunnelEstablisher establisher = new SslProxyTunnelEstablisher();
137+
ProxyCredentialsProvider proxyCredentialsProvider = mock(ProxyCredentialsProvider.class);
135138

136139
try {
137140
establisher.establishTunnel(
@@ -140,7 +143,7 @@ public void establishTunnelWithFailingProxyConnectionThrows() {
140143
"example.com",
141144
443,
142145
clientSslSocketFactory,
143-
mProxyCredentialsProvider);
146+
proxyCredentialsProvider);
144147
fail("Should have thrown exception for connection failure");
145148
} catch (IOException e) {
146149
// The implementation wraps the original exception with a descriptive message
@@ -149,26 +152,130 @@ public void establishTunnelWithFailingProxyConnectionThrows() {
149152
}
150153

151154
@Test
152-
public void bearerTokenIsPassedWhenSet() {
155+
public void bearerTokenIsPassedWhenSet() throws IOException, InterruptedException {
153156
SslProxyTunnelEstablisher establisher = new SslProxyTunnelEstablisher();
154-
try {
155-
establisher.establishTunnel(
156-
"localhost",
157-
testProxy.getPort(),
158-
"example.com",
159-
443,
160-
clientSslSocketFactory,
161-
new ProxyCredentialsProvider() {
162-
@Override
163-
public String getBearerToken() {
164-
return "token";
165-
}
166-
});
167-
boolean await = testProxy.getAuthorizationHeaderReceived().await(5, TimeUnit.SECONDS);
168-
assertTrue("Proxy should have received authorization header", await);
169-
} catch (IOException | InterruptedException e) {
170-
throw new RuntimeException(e);
171-
}
157+
establisher.establishTunnel(
158+
"localhost",
159+
testProxy.getPort(),
160+
"example.com",
161+
443,
162+
clientSslSocketFactory,
163+
new ProxyCredentialsProvider() {
164+
@Override
165+
public String getBearerToken() {
166+
return "token";
167+
}
168+
});
169+
boolean await = testProxy.getAuthorizationHeaderReceived().await(5, TimeUnit.SECONDS);
170+
assertTrue("Proxy should have received authorization header", await);
171+
}
172+
173+
@Test
174+
public void establishTunnelWithNullCredentialsProviderDoesNotAddAuthHeader() throws Exception {
175+
SslProxyTunnelEstablisher establisher = new SslProxyTunnelEstablisher();
176+
177+
Socket tunnelSocket = establisher.establishTunnel(
178+
"localhost",
179+
testProxy.getPort(),
180+
"example.com",
181+
443,
182+
clientSslSocketFactory,
183+
null);
184+
185+
assertNotNull(tunnelSocket);
186+
assertTrue(testProxy.getConnectRequestReceived().await(5, TimeUnit.SECONDS));
187+
188+
assertEquals(1, testProxy.getAuthorizationHeaderReceived().getCount());
189+
190+
tunnelSocket.close();
191+
}
192+
193+
@Test
194+
public void establishTunnelWithNullBearerTokenDoesNotAddAuthHeader() throws Exception {
195+
SslProxyTunnelEstablisher establisher = new SslProxyTunnelEstablisher();
196+
197+
Socket tunnelSocket = establisher.establishTunnel(
198+
"localhost",
199+
testProxy.getPort(),
200+
"example.com",
201+
443,
202+
clientSslSocketFactory,
203+
() -> null);
204+
205+
assertNotNull(tunnelSocket);
206+
assertTrue(testProxy.getConnectRequestReceived().await(5, TimeUnit.SECONDS));
207+
208+
assertEquals(1, testProxy.getAuthorizationHeaderReceived().getCount());
209+
210+
tunnelSocket.close();
211+
}
212+
213+
@Test
214+
public void establishTunnelWithEmptyBearerTokenDoesNotAddAuthHeader() throws Exception {
215+
SslProxyTunnelEstablisher establisher = new SslProxyTunnelEstablisher();
216+
217+
Socket tunnelSocket = establisher.establishTunnel(
218+
"localhost",
219+
testProxy.getPort(),
220+
"example.com",
221+
443,
222+
clientSslSocketFactory,
223+
() -> " ");
224+
225+
assertNotNull(tunnelSocket);
226+
assertTrue(testProxy.getConnectRequestReceived().await(5, TimeUnit.SECONDS));
227+
228+
assertEquals(1, testProxy.getAuthorizationHeaderReceived().getCount());
229+
230+
tunnelSocket.close();
231+
}
232+
233+
@Test
234+
public void establishTunnelWithNullStatusLineThrowsIOException() {
235+
testProxy.setConnectResponse(null);
236+
SslProxyTunnelEstablisher establisher = new SslProxyTunnelEstablisher();
237+
238+
IOException exception = assertThrows(IOException.class, () -> establisher.establishTunnel(
239+
"localhost",
240+
testProxy.getPort(),
241+
"example.com",
242+
443,
243+
clientSslSocketFactory,
244+
null));
245+
246+
assertNotNull(exception);
247+
}
248+
249+
@Test
250+
public void establishTunnelWithMalformedStatusLineThrowsIOException() {
251+
testProxy.setConnectResponse("HTTP/1.1"); // Malformed, missing status code
252+
SslProxyTunnelEstablisher establisher = new SslProxyTunnelEstablisher();
253+
254+
IOException exception = assertThrows(IOException.class, () -> establisher.establishTunnel(
255+
"localhost",
256+
testProxy.getPort(),
257+
"example.com",
258+
443,
259+
clientSslSocketFactory,
260+
null));
261+
262+
assertNotNull(exception);
263+
}
264+
265+
@Test
266+
public void establishTunnelWithProxyAuthRequiredThrowsHttpRetryException() {
267+
testProxy.setConnectResponse("HTTP/1.1 407 Proxy Authentication Required");
268+
SslProxyTunnelEstablisher establisher = new SslProxyTunnelEstablisher();
269+
270+
HttpRetryException exception = assertThrows(HttpRetryException.class, () -> establisher.establishTunnel(
271+
"localhost",
272+
testProxy.getPort(),
273+
"example.com",
274+
443,
275+
clientSslSocketFactory,
276+
null));
277+
278+
assertEquals(407, exception.responseCode());
172279
}
173280

174281
/**
@@ -182,6 +289,7 @@ private static class TestSslProxy extends Thread {
182289
private final CountDownLatch mConnectRequestReceived = new CountDownLatch(1);
183290
private final CountDownLatch mAuthorizationHeaderReceived = new CountDownLatch(1);
184291
private final AtomicReference<String> mReceivedConnectLine = new AtomicReference<>();
292+
private final AtomicReference<String> mConnectResponse = new AtomicReference<>("HTTP/1.1 200 Connection established");
185293

186294
public TestSslProxy(int port, HeldCertificate serverCert) {
187295
mPort = port;
@@ -237,10 +345,13 @@ private void handleClient(Socket client) {
237345
}
238346
}
239347

240-
// Send successful CONNECT response
241-
writer.println("HTTP/1.1 200 Connection established");
242-
writer.println();
243-
writer.flush();
348+
// Send configured CONNECT response
349+
String response = mConnectResponse.get();
350+
if (response != null) {
351+
writer.println(response);
352+
writer.println();
353+
writer.flush();
354+
}
244355

245356
// Keep connection open for tunnel
246357
Thread.sleep(100);
@@ -271,5 +382,9 @@ public CountDownLatch getAuthorizationHeaderReceived() {
271382
public String getReceivedConnectLine() {
272383
return mReceivedConnectLine.get();
273384
}
385+
386+
public void setConnectResponse(String connectResponse) {
387+
mConnectResponse.set(connectResponse);
388+
}
274389
}
275390
}

0 commit comments

Comments
 (0)