aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorEric Hartmann <hartmann.eric@gmail.com>2017-07-03 12:15:00 +0200
committerSimon Brandhof <simon.brandhof@sonarsource.com>2017-07-06 12:32:00 +0200
commitbf1ca1cbcd17a623ec9c53f5069ade9f792f2b3f (patch)
tree41de1b71a14ecdfe8852ebb3e4ce981d9879fe6e /tests
parent4b08d04bb8db93c40fa7cffe05ed51dbdac4b81d (diff)
downloadsonarqube-bf1ca1cbcd17a623ec9c53f5069ade9f792f2b3f.tar.gz
sonarqube-bf1ca1cbcd17a623ec9c53f5069ade9f792f2b3f.zip
SONAR-9481 Make operations on QProfiles resilient to ES errors
Diffstat (limited to 'tests')
-rw-r--r--tests/resilience/active_rule_indexer.btm12
-rw-r--r--tests/src/test/java/org/sonarqube/tests/Category5Suite.java2
-rw-r--r--tests/src/test/java/org/sonarqube/tests/qualityProfile/ActiveRuleEsResilienceTest.java107
3 files changed, 121 insertions, 0 deletions
diff --git a/tests/resilience/active_rule_indexer.btm b/tests/resilience/active_rule_indexer.btm
new file mode 100644
index 00000000000..331b76d69e7
--- /dev/null
+++ b/tests/resilience/active_rule_indexer.btm
@@ -0,0 +1,12 @@
+# sonar.web.javaAdditionalOpts=-javaagent:/path/to/byteman-3.0.10/lib/byteman.jar=script:/path/to/active_rule_indexer.btm,boot:/path/to/byteman-3.0.10/lib/byteman.jar
+# sonar.search.recovery.delayInMs=10000
+# sonar.search.recovery.minAgeInMs=30000
+
+RULE make indexing of active rules silently fail
+CLASS ActiveRuleIndexer
+METHOD postCommit
+COMPILE
+AT ENTRY
+IF TRUE
+DO RETURN
+ENDRULE
diff --git a/tests/src/test/java/org/sonarqube/tests/Category5Suite.java b/tests/src/test/java/org/sonarqube/tests/Category5Suite.java
index 63b7c1f1628..49bc73e4c44 100644
--- a/tests/src/test/java/org/sonarqube/tests/Category5Suite.java
+++ b/tests/src/test/java/org/sonarqube/tests/Category5Suite.java
@@ -21,6 +21,7 @@ package org.sonarqube.tests;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
+import org.sonarqube.tests.qualityProfile.ActiveRuleEsResilienceTest;
import org.sonarqube.tests.qualityProfile.BuiltInQualityProfilesNotificationTest;
import org.sonarqube.tests.serverSystem.ClusterTest;
import org.sonarqube.tests.serverSystem.RestartTest;
@@ -51,6 +52,7 @@ import org.sonarqube.tests.user.UserEsResilienceTest;
SsoAuthenticationTest.class,
OnboardingTest.class,
BuiltInQualityProfilesNotificationTest.class,
+ ActiveRuleEsResilienceTest.class,
UserEsResilienceTest.class
})
public class Category5Suite {
diff --git a/tests/src/test/java/org/sonarqube/tests/qualityProfile/ActiveRuleEsResilienceTest.java b/tests/src/test/java/org/sonarqube/tests/qualityProfile/ActiveRuleEsResilienceTest.java
new file mode 100644
index 00000000000..6203a647054
--- /dev/null
+++ b/tests/src/test/java/org/sonarqube/tests/qualityProfile/ActiveRuleEsResilienceTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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.qualityProfile;
+
+import com.sonar.orchestrator.Orchestrator;
+import java.io.File;
+import java.util.concurrent.TimeUnit;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.DisableOnDebug;
+import org.junit.rules.TestRule;
+import org.junit.rules.Timeout;
+import org.sonarqube.tests.Tester;
+import org.sonarqube.ws.Organizations;
+import org.sonarqube.ws.QualityProfiles;
+import org.sonarqube.ws.client.rule.SearchWsRequest;
+import util.ItUtils;
+
+import static java.lang.String.format;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ActiveRuleEsResilienceTest {
+ private static final String RULE_ONE_BUG_PER_LINE = "xoo:OneBugIssuePerLine";
+
+ @ClassRule
+ public static final Orchestrator orchestrator = Orchestrator.builderEnv()
+ .setServerProperty("sonar.web.javaAdditionalOpts",
+ format("-javaagent:%s=script:%s,boot:%s", findBytemanJar(), findBytemanScript(), findBytemanJar()))
+ .setServerProperty("sonar.search.recovery.delayInMs", "500")
+ .setServerProperty("sonar.search.recovery.minAgeInMs", "3000")
+ .addPlugin(ItUtils.xooPlugin())
+ .build();
+
+ @Rule
+ public TestRule timeout = new DisableOnDebug(Timeout.builder()
+ .withLookingForStuckThread(true)
+ .withTimeout(60L, TimeUnit.SECONDS)
+ .build());
+
+ @Rule
+ public Tester tester = new Tester(orchestrator);
+
+ @Test
+ public void activation_and_deactivation_of_rule_is_resilient_to_indexing_errors() throws Exception {
+ Organizations.Organization organization = tester.organizations().generate();
+ QualityProfiles.CreateWsResponse.QualityProfile profile = tester.qProfiles().createXooProfile(organization);
+
+ // step 1. activation
+ tester.qProfiles().activateRule(profile.getKey(), RULE_ONE_BUG_PER_LINE);
+
+ assertThat(searchActiveRules(profile)).isEqualTo(0);
+ while (searchActiveRules(profile) == 0) {
+ // rule is indexed by the recovery daemon, which runs every 3 seconds
+ Thread.sleep(500L);
+ }
+ assertThat(searchActiveRules(profile)).isEqualTo(1);
+
+ // step 2. deactivation
+ tester.qProfiles().deactivateRule(profile, RULE_ONE_BUG_PER_LINE);
+ while (searchActiveRules(profile) == 1) {
+ // rule is indexed by the recovery daemon, which runs every 3 seconds
+ Thread.sleep(500L);
+ }
+ assertThat(searchActiveRules(profile)).isEqualTo(0);
+ }
+
+ private long searchActiveRules(QualityProfiles.CreateWsResponse.QualityProfile profile) {
+ SearchWsRequest request = new SearchWsRequest().setActivation(true).setQProfile(profile.getKey());
+ return tester.wsClient().rules().search(request).getRulesCount();
+ }
+
+ private static String findBytemanJar() {
+ // see pom.xml, Maven copies and renames the artifact.
+ File jar = new File("target/byteman.jar");
+ if (!jar.exists()) {
+ throw new IllegalStateException("Can't find " + jar + ". Please execute 'mvn generate-test-resources' on integration tests once.");
+ }
+ return jar.getAbsolutePath();
+ }
+
+ private static String findBytemanScript() {
+ // see pom.xml, Maven copies and renames the artifact.
+ File script = new File("resilience/active_rule_indexer.btm");
+ if (!script.exists()) {
+ throw new IllegalStateException("Can't find " + script);
+ }
+ return script.getAbsolutePath();
+ }
+}