Skip to content

Commit 558e26e

Browse files
committed
Replace MockHttpServer by Wiremock
1 parent cc3ba34 commit 558e26e

5 files changed

Lines changed: 108 additions & 138 deletions

File tree

lib/pom.xml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,17 +66,18 @@
6666
<artifactId>assertj-core</artifactId>
6767
<scope>test</scope>
6868
</dependency>
69-
<dependency>
70-
<groupId>com.squareup.okhttp3</groupId>
71-
<artifactId>mockwebserver</artifactId>
72-
<scope>test</scope>
73-
</dependency>
7469
<dependency>
7570
<!-- used to compare results -->
7671
<groupId>commons-codec</groupId>
7772
<artifactId>commons-codec</artifactId>
7873
<scope>test</scope>
7974
</dependency>
75+
<dependency>
76+
<groupId>org.wiremock</groupId>
77+
<artifactId>wiremock-standalone</artifactId>
78+
<version>3.5.4</version>
79+
<scope>test</scope>
80+
</dependency>
8081
</dependencies>
8182

8283
<build>

lib/src/test/java/org/sonarsource/scanner/lib/internal/IsolatedClassloaderTest.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,17 @@ public void add_jars() throws MalformedURLException {
7777
}
7878

7979
@Test
80-
public void error_add_jars() throws MalformedURLException {
80+
public void error_add_jars() {
81+
// Used to produce a MalformedURLException (see https://stackoverflow.com/a/42218175/534773)
82+
URL.setURLStreamHandlerFactory(protocol -> {
83+
if (protocol.equals("broken")) {
84+
throw new UnsupportedOperationException();
85+
}
86+
return null;
87+
});
88+
8189
File f = mock(File.class);
82-
URI uri = mock(URI.class);
83-
when(f.toURI()).thenReturn(uri);
84-
when(uri.toURL()).thenThrow(MalformedURLException.class);
90+
when(f.toURI()).thenReturn(URI.create("broken://dummy"));
8591
File[] files = {f};
8692

8793
thrown.expect(IllegalStateException.class);

lib/src/test/java/org/sonarsource/scanner/lib/internal/OkHttpClientFactoryTest.java

Lines changed: 63 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -19,38 +19,35 @@
1919
*/
2020
package org.sonarsource.scanner.lib.internal;
2121

22-
import java.io.FileInputStream;
22+
import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
2323
import java.io.IOException;
2424
import java.net.URISyntaxException;
25+
import java.net.URL;
2526
import java.nio.file.Path;
2627
import java.nio.file.Paths;
27-
import java.security.KeyStore;
28-
import java.security.SecureRandom;
29-
import javax.net.ssl.KeyManagerFactory;
30-
import javax.net.ssl.SSLContext;
3128
import javax.net.ssl.SSLHandshakeException;
32-
import javax.net.ssl.TrustManagerFactory;
3329
import okhttp3.OkHttpClient;
3430
import okhttp3.Request;
3531
import okhttp3.Response;
36-
import okhttp3.mockwebserver.Dispatcher;
37-
import okhttp3.mockwebserver.MockResponse;
38-
import okhttp3.mockwebserver.MockWebServer;
39-
import okhttp3.mockwebserver.RecordedRequest;
40-
import org.junit.After;
41-
import org.junit.Rule;
42-
import org.junit.Test;
43-
import org.junit.experimental.theories.Theory;
44-
import org.junit.rules.ExpectedException;
32+
import org.junit.jupiter.api.AfterEach;
33+
import org.junit.jupiter.api.BeforeEach;
34+
import org.junit.jupiter.api.Test;
35+
import org.junit.jupiter.api.extension.RegisterExtension;
4536
import org.sonarsource.scanner.lib.internal.cache.Logger;
4637

47-
import static java.lang.String.format;
38+
import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl;
39+
import static com.github.tomakehurst.wiremock.client.WireMock.get;
40+
import static com.github.tomakehurst.wiremock.client.WireMock.matching;
41+
import static com.github.tomakehurst.wiremock.client.WireMock.ok;
42+
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
43+
import static java.util.Objects.requireNonNull;
4844
import static org.assertj.core.api.Assertions.assertThat;
4945
import static org.assertj.core.api.Assertions.assertThatThrownBy;
46+
import static org.junit.Assert.assertThrows;
5047
import static org.junit.Assert.fail;
5148
import static org.mockito.Mockito.mock;
5249

53-
public class OkHttpClientFactoryTest {
50+
class OkHttpClientFactoryTest {
5451

5552
private static final String KEYSTORE_CLIENT_WITH_CA = "/client-with-ca.p12";
5653
private static final String CLIENT_WITH_CA_KEYSTORE_PASSWORD = "pwdClientCAP12";
@@ -64,56 +61,76 @@ public class OkHttpClientFactoryTest {
6461
private static final String SONAR_WS_TIMEOUT = "sonar.ws.timeout";
6562
private static final String COOKIE = "BIGipServerpool_sonarqube.example.com_8443=123456789.12345.0000";
6663

67-
@Rule
68-
public ExpectedException expectedException = ExpectedException.none();
64+
@RegisterExtension
65+
static WireMockExtension sonarqubeMock = WireMockExtension.newInstance()
66+
.options(wireMockConfig().dynamicHttpsPort().httpDisabled(true).globalTemplating(true)
67+
.keystoreType("pkcs12")
68+
.keystorePath(toPath(requireNonNull(OkHttpClientFactoryTest.class.getResource(SERVER_KEYSTORE_FILE))).toString())
69+
.keystorePassword(SERVER_KEYSTORE_PASSWORD)
70+
.keyManagerPassword(SERVER_KEYSTORE_PASSWORD))
71+
.build();
72+
73+
@BeforeEach
74+
void mockServerResponses() {
75+
sonarqubeMock.stubFor(get(anyUrl()).withHeader("Cookie", matching(".*")).atPriority(1)
76+
.willReturn(ok("OK\n{{request.headers.Cookie}}")));
77+
sonarqubeMock.stubFor(get(anyUrl()).atPriority(2)
78+
.willReturn(ok("OK").withHeader("Set-Cookie", COOKIE)));
79+
}
6980

70-
@After
81+
@AfterEach
7182
public void cleanSystemProperty() {
7283
System.clearProperty(SONAR_WS_TIMEOUT);
7384
}
7485

7586
@Test
76-
public void support_custom_timeouts() {
87+
void support_custom_timeouts() {
7788
int readTimeoutSec = 2000;
7889
System.setProperty(SONAR_WS_TIMEOUT, String.valueOf(readTimeoutSec));
7990

80-
Logger logger = mock(Logger.class);
8191
OkHttpClient underTest = OkHttpClientFactory.create(logger);
8292

8393
assertThat(underTest.readTimeoutMillis()).isEqualTo(readTimeoutSec * 1000);
8494
}
8595

8696
@Test
87-
public void support_custom_timeouts_throws_exception_on_non_number() {
97+
void support_custom_timeouts_throws_exception_on_non_number() {
8898
System.setProperty(SONAR_WS_TIMEOUT, "fail");
8999

90-
Logger logger = mock(Logger.class);
91100
assertThatThrownBy(() -> OkHttpClientFactory.create(logger)).isInstanceOf(NumberFormatException.class);
92101
}
93102

94103
@Test
95-
public void test_with_external_http_server() throws IOException {
104+
void test_with_external_http_server() throws IOException {
96105
Response response = call("http://www.google.com");
97106
assertThat(response.code()).isEqualTo(200);
98107
assertThat(response.body().string()).contains("doctype html");
99108
}
100109

101110
@Test
102-
public void test_with_external_https_server_with_correct_certificate() throws IOException {
111+
void test_with_external_https_server_with_correct_certificate() throws IOException {
103112
Response response = call("https://www.google.com");
104113
assertThat(response.code()).isEqualTo(200);
105114
assertThat(response.body().string()).contains("doctype html");
106115
}
107116

108-
@Theory
109-
public void when_overriding_truststore_known_websites_are_failing(String clientKeyStore) throws IOException, URISyntaxException {
117+
@Test
118+
void when_overriding_truststore_using_ca_known_websites_are_failing() throws IOException, URISyntaxException {
119+
when_overriding_truststore_known_websites_are_failing(KEYSTORE_CLIENT_WITH_CA, CLIENT_WITH_CA_KEYSTORE_PASSWORD);
120+
}
121+
122+
@Test
123+
void when_overriding_truststore_using_server_certificate_known_websites_are_failing() throws IOException, URISyntaxException {
124+
when_overriding_truststore_known_websites_are_failing(KEYSTORE_CLIENT_WITH_CERTIFICATE, CLIENT_WITH_CERTIFICATE_KEYSTORE_PASSWORD);
125+
}
126+
127+
public void when_overriding_truststore_known_websites_are_failing(String clientKeyStore, String keyStorePassword) throws URISyntaxException {
110128
try {
111129
Path clientTruststore = Paths.get(getClass().getResource(clientKeyStore).toURI()).toAbsolutePath();
112130
System.setProperty("javax.net.ssl.trustStore", clientTruststore.toString());
113-
System.setProperty("javax.net.ssl.trustStorePassword", SERVER_KEYSTORE_PASSWORD);
131+
System.setProperty("javax.net.ssl.trustStorePassword", keyStorePassword);
114132

115-
expectedException.expect(SSLHandshakeException.class);
116-
call("https://www.google.com");
133+
assertThrows(SSLHandshakeException.class, () -> call("https://www.google.com"));
117134
} finally {
118135
// Ensure to not keeping this property for other tests
119136
System.clearProperty("javax.net.ssl.trustStore");
@@ -122,19 +139,19 @@ public void when_overriding_truststore_known_websites_are_failing(String clientK
122139
}
123140

124141
@Test
125-
public void test_with_custom_https_server_using_ca_in_truststore() throws Exception {
142+
void test_with_custom_https_server_using_ca_in_truststore() throws Exception {
126143
test_with_custom_https_server(KEYSTORE_CLIENT_WITH_CA, CLIENT_WITH_CA_KEYSTORE_PASSWORD);
127144
}
128145

129146
@Test
130-
public void test_with_custom_https_server_using_server_certificate_in_truststore() throws Exception {
147+
void test_with_custom_https_server_using_server_certificate_in_truststore() throws Exception {
131148
test_with_custom_https_server(KEYSTORE_CLIENT_WITH_CERTIFICATE, CLIENT_WITH_CERTIFICATE_KEYSTORE_PASSWORD);
132149
}
133150

134151
private void test_with_custom_https_server(String clientKeyStore, String keyStorePassword) throws Exception {
135152
System.setProperty("javax.net.debug", "ssl,handshake,record");
136-
try (MockWebServer server = buildTLSServer()) {
137-
String url = format("https://localhost:%d/", server.getPort());
153+
try {
154+
String url = sonarqubeMock.baseUrl();
138155

139156
// First test without any truststore is expecting to fail
140157
try {
@@ -160,18 +177,18 @@ private void test_with_custom_https_server(String clientKeyStore, String keyStor
160177
}
161178

162179
@Test
163-
public void test_with_cookie_using_ca_in_truststore() throws Exception {
180+
void test_with_cookie_using_ca_in_truststore() throws Exception {
164181
test_with_cookie(KEYSTORE_CLIENT_WITH_CA, CLIENT_WITH_CA_KEYSTORE_PASSWORD);
165182
}
166183

167184
@Test
168-
public void test_with_cookie_using_server_certificate_in_truststore() throws Exception {
185+
void test_with_cookie_using_server_certificate_in_truststore() throws Exception {
169186
test_with_cookie(KEYSTORE_CLIENT_WITH_CERTIFICATE, CLIENT_WITH_CERTIFICATE_KEYSTORE_PASSWORD);
170187
}
171188

172189
private void test_with_cookie(String clientKeyStore, String keyStorePassword) throws Exception {
173-
try (MockWebServer server = buildTLSServer()) {
174-
String url = format("https://localhost:%d/", server.getPort());
190+
try {
191+
String url = sonarqubeMock.baseUrl();
175192

176193
// Add the truststore
177194
Path clientTruststore = Paths.get(getClass().getResource(clientKeyStore).toURI()).toAbsolutePath();
@@ -203,54 +220,12 @@ private static Response call(String url) throws IOException {
203220
.execute();
204221
}
205222

206-
/**
207-
* Build a MockWebServer with a dispatcher always sending 200 response with OK
208-
* This webserver will use respond only to https protocol
209-
*/
210-
private MockWebServer buildTLSServer() throws Exception {
211-
MockWebServer server = new MockWebServer();
212-
server.setDispatcher(new Dispatcher() {
213-
@Override
214-
public MockResponse dispatch(RecordedRequest request) {
215-
String responseBody = "OK";
216-
MockResponse response = new MockResponse().setResponseCode(200);
217-
String cookie = request.getHeader("Cookie");
218-
if (cookie == null || cookie.isEmpty()) {
219-
// Only set the cookie if it is not already set
220-
response.addHeader("Set-Cookie", COOKIE);
221-
} else {
222-
// dump the cookie into the response body to aid in test inspection
223-
responseBody += "\nCookie: " + cookie;
224-
}
225-
response.setBody(responseBody);
226-
return response;
227-
}
228-
});
229-
230-
// JKS file storing the private key and TLS certificate
231-
Path serverCertificate = Paths.get(getClass().getResource(SERVER_KEYSTORE_FILE).toURI()).toAbsolutePath();
232-
233-
// Load the KeyStore
234-
KeyStore serverKeyStore = KeyStore.getInstance("pkcs12");
235-
FileInputStream stream = new FileInputStream(serverCertificate.toFile());
236-
serverKeyStore.load(stream, SERVER_KEYSTORE_PASSWORD.toCharArray());
237-
238-
// Load the KeyManager from the KeyStore
239-
String kmfAlgorithm = KeyManagerFactory.getDefaultAlgorithm();
240-
KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmfAlgorithm);
241-
kmf.init(serverKeyStore, SERVER_KEYSTORE_PASSWORD.toCharArray());
242-
243-
// Add the "Keys" (ie. private key and TLS certificate to the TrustManager
244-
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(kmfAlgorithm);
245-
trustManagerFactory.init(serverKeyStore);
246-
247-
// Create the SocketFactory using the TrustManager so the private key and certificate
248-
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
249-
sslContext.init(kmf.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
250-
251-
// Let's use it for the WebServer
252-
server.useHttps(sslContext.getSocketFactory(), false);
253-
254-
return server;
223+
private static Path toPath(URL url) {
224+
try {
225+
return Paths.get(url.toURI());
226+
} catch (URISyntaxException e) {
227+
throw new RuntimeException(e);
228+
}
255229
}
230+
256231
}

0 commit comments

Comments
 (0)