From: Sébastien Lesaint Date: Mon, 11 May 2015 09:28:47 +0000 (+0200) Subject: add medium test for plugins webservices X-Git-Tag: 5.2-RC1~1953 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=d356b785defb5bb431422c13a9adc2fbbc57cb95;p=sonarqube.git add medium test for plugins webservices --- diff --git a/server/sonar-server/pom.xml b/server/sonar-server/pom.xml index fd3ee697d4f..060f744bfa1 100644 --- a/server/sonar-server/pom.xml +++ b/server/sonar-server/pom.xml @@ -255,6 +255,10 @@ src/test/resources false + + src/test/filteredresources + true + src/test/projects false diff --git a/server/sonar-server/src/test/filteredresources/org/sonar/server/plugins/ws/PluginsWsMediumTest/update-center.properties b/server/sonar-server/src/test/filteredresources/org/sonar/server/plugins/ws/PluginsWsMediumTest/update-center.properties new file mode 100644 index 00000000000..48e90c02556 --- /dev/null +++ b/server/sonar-server/src/test/filteredresources/org/sonar/server/plugins/ws/PluginsWsMediumTest/update-center.properties @@ -0,0 +1,63 @@ +# Current development version (single value) +devVersion=${project.version} + +# List of all versions available in production update center. No need to sort nor to include "devVersion". +publicVersions=3.7.1 + +# Versions not published to production, usually when technical release is done but doc and annoucement are still pending. No need to include "devVersion" +#privateVersions=4.2 + +# Long Term Support release. Must be declared in "publicVersions". +ltsVersion=3.7.1 + +# Describe each version listed in "publicVersions" and "privateVersions" : release date, URL to release notes, plain-text description, URL to ZIP distribution +3.7.1.date=2012-05-20 +3.7.1.changelogUrl=http://jira.codehaus.org/secure/ReleaseNote.jspa?projectId=11694&version=232323 +3.7.1.description=Fix regressions +3.7.1.downloadUrl=http://dist.sonar.codehaus.org/sonar-3.7.1.zip + +# list of plugins. It is used to load other files from the same directory. No need to sort. +plugins=foo,decoy + +# =============== decoy plugin +# Releases. Note that no need for "privateVersions" for now. +decoy.publicVersions=1.0,1.1 + +decoy.description=decoy +decoy.category=Languages + +decoy.defaults.mavenGroupId=org.codehaus.sonar-plugins +decoy.defaults.mavenArtifactId=sonar-decoy-plugin + +# Metadata of each release +# The range of supported SQ versions accepts the alias LATEST and * +decoy.1.0.date=2012-03-18 +decoy.1.0.sqVersions=${project.version} +decoy.1.0.description=Surprise +decoy.1.0.downloadUrl=file://${project.build.testOutputDirectory}/org/sonar/server/plugins/ws/PluginsWsMediumTest/sonar-decoy-plugin-1.0.jar +decoy.1.0.changelogUrl=http://jira.codehaus.org/foo + +decoy.1.1.date=2012-03-18 +decoy.1.1.sqVersions=${project.version} +decoy.1.1.description=Surprise +decoy.1.1.downloadUrl=file://${project.build.testOutputDirectory}/org/sonar/server/plugins/ws/PluginsWsMediumTest/sonar-decoy-plugin-1.1.jar +decoy.1.1.changelogUrl=http://jira.codehaus.org/foo + +# =============== decoy plugin +# Releases. Note that no need for "privateVersions" for now. +foo.publicVersions=1.0 + +foo.description=Foo +foo.category=Languages + +foo.defaults.mavenGroupId=org.codehaus.sonar-plugins +foo.defaults.mavenArtifactId=sonar-foo-plugin + +# Metadata of each release +# The range of supported SQ versions accepts the alias LATEST and * +foo.1.0.date=2012-03-18 +foo.1.0.sqVersions=${project.version} +foo.1.0.description=Surprise +foo.1.0.downloadUrl=file://${project.build.testOutputDirectory}/org/sonar/server/plugins/ws/PluginsWsMediumTest/sonar-foo-plugin-1.0.jar +foo.1.0.changelogUrl=http://jira.codehaus.org/foo + diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PluginsWsMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PluginsWsMediumTest.java new file mode 100644 index 00000000000..9427afa3358 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PluginsWsMediumTest.java @@ -0,0 +1,169 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.plugins.ws; + +import java.io.File; +import java.net.URISyntaxException; +import java.net.URL; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.sonar.core.permission.GlobalPermissions; +import org.sonar.server.tester.ServerTester; +import org.sonar.server.tester.UserSessionRule; +import org.sonar.server.ws.WsTester; + +public class PluginsWsMediumTest { + @ClassRule + public static ServerTester serverTester = new ServerTester() + .addPluginJar(getFile("sonar-decoy-plugin-1.0.jar")) + .setUpdateCenterUrl(getFileUrl("update-center.properties")); + @Rule + public UserSessionRule userSessionRule = UserSessionRule.forServerTester(serverTester); + + @Test + public void test_update_existing_and_install_new_scenario() throws Exception { + WsTester wsTester = new WsTester(serverTester.get(PluginsWs.class)); + + // 1 - check what's installed, available and pending + wsTester.newGetRequest("api/plugins", "installed").execute().assertJson("{" + + " \"plugins\": [" + + " {" + + " \"key\": \"decoy\"," + + " \"version\": \"1.0\"" + + " }" + + " ]" + + "}" + ); + + wsTester.newGetRequest("api/plugins", "available").execute().assertJson("{" + + " \"plugins\": [" + + " {" + + " \"key\": \"foo\"," + + " \"release\": {" + + " \"version\": \"1.0\"," + + " }," + + " \"update\": {" + + " \"status\": \"COMPATIBLE\"," + + " \"requires\": []" + + " }" + + " }" + + " ]" + + "}"); + + wsTester.newGetRequest("api/plugins", "pending").execute().assertJson("{\"installing\":[],\"removing\":[]}"); + + // 2 - login as admin and install one plugin, update another, verify pending status in the process + userSessionRule.login().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + wsTester.newPostRequest("api/plugins", "update").setParam("key", "decoy").execute().assertNoContent(); + + wsTester.newGetRequest("api/plugins", "pending").execute().assertJson("{" + + " \"installing\": [" + + " {" + + " \"key\": \"decoy\"," + + " \"version\": \"1.1\"" + + " }" + + " ]," + + " \"removing\": []" + + "}"); + + wsTester.newPostRequest("api/plugins", "install").setParam("key", "foo").execute().assertNoContent(); + + wsTester.newGetRequest("api/plugins", "pending").execute().assertJson("{" + + " \"installing\": [" + + " {" + + " \"key\": \"decoy\"," + + " \"version\": \"1.1\"" + + " }," + + " {" + + " \"key\": \"foo\"," + + " \"version\": \"1.0\"" + + " }" + + " ]," + + " \"removing\": []" + + "}"); + + // 3 - simulate SQ restart + wsTester = restartServerTester(); + + // 4 - make sure plugin is installed + wsTester.newGetRequest("api/plugins", "installed").execute().assertJson("{" + + " \"plugins\": [" + + " {" + + " \"key\": \"decoy\"," + + " \"version\": \"1.1\"" + + " }," + + " {" + + " \"key\": \"foo\"," + + " \"version\": \"1.0\"" + + " }" + + " ]" + + "}" + ); + + // 5 - login as admin again and uninstall a plugin, verify pending status in the process + userSessionRule.login().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + wsTester.newPostRequest("api/plugins", "uninstall").setParam("key", "foo").execute().assertNoContent(); + + wsTester.newGetRequest("api/plugins", "pending").execute().assertJson("{" + + " \"installing\": []," + + " \"removing\": [" + + " {" + + " \"key\": \"foo\"," + + " \"version\": \"1.0\"" + + " }" + + " ]," + + "}"); + + // 6 - simulate SQ restart again + wsTester = restartServerTester(); + + // 7 - make sure plugin has been uninstalled + wsTester.newGetRequest("api/plugins", "installed").execute().assertJson("{" + + " \"plugins\": [" + + " {" + + " \"key\": \"decoy\"," + + " \"version\": \"1.1\"" + + " }" + + " ]" + + "}" + ); + } + + private WsTester restartServerTester() { + serverTester.restart(); + // correctly simulate a server restart (ie. user is disconnected) + userSessionRule.anonymous(); + // must use a new WsTester to reference the right PluginWs instance + return new WsTester(serverTester.get(PluginsWs.class)); + } + + private static File getFile(String jarFileName) { + try { + return new File(getFileUrl(jarFileName).toURI()); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + + private static URL getFileUrl(String fileName) { + return PluginsWsMediumTest.class.getResource(PluginsWsMediumTest.class.getSimpleName() + "/" + fileName); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/tester/ServerTester.java b/server/sonar-server/src/test/java/org/sonar/server/tester/ServerTester.java index 93b786e6c8a..7aa97b0a535 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/tester/ServerTester.java +++ b/server/sonar-server/src/test/java/org/sonar/server/tester/ServerTester.java @@ -19,8 +19,17 @@ */ package org.sonar.server.tester; -import com.google.common.base.Throwables; -import com.google.common.collect.Lists; +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import javax.annotation.Nullable; +import javax.servlet.ServletContext; + import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUtils; import org.junit.rules.ExternalResource; @@ -32,17 +41,13 @@ import org.sonar.process.ProcessProperties; import org.sonar.server.es.EsServerHolder; import org.sonar.server.platform.BackendCleanup; import org.sonar.server.platform.Platform; +import org.sonar.server.plugins.UpdateCenterClient; import org.sonar.server.ws.WsTester; import org.sonar.test.TestUtils; -import javax.annotation.Nullable; -import javax.servlet.ServletContext; -import java.io.File; -import java.io.IOException; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Properties; +import com.google.common.base.Preconditions; +import com.google.common.base.Throwables; +import com.google.common.collect.Lists; /** * Entry point to implement medium tests of server components. @@ -63,6 +68,7 @@ public class ServerTester extends ExternalResource { private final List components = Lists.newArrayList(WsTester.class); private final Properties initialProps = new Properties(); private final ServletContext servletContext = new AttributeHolderServletContext(); + private URL updateCenterUrl; /** * Called only when JUnit @Rule or @ClassRule is used. @@ -90,6 +96,9 @@ public class ServerTester extends ExternalResource { properties.setProperty(ProcessProperties.PATH_DATA, new File(homeDir, "data").getAbsolutePath()); properties.setProperty(ProcessProperties.PATH_TEMP, createTemporaryFolderIn().getAbsolutePath()); properties.setProperty(DatabaseProperties.PROP_URL, "jdbc:h2:" + homeDir.getAbsolutePath() + "/h2"); + if (updateCenterUrl != null) { + properties.setProperty(UpdateCenterClient.URL_PROPERTY, updateCenterUrl.toString()); + } for (Map.Entry entry : System.getProperties().entrySet()) { String key = entry.getKey().toString(); if (key.startsWith(PROP_PREFIX)) { @@ -162,6 +171,23 @@ public class ServerTester extends ExternalResource { return this; } + public ServerTester addPluginJar(File jar) { + Preconditions.checkArgument(jar.exists() && jar.isFile(), "Plugin JAR file does not exist: " + jar.getAbsolutePath()); + try { + File pluginsDir = new File(homeDir, "extensions/plugins"); + FileUtils.forceMkdir(pluginsDir); + FileUtils.copyFileToDirectory(jar, pluginsDir); + return this; + } catch (Exception e) { + throw new IllegalStateException("Fail to copy plugin JAR file: " + jar.getAbsolutePath(), e); + } + } + + public ServerTester setUpdateCenterUrl(URL url) { + this.updateCenterUrl = url; + return this; + } + /** * Set a property available for startup. Must be called before {@link #start()}. Does not affect * Elasticsearch server. diff --git a/server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/PluginsWsMediumTest/sonar-decoy-plugin-1.0.jar b/server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/PluginsWsMediumTest/sonar-decoy-plugin-1.0.jar new file mode 100644 index 00000000000..1ca2ea2d1f6 Binary files /dev/null and b/server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/PluginsWsMediumTest/sonar-decoy-plugin-1.0.jar differ diff --git a/server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/PluginsWsMediumTest/sonar-decoy-plugin-1.1.jar b/server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/PluginsWsMediumTest/sonar-decoy-plugin-1.1.jar new file mode 100644 index 00000000000..c814e8a5176 Binary files /dev/null and b/server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/PluginsWsMediumTest/sonar-decoy-plugin-1.1.jar differ diff --git a/server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/PluginsWsMediumTest/sonar-foo-plugin-1.0.jar b/server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/PluginsWsMediumTest/sonar-foo-plugin-1.0.jar new file mode 100644 index 00000000000..9d608e08281 Binary files /dev/null and b/server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/PluginsWsMediumTest/sonar-foo-plugin-1.0.jar differ