aboutsummaryrefslogtreecommitdiffstats
path: root/tests/src/test/java
diff options
context:
space:
mode:
authorDaniel Schwarz <bartfastiel@users.noreply.github.com>2017-08-14 14:34:29 +0200
committerGitHub <noreply@github.com>2017-08-14 14:34:29 +0200
commitffff02cbed3e5f94bbf0c1718425d66e19ac3901 (patch)
tree6d99fd0df0913d32b37da9c8b3a280af6ad856d1 /tests/src/test/java
parent3a98cfe82a4eaf08eade2517dd115837b0126799 (diff)
downloadsonarqube-ffff02cbed3e5f94bbf0c1718425d66e19ac3901.tar.gz
sonarqube-ffff02cbed3e5f94bbf0c1718425d66e19ac3901.zip
SONAR-9704 verify that the compute engine is resilient
Diffstat (limited to 'tests/src/test/java')
-rw-r--r--tests/src/test/java/org/sonarqube/tests/Byteman.java50
-rw-r--r--tests/src/test/java/org/sonarqube/tests/QProfileTester.java10
-rw-r--r--tests/src/test/java/org/sonarqube/tests/analysis/AnalysisEsResilienceTest.java150
-rw-r--r--tests/src/test/java/org/sonarqube/tests/qualityProfile/ActiveRuleEsResilienceTest.java20
-rw-r--r--tests/src/test/java/org/sonarqube/tests/rule/RuleEsResilienceTest.java20
-rw-r--r--tests/src/test/java/org/sonarqube/tests/user/UserEsResilienceTest.java23
6 files changed, 263 insertions, 10 deletions
diff --git a/tests/src/test/java/org/sonarqube/tests/Byteman.java b/tests/src/test/java/org/sonarqube/tests/Byteman.java
index ccb025e34f9..59dc06f8112 100644
--- a/tests/src/test/java/org/sonarqube/tests/Byteman.java
+++ b/tests/src/test/java/org/sonarqube/tests/Byteman.java
@@ -21,6 +21,10 @@
import com.sonar.orchestrator.OrchestratorBuilder;
import java.io.File;
+import java.net.InetAddress;
+import java.util.Collections;
+import org.jboss.byteman.agent.submit.Submit;
+import org.sonar.process.NetworkUtils;
import static java.lang.String.format;
@@ -30,14 +34,25 @@ import static java.lang.String.format;
*/
public class Byteman {
- public static OrchestratorBuilder enableScript(OrchestratorBuilder builder, String filename) {
+ private final int port;
+ private final OrchestratorBuilder builder;
+
+ public enum Process {
+ WEB("sonar.web.javaAdditionalOpts"), CE("sonar.ce.javaAdditionalOpts");
+
+ private final String argument;
+
+ Process(String argument) {
+ this.argument = argument;
+ }
+ }
+
+ public Byteman(OrchestratorBuilder builder, Process process) {
+ this.builder = builder;
String jar = findBytemanJar();
- builder
- .setServerProperty("sonar.web.javaAdditionalOpts",
- format("-javaagent:%s=script:%s,boot:%s", jar, findBytemanScript(filename), jar))
- .setServerProperty("sonar.search.recovery.delayInMs", "1000")
- .setServerProperty("sonar.search.recovery.minAgeInMs", "3000");
- return builder;
+ port = NetworkUtils.getNextAvailablePort(InetAddress.getLoopbackAddress());
+ String bytemanArg = format("-javaagent:%s=boot:%s,port:%d", jar, jar, port);
+ builder.setServerProperty(process.argument, bytemanArg);
}
private static String findBytemanJar() {
@@ -49,6 +64,12 @@ public class Byteman {
return jar.getAbsolutePath();
}
+ public void activateScript(String filename) throws Exception {
+ String bytemanScript = findBytemanScript(filename);
+ Submit submit = new Submit(InetAddress.getLoopbackAddress().getHostAddress(), port);
+ submit.addRulesFromFiles(Collections.singletonList(bytemanScript));
+ }
+
private static String findBytemanScript(String filename) {
// see pom.xml, Maven copies and renames the artifact.
File script = new File( filename);
@@ -57,4 +78,19 @@ public class Byteman {
}
return script.getAbsolutePath();
}
+
+ public void deactivateAllRules() throws Exception {
+ Submit submit = new Submit(InetAddress.getLoopbackAddress().getHostAddress(), port);
+ try {
+ submit.deleteAllRules();
+ } catch (java.lang.Exception e) {
+ if (e.getMessage() == null || !e.getMessage().contains("No rule scripts to remove")) {
+ throw e;
+ }
+ }
+ }
+
+ public OrchestratorBuilder getOrchestratorBuilder() {
+ return builder;
+ }
}
diff --git a/tests/src/test/java/org/sonarqube/tests/QProfileTester.java b/tests/src/test/java/org/sonarqube/tests/QProfileTester.java
index 764b80d6955..c2d163151c6 100644
--- a/tests/src/test/java/org/sonarqube/tests/QProfileTester.java
+++ b/tests/src/test/java/org/sonarqube/tests/QProfileTester.java
@@ -26,8 +26,10 @@ import org.sonarqube.ws.Common;
import org.sonarqube.ws.Organizations.Organization;
import org.sonarqube.ws.QualityProfiles.CreateWsResponse.QualityProfile;
import org.sonarqube.ws.Rules;
+import org.sonarqube.ws.WsProjects.CreateWsResponse.Project;
import org.sonarqube.ws.client.HttpException;
import org.sonarqube.ws.client.qualityprofile.ActivateRuleWsRequest;
+import org.sonarqube.ws.client.qualityprofile.AddProjectRequest;
import org.sonarqube.ws.client.qualityprofile.CreateRequest;
import org.sonarqube.ws.client.qualityprofile.QualityProfilesService;
import org.sonarqube.ws.client.rule.SearchWsRequest;
@@ -79,6 +81,14 @@ public class QProfileTester {
return this;
}
+ public QProfileTester assignQProfileToProject(QualityProfile profile, Project project) {
+ service().addProject(AddProjectRequest.builder()
+ .setProjectKey(project.getKey())
+ .setProfileKey(profile.getKey())
+ .build());
+ return this;
+ }
+
public QProfileTester assertThatNumberOfActiveRulesEqualsTo(QualityProfile profile, int expectedActiveRules) {
return assertThatNumberOfActiveRulesEqualsTo(profile.getKey(), expectedActiveRules);
}
diff --git a/tests/src/test/java/org/sonarqube/tests/analysis/AnalysisEsResilienceTest.java b/tests/src/test/java/org/sonarqube/tests/analysis/AnalysisEsResilienceTest.java
new file mode 100644
index 00000000000..6d6adeb2030
--- /dev/null
+++ b/tests/src/test/java/org/sonarqube/tests/analysis/AnalysisEsResilienceTest.java
@@ -0,0 +1,150 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.sonarqube.tests.analysis;
+
+import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.build.BuildResult;
+import com.sonar.orchestrator.build.SonarScanner;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.junit.After;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonarqube.tests.Byteman;
+import org.sonarqube.tests.Tester;
+import org.sonarqube.ws.Issues;
+import org.sonarqube.ws.Organizations.Organization;
+import org.sonarqube.ws.QualityProfiles.CreateWsResponse.QualityProfile;
+import org.sonarqube.ws.WsProjects;
+import org.sonarqube.ws.WsUsers.CreateWsResponse.User;
+import org.sonarqube.ws.client.component.SuggestionsWsRequest;
+import org.sonarqube.ws.client.issue.SearchWsRequest;
+import util.ItUtils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.tuple;
+import static org.sonarqube.tests.Byteman.Process.CE;
+import static util.ItUtils.projectDir;
+
+public class AnalysisEsResilienceTest {
+
+ @ClassRule
+ public static final Orchestrator orchestrator;
+ private static final Byteman byteman;
+
+ static {
+ byteman = new Byteman(Orchestrator.builderEnv(), CE);
+ orchestrator = byteman
+ .getOrchestratorBuilder()
+ .addPlugin(ItUtils.xooPlugin())
+ .build();
+ }
+
+ @Rule
+ public Tester tester = new Tester(orchestrator);
+
+ @After
+ public void after() throws Exception {
+ byteman.deactivateAllRules();
+ }
+
+ @Test
+ public void activation_and_deactivation_of_rule_is_resilient_to_indexing_errors() throws Exception {
+ Organization organization = tester.organizations().generate();
+ User orgAdministrator = tester.users().generateAdministrator(organization);
+ WsProjects.CreateWsResponse.Project project = tester.projects().generate(organization);
+ String projectKey = project.getKey();
+ String fileKey = projectKey + ":src/main/xoo/sample/Sample.xoo";
+ String file2Key = projectKey + ":src/main/xoo/sample/Sample2.xoo";
+ String file3Key = projectKey + ":src/main/xoo/sample/Sample3.xoo";
+
+ QualityProfile profile = tester.qProfiles().createXooProfile(organization);
+ tester.qProfiles()
+ .activateRule(profile, "xoo:OneIssuePerFile")
+ .assignQProfileToProject(profile, project);
+
+ executeAnalysis(projectKey, organization, orgAdministrator, "analysis/resilience/resilience-sample-v1");
+ assertThat(searchFile(fileKey, organization)).isNotEmpty();
+ assertThat(searchFile(file2Key, organization)).isEmpty();
+ assertThat(searchFile(file3Key, organization)).isEmpty();
+ List<Issues.Issue> issues = searchIssues(projectKey);
+ assertThat(issues)
+ .extracting(Issues.Issue::getComponent)
+ .containsExactlyInAnyOrder(fileKey);
+
+ byteman.activateScript("resilience/making_ce_indexation_failing.btm");
+ executeAnalysis(projectKey, organization, orgAdministrator, "analysis/resilience/resilience-sample-v2");
+ assertThat(searchFile(fileKey, organization)).isNotEmpty();
+ assertThat(searchFile(file2Key, organization)).isEmpty();// inconsistency: in DB there is also file2Key
+ assertThat(searchFile(file3Key, organization)).isEmpty();// inconsistency: in DB there is also file3Key
+ issues = searchIssues(projectKey);
+ assertThat(issues)
+ .extracting(Issues.Issue::getComponent)
+ .containsExactlyInAnyOrder(fileKey /* inconsistency: in DB there is also file2Key and file3Key */);
+ byteman.deactivateAllRules();
+
+ executeAnalysis(projectKey, organization, orgAdministrator, "analysis/resilience/resilience-sample-v3");
+ assertThat(searchFile(fileKey, organization)).isNotEmpty();
+ assertThat(searchFile(file2Key, organization)).isEmpty();
+ assertThat(searchFile(file3Key, organization)).isNotEmpty();
+ issues = searchIssues(projectKey);
+ assertThat(issues)
+ .extracting(Issues.Issue::getComponent, Issues.Issue::getStatus)
+ .containsExactlyInAnyOrder(
+ tuple(fileKey, "OPEN"),
+ tuple(file2Key, "CLOSED"),
+ tuple(file3Key, "OPEN"));
+ }
+
+ private List<Issues.Issue> searchIssues(String projectKey) {
+ SearchWsRequest request = new SearchWsRequest()
+ .setProjectKeys(Collections.singletonList(projectKey));
+ Issues.SearchWsResponse results = tester.wsClient().issues().search(request);
+ return results.getIssuesList();
+ }
+
+ private List<String> searchFile(String key, Organization organization) {
+ SuggestionsWsRequest query = SuggestionsWsRequest.builder()
+ .setS(key)
+ .build();
+ Map<String, Object> response = ItUtils.jsonToMap(
+ tester.wsClient().components().suggestions(query).content()
+ );
+ List results = (List) response.get("results");
+ Map trkResult = (Map) results.stream().filter(result -> "FIL".equals(((Map) result).get("q"))).findAny().get();
+ List items = (List) trkResult.get("items");
+ Stream<String> x = items.stream().map(item -> (String) ((Map) item).get("key"));
+ return x.collect(Collectors.toList());
+ }
+
+ private String executeAnalysis(String projectKey, Organization organization, User orgAdministrator, String projectPath) {
+ BuildResult buildResult = orchestrator.executeBuild(SonarScanner.create(projectDir(projectPath),
+ "sonar.organization", organization.getKey(),
+ "sonar.projectKey", projectKey,
+ "sonar.login", orgAdministrator.getLogin(),
+ "sonar.password", orgAdministrator.getLogin()));
+ return ItUtils.extractCeTaskId(buildResult);
+ }
+
+}
diff --git a/tests/src/test/java/org/sonarqube/tests/qualityProfile/ActiveRuleEsResilienceTest.java b/tests/src/test/java/org/sonarqube/tests/qualityProfile/ActiveRuleEsResilienceTest.java
index cfa5f160423..49be3215f07 100644
--- a/tests/src/test/java/org/sonarqube/tests/qualityProfile/ActiveRuleEsResilienceTest.java
+++ b/tests/src/test/java/org/sonarqube/tests/qualityProfile/ActiveRuleEsResilienceTest.java
@@ -21,6 +21,8 @@ package org.sonarqube.tests.qualityProfile;
import com.sonar.orchestrator.Orchestrator;
import java.util.concurrent.TimeUnit;
+import org.junit.After;
+import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
@@ -35,19 +37,35 @@ import org.sonarqube.ws.client.rule.SearchWsRequest;
import util.ItUtils;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonarqube.tests.Byteman.Process.WEB;
public class ActiveRuleEsResilienceTest {
private static final String RULE_ONE_BUG_PER_LINE = "xoo:OneBugIssuePerLine";
@ClassRule
public static final Orchestrator orchestrator;
+ private static final Byteman byteman;
static {
- orchestrator = Byteman.enableScript(Orchestrator.builderEnv(), "resilience/active_rule_indexer.btm")
+ byteman = new Byteman(Orchestrator.builderEnv(), WEB);
+ orchestrator = byteman
+ .getOrchestratorBuilder()
+ .setServerProperty("sonar.search.recovery.delayInMs", "1000")
+ .setServerProperty("sonar.search.recovery.minAgeInMs", "3000")
.addPlugin(ItUtils.xooPlugin())
.build();
}
+ @Before
+ public void before() throws Exception {
+ byteman.activateScript("resilience/active_rule_indexer.btm");
+ }
+
+ @After
+ public void after() throws Exception {
+ byteman.deactivateAllRules();
+ }
+
@Rule
public TestRule timeout = new DisableOnDebug(Timeout.builder()
.withLookingForStuckThread(true)
diff --git a/tests/src/test/java/org/sonarqube/tests/rule/RuleEsResilienceTest.java b/tests/src/test/java/org/sonarqube/tests/rule/RuleEsResilienceTest.java
index a9f606fb320..c887cf652f3 100644
--- a/tests/src/test/java/org/sonarqube/tests/rule/RuleEsResilienceTest.java
+++ b/tests/src/test/java/org/sonarqube/tests/rule/RuleEsResilienceTest.java
@@ -21,6 +21,8 @@ package org.sonarqube.tests.rule;
import com.sonar.orchestrator.Orchestrator;
import java.util.concurrent.TimeUnit;
+import org.junit.After;
+import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
@@ -35,18 +37,34 @@ import util.ItUtils;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonarqube.tests.Byteman.Process.WEB;
public class RuleEsResilienceTest {
@ClassRule
public static final Orchestrator orchestrator;
+ private static final Byteman byteman;
static {
- orchestrator = Byteman.enableScript(Orchestrator.builderEnv(), "resilience/rule_indexer.btm")
+ byteman = new Byteman(Orchestrator.builderEnv(), WEB);
+ orchestrator = byteman
+ .getOrchestratorBuilder()
+ .setServerProperty("sonar.search.recovery.delayInMs", "1000")
+ .setServerProperty("sonar.search.recovery.minAgeInMs", "3000")
.addPlugin(ItUtils.xooPlugin())
.build();
}
+ @Before
+ public void before() throws Exception {
+ byteman.activateScript("resilience/rule_indexer.btm");
+ }
+
+ @After
+ public void after() throws Exception {
+ byteman.deactivateAllRules();
+ }
+
@Rule
public TestRule timeout = new DisableOnDebug(Timeout.builder()
.withLookingForStuckThread(true)
diff --git a/tests/src/test/java/org/sonarqube/tests/user/UserEsResilienceTest.java b/tests/src/test/java/org/sonarqube/tests/user/UserEsResilienceTest.java
index b98661e8fe4..3f2d69fe898 100644
--- a/tests/src/test/java/org/sonarqube/tests/user/UserEsResilienceTest.java
+++ b/tests/src/test/java/org/sonarqube/tests/user/UserEsResilienceTest.java
@@ -21,6 +21,8 @@ package org.sonarqube.tests.user;
import com.sonar.orchestrator.Orchestrator;
import java.util.concurrent.TimeUnit;
+import org.junit.After;
+import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
@@ -32,17 +34,36 @@ import org.sonarqube.tests.Tester;
import org.sonarqube.ws.WsUsers.CreateWsResponse.User;
import org.sonarqube.ws.client.user.SearchRequest;
import org.sonarqube.ws.client.user.UpdateRequest;
+import util.ItUtils;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonarqube.tests.Byteman.Process.WEB;
import static util.ItUtils.expectHttpError;
public class UserEsResilienceTest {
@ClassRule
public static final Orchestrator orchestrator;
+ private static final Byteman byteman;
static {
- orchestrator = Byteman.enableScript(Orchestrator.builderEnv(), "resilience/user_indexer.btm").build();
+ byteman = new Byteman(Orchestrator.builderEnv(), WEB);
+ orchestrator = byteman
+ .getOrchestratorBuilder()
+ .setServerProperty("sonar.search.recovery.delayInMs", "1000")
+ .setServerProperty("sonar.search.recovery.minAgeInMs", "3000")
+ .addPlugin(ItUtils.xooPlugin())
+ .build();
+ }
+
+ @Before
+ public void before() throws Exception {
+ byteman.activateScript("resilience/user_indexer.btm");
+ }
+
+ @After
+ public void after() throws Exception {
+ byteman.deactivateAllRules();
}
@Rule