From d356b785defb5bb431422c13a9adc2fbbc57cb95 Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=C3=A9bastien=20Lesaint?= Date: Mon, 11 May 2015 11:28:47 +0200 Subject: [PATCH] add medium test for plugins webservices --- server/sonar-server/pom.xml | 4 + .../update-center.properties | 63 +++++++ .../plugins/ws/PluginsWsMediumTest.java | 169 ++++++++++++++++++ .../org/sonar/server/tester/ServerTester.java | 46 +++-- .../sonar-decoy-plugin-1.0.jar | Bin 0 -> 1613 bytes .../sonar-decoy-plugin-1.1.jar | Bin 0 -> 1613 bytes .../sonar-foo-plugin-1.0.jar | Bin 0 -> 1587 bytes 7 files changed, 272 insertions(+), 10 deletions(-) create mode 100644 server/sonar-server/src/test/filteredresources/org/sonar/server/plugins/ws/PluginsWsMediumTest/update-center.properties create mode 100644 server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PluginsWsMediumTest.java create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/PluginsWsMediumTest/sonar-decoy-plugin-1.0.jar create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/PluginsWsMediumTest/sonar-decoy-plugin-1.1.jar create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/plugins/ws/PluginsWsMediumTest/sonar-foo-plugin-1.0.jar 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 0000000000000000000000000000000000000000..1ca2ea2d1f6e3fc75c260ccb5afef62c4dea3063 GIT binary patch literal 1613 zcmWIWW@Zs#U|`^2*pj;3ZKeAf#tn=N3{uPt3?d9N48E=*j=G+HZu-8Cex7cw!6ACS zZlNKZ49vk!-l3jATw1}+z{v6vs2oh>2F2#jHV~f-6JBEvI9r+(fy6fT)|Rq57Oj&$8S z*FIdy{_^Qz^}g@?0r1$*Oj+)B-O2p*abQ|F2uuMQz}U|(O4l#W&r2-QFUToP&&(^< zPf1PAuhe$|kpW;Ky{yEtL~x3DYVRE?#bn6S_P)03fv0|L<4%rOnXat! z7hDT?RCa4pN=p0D^7}6}R=-G0+}ry9{D0LyM}PW@3mCC$TUu^YEo+=~L;2So^J4+g zM%r`k+`Q?hdCRp=aBq;`r9Hc{h5k-`9}<4zo!h4dox6&Y*yZPP=)9i0n$=k+soRq^ z@6>k28Tsc=__)hFi!NF3qv_!A_duPM^mPV_t&dqIfBfocoFV=>yzX&S4fh6@k3LJk zedPCByE-T=zRNRf`S}U$yL7j?{+60~Zrz3MpNxorQixvdrmDgCr3@HI*O?d?G>HtT zsuz`TEsys%v}Fgy-ORpY;JAO z_#ai0`9WswxztC;v@U7!NThl0sJLe2v0{nx>c5;T!|cjK7IkiqPL$gHDJb>cGxu|L zr=m`8FgO};YHs8Wtz_wLp6cX^<(baA&F8wm%-VHCKxE>hzvq@NT$}dd_my9-E27Gj z@1CBMB(CAJhq)uDOo}aLO%Zvu!LL+hAGXXmP%>w2v_3>}@Vw4x# z5IDEuXY(!P6^0Jak2`ArU&Q@*!PfeVT4LN^Rydq3m#DwFRq&e3hOK+DU$O^yGcw6B z<0=6qfVqKz0T|N^OBz8e?ByXVq&!56Ph^uZa~HzoEsg(x77(A;fVP418Xns)lPJVC lkPo&rssjsaVr+vZSfF)S5^I1rD;vl-W*{^Ng%2x;2LL05gx&xE literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..c814e8a5176b04ab473371305c38f01ad5cb327c GIT binary patch literal 1613 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 Xfl?`kRjh0vqnLqEAL#6NEFc~Lz)gQu literal 0 HcmV?d00001 -- 2.39.5