aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PluginFilesTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PluginFilesTest.java')
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PluginFilesTest.java172
1 files changed, 96 insertions, 76 deletions
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PluginFilesTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PluginFilesTest.java
index 21d6b3c5317..907e13f92bc 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PluginFilesTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PluginFilesTest.java
@@ -19,98 +19,113 @@
*/
package org.sonar.scanner.bootstrap;
+import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketTimeoutException;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.Collections;
import java.util.Optional;
-import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
-import okhttp3.HttpUrl;
-import okhttp3.mockwebserver.MockResponse;
-import okhttp3.mockwebserver.MockWebServer;
-import okio.Buffer;
import org.apache.commons.codec.digest.DigestUtils;
-import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.RandomStringUtils;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.junit.jupiter.api.io.TempDir;
import org.sonar.api.config.internal.MapSettings;
import org.sonar.api.notifications.AnalysisWarnings;
import org.sonar.scanner.bootstrap.ScannerPluginInstaller.InstalledPlugin;
+import org.sonar.scanner.http.DefaultScannerWsClient;
import org.sonarqube.ws.client.HttpConnector;
import org.sonarqube.ws.client.WsClientFactories;
+import static com.github.tomakehurst.wiremock.client.WireMock.anyRequestedFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl;
+import static com.github.tomakehurst.wiremock.client.WireMock.exactly;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.notFound;
+import static com.github.tomakehurst.wiremock.client.WireMock.ok;
+import static com.github.tomakehurst.wiremock.client.WireMock.serverError;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
+import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
import static org.apache.commons.io.FileUtils.moveFile;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.ThrowableAssert.ThrowingCallable;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import static org.sonar.scanner.bootstrap.PluginFiles.PLUGINS_DOWNLOAD_TIMEOUT_PROPERTY;
-public class PluginFilesTest {
+class PluginFilesTest {
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
- @Rule
- public MockWebServer server = new MockWebServer();
+ @RegisterExtension
+ static WireMockExtension sonarqube = WireMockExtension.newInstance()
+ .options(wireMockConfig().dynamicPort())
+ .build();
+
+ @TempDir
+ private Path tempDir;
+
+ private final SonarUserHome sonarUserHome = mock(SonarUserHome.class);
private final AnalysisWarnings analysisWarnings = mock(AnalysisWarnings.class);
- private File userHome;
private PluginFiles underTest;
- @Before
- public void setUp() throws Exception {
- HttpConnector connector = HttpConnector.newBuilder().acceptGzip(true).url(server.url("/").toString()).build();
+ @BeforeEach
+ void setUp(@TempDir Path sonarUserHomeDir) throws Exception {
+ when(sonarUserHome.getPath()).thenReturn(sonarUserHomeDir);
+
+ HttpConnector connector = HttpConnector.newBuilder().acceptGzip(true).url(sonarqube.url("/")).build();
GlobalAnalysisMode analysisMode = new GlobalAnalysisMode(new ScannerProperties(Collections.emptyMap()));
DefaultScannerWsClient wsClient = new DefaultScannerWsClient(WsClientFactories.getDefault().newClient(connector), false,
analysisMode, analysisWarnings);
- userHome = temp.newFolder();
MapSettings settings = new MapSettings();
- settings.setProperty("sonar.userHome", userHome.getAbsolutePath());
settings.setProperty(PLUGINS_DOWNLOAD_TIMEOUT_PROPERTY, 1);
- underTest = new PluginFiles(wsClient, settings.asConfig());
+ underTest = new PluginFiles(wsClient, settings.asConfig(), sonarUserHome);
}
@Test
- public void get_jar_from_cache_if_present() throws Exception {
+ void get_jar_from_cache_if_present() throws Exception {
FileAndMd5 jar = createFileInCache("foo");
File result = underTest.get(newInstalledPlugin("foo", jar.md5)).get();
- verifySameContent(result, jar);
+ verifySameContent(result.toPath(), jar);
// no requests to server
- assertThat(server.getRequestCount()).isZero();
+ sonarqube.verify(0, anyRequestedFor(anyUrl()));
}
@Test
- public void download_and_add_jar_to_cache_if_missing() throws Exception {
+ void download_and_add_jar_to_cache_if_missing() throws Exception {
FileAndMd5 tempJar = new FileAndMd5();
- enqueueDownload(tempJar);
+ stubDownload(tempJar);
InstalledPlugin plugin = newInstalledPlugin("foo", tempJar.md5);
File result = underTest.get(plugin).get();
- verifySameContent(result, tempJar);
- HttpUrl requestedUrl = server.takeRequest().getRequestUrl();
- assertThat(requestedUrl.encodedPath()).isEqualTo("/api/plugins/download");
- assertThat(requestedUrl.encodedQuery()).isEqualTo("plugin=foo");
+ verifySameContent(result.toPath(), tempJar);
+
+ sonarqube.verify(exactly(1), getRequestedFor(urlEqualTo("/api/plugins/download?plugin=foo")));
// get from cache on second call
result = underTest.get(plugin).get();
- verifySameContent(result, tempJar);
- assertThat(server.getRequestCount()).isOne();
+ verifySameContent(result.toPath(), tempJar);
+
+ sonarqube.verify(exactly(1), getRequestedFor(urlEqualTo("/api/plugins/download?plugin=foo")));
}
@Test
- public void return_empty_if_plugin_not_found_on_server() {
- server.enqueue(new MockResponse().setResponseCode(404));
+ void return_empty_if_plugin_not_found_on_server() {
+ sonarqube.stubFor(get(anyUrl())
+ .willReturn(notFound()));
InstalledPlugin plugin = newInstalledPlugin("foo", "abc");
Optional<File> result = underTest.get(plugin);
@@ -119,9 +134,9 @@ public class PluginFilesTest {
}
@Test
- public void fail_if_integrity_of_download_is_not_valid() throws IOException {
+ void fail_if_integrity_of_download_is_not_valid() throws IOException {
FileAndMd5 tempJar = new FileAndMd5();
- enqueueDownload(tempJar.file, "invalid_hash");
+ stubDownload(tempJar.file, "invalid_hash");
InstalledPlugin plugin = newInstalledPlugin("foo", "abc");
expectISE("foo", "was expected to have checksum invalid_hash but had " + tempJar.md5,
@@ -129,63 +144,68 @@ public class PluginFilesTest {
}
@Test
- public void fail_if_md5_header_is_missing_from_response() throws IOException {
- File tempJar = temp.newFile();
- enqueueDownload(tempJar, null);
+ void fail_if_md5_header_is_missing_from_response(@TempDir Path tempDir) throws IOException {
+ var tempJar = Files.createTempFile(tempDir, "plugin", ".jar");
+ stubDownload(tempJar, null);
InstalledPlugin plugin = newInstalledPlugin("foo", "abc");
expectISE("foo", "did not return header Sonar-MD5", () -> underTest.get(plugin));
}
@Test
- public void fail_if_server_returns_error() {
- server.enqueue(new MockResponse().setResponseCode(500));
+ void fail_if_server_returns_error() {
+ sonarqube.stubFor(get(anyUrl())
+ .willReturn(serverError()));
+
InstalledPlugin plugin = newInstalledPlugin("foo", "abc");
expectISE("foo", "returned code 500", () -> underTest.get(plugin));
}
@Test
- public void getPlugin_whenTimeOutReached_thenDownloadFails() {
- MockResponse response = new MockResponse().setBody("test").setBodyDelay(2, TimeUnit.SECONDS);
- response.setHeader("Sonar-MD5", "md5");
- server.enqueue(response);
+ void getPlugin_whenTimeOutReached_thenDownloadFails() {
+ sonarqube.stubFor(get(anyUrl())
+ .willReturn(ok()
+ .withFixedDelay(5000)));
+
InstalledPlugin plugin = newInstalledPlugin("foo", "abc");
assertThatThrownBy(() -> underTest.get(plugin))
.isInstanceOf(IllegalStateException.class)
- .hasMessageStartingWith("Fail to download plugin [" + plugin.key + "]")
+ .hasMessageStartingWith("Fail to request url")
.cause().isInstanceOf(SocketTimeoutException.class);
}
@Test
- public void download_a_new_version_of_plugin_during_blue_green_switch() throws IOException {
+ void download_a_new_version_of_plugin_during_blue_green_switch() throws IOException {
FileAndMd5 tempJar = new FileAndMd5();
- enqueueDownload(tempJar);
+ stubDownload(tempJar);
// expecting to download plugin foo with checksum "abc"
InstalledPlugin pluginV1 = newInstalledPlugin("foo", "abc");
File result = underTest.get(pluginV1).get();
- verifySameContent(result, tempJar);
+ verifySameContent(result.toPath(), tempJar);
// new version of downloaded jar is put in cache with the new md5
InstalledPlugin pluginV2 = newInstalledPlugin("foo", tempJar.md5);
result = underTest.get(pluginV2).get();
- verifySameContent(result, tempJar);
- assertThat(server.getRequestCount()).isOne();
+ verifySameContent(result.toPath(), tempJar);
+
+ sonarqube.verify(exactly(1), getRequestedFor(urlEqualTo("/api/plugins/download?plugin=foo")));
// v1 still requests server and downloads v2
- enqueueDownload(tempJar);
+ stubDownload(tempJar);
result = underTest.get(pluginV1).get();
- verifySameContent(result, tempJar);
- assertThat(server.getRequestCount()).isEqualTo(2);
+ verifySameContent(result.toPath(), tempJar);
+
+ sonarqube.verify(exactly(2), getRequestedFor(urlEqualTo("/api/plugins/download?plugin=foo")));
}
@Test
- public void fail_if_cached_file_is_outside_cache_dir() throws IOException {
+ void fail_if_cached_file_is_outside_cache_dir() throws IOException {
FileAndMd5 tempJar = new FileAndMd5();
- enqueueDownload(tempJar);
+ stubDownload(tempJar);
InstalledPlugin plugin = newInstalledPlugin("foo/bar", "abc");
@@ -200,29 +220,29 @@ public class PluginFilesTest {
}
private FileAndMd5 moveToCache(String pluginKey, FileAndMd5 jar) throws IOException {
- File jarInCache = new File(userHome, "cache/" + jar.md5 + "/sonar-" + pluginKey + "-plugin.jar");
- moveFile(jar.file, jarInCache);
+ Path jarInCache = sonarUserHome.getPath().resolve("cache/" + jar.md5 + "/sonar-" + pluginKey + "-plugin.jar");
+ moveFile(jar.file.toFile(), jarInCache.toFile());
return new FileAndMd5(jarInCache, jar.md5);
}
/**
* Enqueue download of file with valid MD5
*/
- private void enqueueDownload(FileAndMd5 file) throws IOException {
- enqueueDownload(file.file, file.md5);
+ private void stubDownload(FileAndMd5 file) throws IOException {
+ stubDownload(file.file, file.md5);
}
/**
* Enqueue download of file with a MD5 that may not be returned (null) or not valid
*/
- private void enqueueDownload(File file, @Nullable String md5) throws IOException {
- Buffer body = new Buffer();
- body.write(FileUtils.readFileToByteArray(file));
- MockResponse response = new MockResponse().setBody(body);
+ private void stubDownload(Path file, @Nullable String md5) throws IOException {
+ var responseDefBuilder = ok();
if (md5 != null) {
- response.setHeader("Sonar-MD5", md5);
+ responseDefBuilder.withHeader("Sonar-MD5", md5);
}
- server.enqueue(response);
+ responseDefBuilder.withBody(Files.readAllBytes(file));
+ sonarqube.stubFor(get(urlMatching("/api/plugins/download\\?plugin=.*"))
+ .willReturn(responseDefBuilder));
}
private static InstalledPlugin newInstalledPlugin(String pluginKey, String fileChecksum) {
@@ -232,10 +252,10 @@ public class PluginFilesTest {
return plugin;
}
- private static void verifySameContent(File file1, FileAndMd5 file2) {
- assertThat(file1).isFile().exists();
- assertThat(file2.file).isFile().exists();
- assertThat(file1).hasSameContentAs(file2.file);
+ private static void verifySameContent(Path file1, FileAndMd5 file2) {
+ assertThat(file1).isRegularFile();
+ assertThat(file2.file).isRegularFile();
+ assertThat(file1).hasSameTextualContentAs(file2.file);
}
private void expectISE(String pluginKey, String message, ThrowingCallable shouldRaiseThrowable) {
@@ -246,18 +266,18 @@ public class PluginFilesTest {
}
private class FileAndMd5 {
- private final File file;
+ private final Path file;
private final String md5;
- FileAndMd5(File file, String md5) {
+ FileAndMd5(Path file, String md5) {
this.file = file;
this.md5 = md5;
}
FileAndMd5() throws IOException {
- this.file = temp.newFile();
- FileUtils.write(this.file, RandomStringUtils.random(3));
- try (InputStream fis = FileUtils.openInputStream(this.file)) {
+ this.file = Files.createTempFile(tempDir, "jar", null);
+ Files.write(this.file, RandomStringUtils.random(3).getBytes());
+ try (InputStream fis = Files.newInputStream(this.file)) {
this.md5 = DigestUtils.md5Hex(fis);
} catch (IOException e) {
throw new IllegalStateException("Fail to compute md5 of " + this.file, e);