]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10593 SONAR-10315 support plugin uninstall before CE processing
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Thu, 19 Apr 2018 13:14:31 +0000 (15:14 +0200)
committerSonarTech <sonartech@sonarsource.com>
Thu, 10 May 2018 18:20:54 +0000 (20:20 +0200)
15 files changed:
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStep.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStepTest.java
tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/BlueGreenPlugin.java
tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/BuiltInProfilesV1.java
tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/MetricsDefinitionV1.java [new file with mode: 0644]
tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/RuleSensorV1.java [deleted file]
tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/RulesDefinitionV1.java
tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/SensorV1.java [new file with mode: 0644]
tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/BlueGreenPlugin.java
tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/BuiltInProfilesV2.java
tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/MetricsDefinitionV2.java [new file with mode: 0644]
tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/RuleSensorV2.java [deleted file]
tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/RulesDefinitionV2.java
tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/SensorV2.java [new file with mode: 0644]
tests/src/test/java/org/sonarqube/tests/serverSystem/BlueGreenTest.java

index 88bcb8fffaf46ac4f4c36460773d28a1fb79347e..3ef211cc2cbff4ab7cf94ac7a6de8dcd6c181ebd 100644 (file)
@@ -29,7 +29,6 @@ import org.apache.commons.lang.StringUtils;
 import org.sonar.api.utils.MessageException;
 import org.sonar.ce.queue.CeTask;
 import org.sonar.core.component.ComponentKeys;
-import org.sonar.core.platform.PluginInfo;
 import org.sonar.core.platform.PluginRepository;
 import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
@@ -42,13 +41,13 @@ import org.sonar.scanner.protocol.output.ScannerReport.Metadata.Plugin;
 import org.sonar.scanner.protocol.output.ScannerReport.Metadata.QProfile;
 import org.sonar.server.computation.task.projectanalysis.analysis.MutableAnalysisMetadataHolder;
 import org.sonar.server.computation.task.projectanalysis.analysis.Organization;
-import org.sonar.server.project.Project;
 import org.sonar.server.computation.task.projectanalysis.analysis.ScannerPlugin;
 import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReader;
 import org.sonar.server.computation.task.projectanalysis.component.BranchLoader;
 import org.sonar.server.computation.task.step.ComputationStep;
 import org.sonar.server.organization.DefaultOrganizationProvider;
 import org.sonar.server.organization.OrganizationFlags;
+import org.sonar.server.project.Project;
 import org.sonar.server.qualityprofile.QualityProfile;
 
 import static com.google.common.base.Preconditions.checkState;
@@ -153,13 +152,12 @@ public class LoadReportAnalysisMetadataHolderStep implements ComputationStep {
 
   @CheckForNull
   private String getBasePluginKey(Plugin p) {
-    PluginInfo pluginInfo = pluginRepository.getPluginInfo(p.getKey());
-    if (pluginInfo == null) {
+    if (!pluginRepository.hasPlugin(p.getKey())) {
       // May happen if plugin was uninstalled between start of scanner analysis and now.
       // But it doesn't matter since all active rules are removed anyway, so no issues will be reported
       return null;
     }
-    return pluginInfo.getBasePlugin();
+    return pluginRepository.getPluginInfo(p.getKey()).getBasePlugin();
   }
 
   /**
index 587d5ae5349370cd106a7018d21bc45399a597de..8a392927a17b3031c1fd883115f724c62d60f69d 100644 (file)
@@ -22,11 +22,15 @@ package org.sonar.server.computation.task.projectanalysis.step;
 import com.tngtech.java.junit.dataprovider.DataProvider;
 import com.tngtech.java.junit.dataprovider.DataProviderRunner;
 import com.tngtech.java.junit.dataprovider.UseDataProvider;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.runner.RunWith;
+import org.sonar.api.Plugin;
 import org.sonar.api.utils.MessageException;
 import org.sonar.api.utils.System2;
 import org.sonar.ce.queue.CeTask;
@@ -39,7 +43,6 @@ import org.sonar.db.organization.OrganizationDto;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.server.computation.task.projectanalysis.analysis.MutableAnalysisMetadataHolderRule;
 import org.sonar.server.computation.task.projectanalysis.analysis.Organization;
-import org.sonar.server.project.Project;
 import org.sonar.server.computation.task.projectanalysis.analysis.ScannerPlugin;
 import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReaderRule;
 import org.sonar.server.computation.task.projectanalysis.component.BranchLoader;
@@ -47,7 +50,9 @@ import org.sonar.server.computation.task.step.ComputationStep;
 import org.sonar.server.organization.DefaultOrganizationProvider;
 import org.sonar.server.organization.OrganizationFlags;
 import org.sonar.server.organization.TestDefaultOrganizationProvider;
+import org.sonar.server.project.Project;
 
+import static java.util.Arrays.stream;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.tuple;
 import static org.mockito.ArgumentMatchers.any;
@@ -71,7 +76,7 @@ public class LoadReportAnalysisMetadataHolderStepTest {
 
   private DbClient dbClient = db.getDbClient();
   private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
-  private PluginRepository pluginRepository = mock(PluginRepository.class);
+  private TestPluginRepository pluginRepository = new TestPluginRepository();
   private OrganizationFlags organizationFlags = mock(OrganizationFlags.class);
   private ComponentDto project;
   private ComputationStep underTest;
@@ -330,8 +335,8 @@ public class LoadReportAnalysisMetadataHolderStepTest {
     metadataBuilder
       .setOrganizationKey(organization1.getKey())
       .setProjectKey(projectInOrg1.getDbKey());
-    metadataBuilder.getMutableQprofilesPerLanguage().put("js", ScannerReport.Metadata.QProfile.newBuilder().setKey("jsInOrg1").setName("Sonar way").setLanguage("js").build());
-    metadataBuilder.getMutableQprofilesPerLanguage().put("php", ScannerReport.Metadata.QProfile.newBuilder().setKey("phpInOrg2").setName("PHP way").setLanguage("php").build());
+    metadataBuilder.putQprofilesPerLanguage("js", ScannerReport.Metadata.QProfile.newBuilder().setKey("jsInOrg1").setName("Sonar way").setLanguage("js").build());
+    metadataBuilder.putQprofilesPerLanguage("php", ScannerReport.Metadata.QProfile.newBuilder().setKey("phpInOrg2").setName("PHP way").setLanguage("php").build());
     reportReader.setMetadata(metadataBuilder.build());
 
     db.qualityProfiles().insert(organization1, p -> p.setLanguage("js").setKee("jsInOrg1"));
@@ -353,7 +358,7 @@ public class LoadReportAnalysisMetadataHolderStepTest {
     metadataBuilder
       .setOrganizationKey(organization.getKey())
       .setProjectKey(project.getDbKey());
-    metadataBuilder.getMutableQprofilesPerLanguage().put("js", ScannerReport.Metadata.QProfile.newBuilder().setKey("p1").setName("Sonar way").setLanguage("js").build());
+    metadataBuilder.putQprofilesPerLanguage("js", ScannerReport.Metadata.QProfile.newBuilder().setKey("p1").setName("Sonar way").setLanguage("js").build());
     reportReader.setMetadata(metadataBuilder.build());
 
     ComputationStep underTest = createStep(createCeTask(project.getDbKey(), organization.getUuid()));
@@ -363,22 +368,28 @@ public class LoadReportAnalysisMetadataHolderStepTest {
 
   @Test
   public void execute_read_plugins_from_report() {
-    ScannerReport.Metadata.Builder metadataBuilder = newBatchReportBuilder();
-    metadataBuilder.getMutablePluginsByKey().put("java", ScannerReport.Metadata.Plugin.newBuilder().setKey("java").setUpdatedAt(12345L).build());
-    metadataBuilder.getMutablePluginsByKey().put("php", ScannerReport.Metadata.Plugin.newBuilder().setKey("php").setUpdatedAt(678910L).build());
-    metadataBuilder.getMutablePluginsByKey().put("customjava", ScannerReport.Metadata.Plugin.newBuilder().setKey("customjava").setUpdatedAt(111111L).build());
-    when(pluginRepository.getPluginInfo("customjava")).thenReturn(new PluginInfo("customjava").setBasePlugin("java"));
+    // the installed plugins
+    pluginRepository.add(
+      new PluginInfo("java"),
+      new PluginInfo("customjava").setBasePlugin("java"),
+      new PluginInfo("php"));
 
+    // the plugins sent by scanner
+    ScannerReport.Metadata.Builder metadataBuilder = newBatchReportBuilder();
+    metadataBuilder.putPluginsByKey("java", ScannerReport.Metadata.Plugin.newBuilder().setKey("java").setUpdatedAt(10L).build());
+    metadataBuilder.putPluginsByKey("php", ScannerReport.Metadata.Plugin.newBuilder().setKey("php").setUpdatedAt(20L).build());
+    metadataBuilder.putPluginsByKey("customjava", ScannerReport.Metadata.Plugin.newBuilder().setKey("customjava").setUpdatedAt(30L).build());
+    metadataBuilder.putPluginsByKey("uninstalled", ScannerReport.Metadata.Plugin.newBuilder().setKey("uninstalled").setUpdatedAt(40L).build());
     reportReader.setMetadata(metadataBuilder.build());
 
     underTest.execute();
 
-    assertThat(analysisMetadataHolder.getScannerPluginsByKey()).containsOnlyKeys("java", "php", "customjava");
     assertThat(analysisMetadataHolder.getScannerPluginsByKey().values()).extracting(ScannerPlugin::getKey, ScannerPlugin::getBasePluginKey, ScannerPlugin::getUpdatedAt)
-      .containsOnly(
-        tuple("java", null, 12345L),
-        tuple("customjava", "java", 111111L),
-        tuple("php", null, 678910L));
+      .containsExactlyInAnyOrder(
+        tuple("java", null, 10L),
+        tuple("php", null, 20L),
+        tuple("customjava", "java", 30L),
+        tuple("uninstalled", null, 40L));
   }
 
   private LoadReportAnalysisMetadataHolderStep createStep(CeTask ceTask) {
@@ -398,4 +409,34 @@ public class LoadReportAnalysisMetadataHolderStepTest {
     return res;
   }
 
+  private static class TestPluginRepository implements PluginRepository {
+    private final Map<String, PluginInfo> pluginsMap = new HashMap<>();
+
+    void add(PluginInfo... plugins) {
+      stream(plugins).forEach(p -> pluginsMap.put(p.getKey(), p));
+    }
+
+    @Override
+    public Collection<PluginInfo> getPluginInfos() {
+      return pluginsMap.values();
+    }
+
+    @Override
+    public PluginInfo getPluginInfo(String key) {
+      if (!pluginsMap.containsKey(key)) {
+        throw new IllegalArgumentException();
+      }
+      return pluginsMap.get(key);
+    }
+
+    @Override
+    public Plugin getPluginInstance(String key) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean hasPlugin(String key) {
+      return pluginsMap.containsKey(key);
+    }
+  }
 }
index ea0eea80322ac11fef8c57f70205661b2f7820b0..046347e345ab0b43ce644f5441f02c904b3b7f0a 100644 (file)
@@ -27,9 +27,10 @@ public class BlueGreenPlugin implements Plugin {
   public void define(Context context) {
     context.addExtensions(
       BuiltInProfilesV1.class,
+      MetricsDefinitionV1.class,
       PageDefinitionV1.class,
       RulesDefinitionV1.class,
-      RuleSensorV1.class);
+      SensorV1.class);
   }
 
 }
index 1d19f4e5ad92d0f6fd2520b1ef8831f630a1f69c..911781faf5257d8a40b5969db7e7c9e8c2d6c526 100644 (file)
@@ -25,8 +25,12 @@ public class BuiltInProfilesV1 implements BuiltInQualityProfilesDefinition {
   @Override
   public void define(Context context) {
     NewBuiltInQualityProfile profile = context.createBuiltInQualityProfile("Blue Profile", "xoo");
-    profile.activateRule(RulesDefinitionV1.REPOSITORY_KEY, "a").overrideSeverity("BLOCKER");
-    profile.activateRule(RulesDefinitionV1.REPOSITORY_KEY, "b").overrideSeverity("CRITICAL");
+    profile.activateRule(RulesDefinitionV1.REPOSITORY_KEY, "a")
+      .overrideSeverity("BLOCKER");
+    NewBuiltInActiveRule activeB = profile.activateRule(RulesDefinitionV1.REPOSITORY_KEY, "b")
+      .overrideSeverity("CRITICAL");
+    activeB.overrideParam("p1", "one");
+    activeB.overrideParam("p2", "two");
     profile.done();
   }
 }
diff --git a/tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/MetricsDefinitionV1.java b/tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/MetricsDefinitionV1.java
new file mode 100644 (file)
index 0000000..e681d67
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.qa.bluegreen;
+
+import java.util.Arrays;
+import java.util.List;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.measures.Metrics;
+
+public class MetricsDefinitionV1 implements Metrics {
+  @Override
+  public List<Metric> getMetrics() {
+    return Arrays.asList(
+      new Metric.Builder("blue", "Blue", Metric.ValueType.INT).create(),
+      new Metric.Builder("bluegreen", "BlueGreen", Metric.ValueType.INT).create());
+  }
+}
diff --git a/tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/RuleSensorV1.java b/tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/RuleSensorV1.java
deleted file mode 100644 (file)
index 1d37782..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 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.qa.bluegreen;
-
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.sensor.Sensor;
-import org.sonar.api.batch.sensor.SensorContext;
-import org.sonar.api.batch.sensor.SensorDescriptor;
-import org.sonar.api.batch.sensor.issue.NewIssue;
-import org.sonar.api.rule.RuleKey;
-
-import static org.sonarqube.qa.bluegreen.RulesDefinitionV1.REPOSITORY_KEY;
-
-public class RuleSensorV1 implements Sensor {
-
-  @Override
-  public void describe(SensorDescriptor descriptor) {
-    descriptor.createIssuesForRuleRepositories(REPOSITORY_KEY)
-      .onlyOnLanguage("xoo")
-      .name("BlueGreen V1");
-  }
-
-  @Override
-  public void execute(SensorContext context) {
-    for (InputFile inputFile : context.fileSystem().inputFiles(context.fileSystem().predicates().hasLanguage("xoo"))) {
-      saveIssue(context, inputFile, "a");
-      saveIssue(context, inputFile, "b");
-    }
-  }
-
-  private void saveIssue(SensorContext context, InputFile inputFile, String ruleKey) {
-    NewIssue newIssue = context.newIssue();
-    newIssue.at(newIssue.newLocation().on(inputFile).at(inputFile.selectLine(1)))
-      .forRule(RuleKey.of(REPOSITORY_KEY, ruleKey))
-      .save();
-  }
-
-}
index e6fbc56bbe4513c989cab181f0c1b0d37f4e7e24..4ef3ed24c01b5ebdb33f30961881c90097c25050 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonarqube.qa.bluegreen;
 
+import org.sonar.api.rules.RuleType;
 import org.sonar.api.server.rule.RulesDefinition;
 
 public class RulesDefinitionV1 implements RulesDefinition {
@@ -28,8 +29,16 @@ public class RulesDefinitionV1 implements RulesDefinition {
   @Override
   public void define(Context context) {
     NewRepository repo = context.createRepository(REPOSITORY_KEY, "xoo").setName("BlueGreen");
-    repo.createRule("a").setName("Rule A").setHtmlDescription("Rule A");
-    repo.createRule("b").setName("Rule B").setHtmlDescription("Rule B");
+    repo.createRule("a")
+      .setName("Rule A")
+      .setHtmlDescription("Rule A")
+      .setType(RuleType.VULNERABILITY);
+    NewRule ruleB = repo.createRule("b")
+      .setName("Rule B")
+      .setHtmlDescription("Rule B")
+      .setType(RuleType.VULNERABILITY);
+    ruleB.createParam("p1").setName("Param One");
+    ruleB.createParam("p2").setName("Param Two");
     repo.done();
   }
 }
diff --git a/tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/SensorV1.java b/tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/SensorV1.java
new file mode 100644 (file)
index 0000000..35004ad
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.qa.bluegreen;
+
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.measure.MetricFinder;
+import org.sonar.api.batch.sensor.Sensor;
+import org.sonar.api.batch.sensor.SensorContext;
+import org.sonar.api.batch.sensor.SensorDescriptor;
+import org.sonar.api.batch.sensor.issue.NewIssue;
+import org.sonar.api.rule.RuleKey;
+
+import static org.sonarqube.qa.bluegreen.RulesDefinitionV1.REPOSITORY_KEY;
+
+public class SensorV1 implements Sensor {
+
+  private final MetricFinder metricFinder;
+
+  public SensorV1(MetricFinder metricFinder) {
+    this.metricFinder = metricFinder;
+  }
+
+  @Override
+  public void describe(SensorDescriptor descriptor) {
+    descriptor.createIssuesForRuleRepositories(REPOSITORY_KEY)
+      .onlyOnLanguage("xoo")
+      .name("BlueGreen V1");
+  }
+
+  @Override
+  public void execute(SensorContext context) {
+    for (InputFile inputFile : context.fileSystem().inputFiles(context.fileSystem().predicates().hasLanguage("xoo"))) {
+      saveIssue(context, inputFile, "a");
+      saveIssue(context, inputFile, "b");
+    }
+
+    context.newMeasure()
+      .forMetric(metricFinder.findByKey("blue"))
+      .on(context.module())
+      .withValue(10)
+      .save();
+    context.newMeasure()
+      .forMetric(metricFinder.findByKey("bluegreen"))
+      .on(context.module())
+      .withValue(20)
+      .save();
+  }
+
+  private void saveIssue(SensorContext context, InputFile inputFile, String ruleKey) {
+    NewIssue newIssue = context.newIssue();
+    newIssue.at(newIssue.newLocation().on(inputFile).at(inputFile.selectLine(1)))
+      .forRule(RuleKey.of(REPOSITORY_KEY, ruleKey))
+      .save();
+  }
+
+}
index 156bf7a612f5791cd60b55a194f5c816bd8f5142..e10434bf6d6d6703d5ae81918dfc3d55b4e6002d 100644 (file)
@@ -27,9 +27,10 @@ public class BlueGreenPlugin implements Plugin {
   public void define(Context context) {
     context.addExtensions(
       BuiltInProfilesV2.class,
+      MetricsDefinitionV2.class,
       PageDefinitionV2.class,
       RulesDefinitionV2.class,
-      RuleSensorV2.class);
+      SensorV2.class);
   }
 
 }
index ccb8e096010bf471f08b0655814c681dccacfa4e..42434bd0218b609d77abc5b8b0f3be5c3ae307b1 100644 (file)
@@ -25,7 +25,10 @@ public class BuiltInProfilesV2 implements BuiltInQualityProfilesDefinition {
   @Override
   public void define(Context context) {
     NewBuiltInQualityProfile profile = context.createBuiltInQualityProfile("Green Profile", "xoo");
-    profile.activateRule(RulesDefinitionV2.REPOSITORY_KEY, "b").overrideSeverity("MINOR");
+    NewBuiltInActiveRule activeB = profile.activateRule(RulesDefinitionV2.REPOSITORY_KEY, "b")
+      .overrideSeverity("MINOR");
+    activeB.overrideParam("p2", "two");
+    activeB.overrideParam("p3", "three");
     profile.activateRule(RulesDefinitionV2.REPOSITORY_KEY, "c").overrideSeverity("INFO");
     profile.done();
   }
diff --git a/tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/MetricsDefinitionV2.java b/tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/MetricsDefinitionV2.java
new file mode 100644 (file)
index 0000000..5b98a5d
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.qa.bluegreen;
+
+import java.util.Arrays;
+import java.util.List;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.measures.Metrics;
+
+public class MetricsDefinitionV2 implements Metrics {
+  @Override
+  public List<Metric> getMetrics() {
+    return Arrays.asList(
+      // the metric "blue" has been dropped
+      new Metric.Builder("bluegreen", "BlueGreen", Metric.ValueType.INT).create(),
+      new Metric.Builder("green", "Green", Metric.ValueType.INT).create());
+  }
+}
diff --git a/tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/RuleSensorV2.java b/tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/RuleSensorV2.java
deleted file mode 100644 (file)
index 5dde5dd..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 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.qa.bluegreen;
-
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.sensor.Sensor;
-import org.sonar.api.batch.sensor.SensorContext;
-import org.sonar.api.batch.sensor.SensorDescriptor;
-import org.sonar.api.batch.sensor.issue.NewIssue;
-import org.sonar.api.rule.RuleKey;
-
-import static org.sonarqube.qa.bluegreen.RulesDefinitionV2.REPOSITORY_KEY;
-
-public class RuleSensorV2 implements Sensor {
-
-  @Override
-  public void describe(SensorDescriptor descriptor) {
-    descriptor.createIssuesForRuleRepositories(REPOSITORY_KEY)
-      .onlyOnLanguage("xoo")
-      .name("BlueGreen V2");
-  }
-
-  @Override
-  public void execute(SensorContext context) {
-    for (InputFile inputFile : context.fileSystem().inputFiles(context.fileSystem().predicates().hasLanguage("xoo"))) {
-      saveIssue(context, inputFile, "b");
-      saveIssue(context, inputFile, "c");
-    }
-  }
-
-  private void saveIssue(SensorContext context, InputFile inputFile, String ruleKey) {
-    NewIssue newIssue = context.newIssue();
-    newIssue.at(newIssue.newLocation().on(inputFile).at(inputFile.selectLine(1)))
-      .forRule(RuleKey.of(REPOSITORY_KEY, ruleKey))
-      .save();
-  }
-
-}
index 3e04908a5703e7e98d8e401d7bbcb123c6a5c795..41f563a506c55850f8ceb08ff7619396c8a32360 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonarqube.qa.bluegreen;
 
+import org.sonar.api.rules.RuleType;
 import org.sonar.api.server.rule.RulesDefinition;
 
 public class RulesDefinitionV2 implements RulesDefinition {
@@ -28,8 +29,17 @@ public class RulesDefinitionV2 implements RulesDefinition {
   @Override
   public void define(Context context) {
     NewRepository repo = context.createRepository(REPOSITORY_KEY, "xoo").setName("BlueGreen");
-    repo.createRule("b").setName("Rule B").setHtmlDescription("Rule B");
-    repo.createRule("c").setName("Rule C").setHtmlDescription("Rule C");
+    NewRule ruleB = repo.createRule("b")
+      .setName("Rule B")
+      .setHtmlDescription("Rule B")
+      .setType(RuleType.VULNERABILITY);
+    ruleB.createParam("p2").setName("Param Two");
+    ruleB.createParam("p3").setName("Param Three");
+
+    repo.createRule("c")
+      .setName("Rule C")
+      .setHtmlDescription("Rule C")
+      .setType(RuleType.VULNERABILITY);
     repo.done();
   }
 }
diff --git a/tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/SensorV2.java b/tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/SensorV2.java
new file mode 100644 (file)
index 0000000..3edd3c6
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.qa.bluegreen;
+
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.measure.MetricFinder;
+import org.sonar.api.batch.sensor.Sensor;
+import org.sonar.api.batch.sensor.SensorContext;
+import org.sonar.api.batch.sensor.SensorDescriptor;
+import org.sonar.api.batch.sensor.issue.NewIssue;
+import org.sonar.api.rule.RuleKey;
+
+import static org.sonarqube.qa.bluegreen.RulesDefinitionV2.REPOSITORY_KEY;
+
+public class SensorV2 implements Sensor {
+
+  private final MetricFinder metricFinder;
+
+  public SensorV2(MetricFinder metricFinder) {
+    this.metricFinder = metricFinder;
+  }
+
+  @Override
+  public void describe(SensorDescriptor descriptor) {
+    descriptor.createIssuesForRuleRepositories(REPOSITORY_KEY)
+      .onlyOnLanguage("xoo")
+      .name("BlueGreen V2");
+  }
+
+  @Override
+  public void execute(SensorContext context) {
+    for (InputFile inputFile : context.fileSystem().inputFiles(context.fileSystem().predicates().hasLanguage("xoo"))) {
+      saveIssue(context, inputFile, "b");
+      saveIssue(context, inputFile, "c");
+    }
+
+    context.newMeasure()
+      .forMetric(metricFinder.findByKey("bluegreen"))
+      .on(context.module())
+      .withValue(30)
+      .save();
+    context.newMeasure()
+      .forMetric(metricFinder.findByKey("green"))
+      .on(context.module())
+      .withValue(40)
+      .save();
+  }
+
+  private void saveIssue(SensorContext context, InputFile inputFile, String ruleKey) {
+    NewIssue newIssue = context.newIssue();
+    newIssue.at(newIssue.newLocation().on(inputFile).at(inputFile.selectLine(1)))
+      .forRule(RuleKey.of(REPOSITORY_KEY, ruleKey))
+      .save();
+  }
+
+}
index 106a47a1e827a993e60b8d4c69210484db432a85..cc81e8e6074293d33b384c246a3d1b0d7c4c1747 100644 (file)
@@ -23,7 +23,6 @@ import com.google.common.util.concurrent.Uninterruptibles;
 import com.sonar.orchestrator.Orchestrator;
 import com.sonar.orchestrator.build.SonarScanner;
 import java.io.File;
-import java.io.IOException;
 import java.util.concurrent.TimeUnit;
 import org.apache.commons.io.FileUtils;
 import org.junit.After;
@@ -34,11 +33,12 @@ import org.junit.rules.TemporaryFolder;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 import org.sonarqube.qa.util.Tester;
-import org.sonarqube.qa.util.pageobjects.Navigation;
 import org.sonarqube.ws.Ce;
 import org.sonarqube.ws.Projects;
 import org.sonarqube.ws.client.ce.ActivityStatusRequest;
+import org.sonarqube.ws.client.plugins.UninstallRequest;
 import org.sonarqube.ws.client.qualityprofiles.AddProjectRequest;
+import util.ItUtils;
 import util.XooProjectBuilder;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -68,7 +68,7 @@ public class BlueGreenTest {
   }
 
   @Test
-  public void test_change_of_version_at_runtime() throws Exception {
+  public void upgrade_analyzer_when_analysis_is_pending_in_compute_engine_queue() throws Exception {
     orchestrator = newOrchestratorBuilder()
       .addPlugin(pluginArtifact("blue-green-plugin-v1"))
       .addPlugin(xooPlugin())
@@ -77,44 +77,50 @@ public class BlueGreenTest {
     orchestrator.start();
     tester.before();
 
-    // pause compute engine so that analysis is kept pending
-    tester.wsClient().ce().pause();
-    Projects.CreateWsResponse.Project project = tester.projects().provision();
-    associateProjectToProfile(project, "Blue Profile");
-    analyze(project);
-    assertThat(loadCeActivity().getPending()).isEqualTo(1);
+    Project project = new Project();
+    project.associateToXooProfile("Blue Profile");
+    project.analyzeAndWait();
+    // assert 2 issues + security rating E (rule A is blocker, rule B is critical)
+    assertThat(ItUtils.getMeasureAsDouble(orchestrator, project.getKey(), "violations")).isEqualTo(2.0);
+    assertThat(ItUtils.getMeasureAsDouble(orchestrator, project.getKey(), "security_rating")).isEqualTo(5.0);
+    assertThat(ItUtils.getMeasureAsDouble(orchestrator, project.getKey(), "blue")).isEqualTo(10.0);
+    assertThat(ItUtils.getMeasureAsDouble(orchestrator, project.getKey(), "bluegreen")).isEqualTo(20.0);
 
-    // open browser
-    Navigation browser = tester.openBrowser();
+    // remove rule "A" and metric "blue" between analysis and execution of Compute Engine
 
+    // 1. pause compute engine so that the second analysis is kept pending
+    tester.wsClient().ce().pause();
+    project.analyze();
+    assertThat(loadCeActivity().getPending()).isEqualTo(1);
 
-    // upgrade plugin
+    // 2. upgrade plugin and verify that analysis is still pending in CE queue
     File pluginV2 = pluginArtifact("blue-green-plugin-v2").getFile();
     FileUtils.copyFileToDirectory(pluginV2, new File(orchestrator.getServer().getHome(), "extensions/downloads"));
     orchestrator.restartServer();
-
-    // analysis task is still pending
     Ce.ActivityStatusWsResponse ceActivity = loadCeActivity();
     assertThat(ceActivity.getInProgress()).isEqualTo(0);
     assertThat(ceActivity.getPending()).isEqualTo(1);
 
+    // 3. resume the queue and verify that the issue on rule A is ignored. Only
+    // the critical issue on rule B is remaining
     resumeAndWaitForCeQueueEmpty();
+    assertThat(ItUtils.getMeasureAsDouble(orchestrator, project.getKey(), "violations")).isEqualTo(1.0);
+    assertThat(ItUtils.getMeasureAsDouble(orchestrator, project.getKey(), "security_rating")).isEqualTo(4.0);
+    assertThat(ItUtils.getMeasure(orchestrator, project.getKey(), "blue")).isNull();
+    assertThat(ItUtils.getMeasureAsDouble(orchestrator, project.getKey(), "bluegreen")).isEqualTo(20.0);
 
-    // TODO check issues and measures
-  }
-
-  private void analyze(Projects.CreateWsResponse.Project project) throws IOException {
-    File projectDir = new XooProjectBuilder(project.getKey())
-      .setFilesPerModule(1)
-      .build(temp.newFolder());
-    orchestrator.executeBuild(SonarScanner.create(projectDir), false);
-  }
+    // test removal of analyzer. Analysis should not fail when queue is resumed.
+    tester.wsClient().ce().pause();
+    project.analyze();
+    tester.wsClient().plugins().uninstall(new UninstallRequest().setKey("xoo"));
+    tester.wsClient().plugins().uninstall(new UninstallRequest().setKey("bluegreen"));
+    orchestrator.restartServer();
 
-  private void associateProjectToProfile(Projects.CreateWsResponse.Project project, String xooProfileName) {
-    tester.wsClient().qualityprofiles().addProject(new AddProjectRequest()
-      .setProject(project.getKey())
-      .setLanguage("xoo")
-      .setQualityProfile(xooProfileName));
+    resumeAndWaitForCeQueueEmpty();
+    assertThat(ItUtils.getMeasureAsDouble(orchestrator, project.getKey(), "violations")).isEqualTo(0.0);
+    assertThat(ItUtils.getMeasureAsDouble(orchestrator, project.getKey(), "security_rating")).isEqualTo(1.0);
+    assertThat(ItUtils.getMeasure(orchestrator, project.getKey(), "blue")).isNull();
+    assertThat(ItUtils.getMeasure(orchestrator, project.getKey(), "bluegreen")).isNull();
   }
 
   private void resumeAndWaitForCeQueueEmpty() {
@@ -131,4 +137,35 @@ public class BlueGreenTest {
   private Ce.ActivityStatusWsResponse loadCeActivity() {
     return tester.wsClient().ce().activityStatus(new ActivityStatusRequest());
   }
+
+  private class Project {
+    private final Projects.CreateWsResponse.Project project;
+    private final File dir;
+
+    Project() throws Exception {
+      this.project = tester.projects().provision();
+      this.dir = new XooProjectBuilder(project.getKey())
+        .setFilesPerModule(1)
+        .build(temp.newFolder());
+    }
+
+    String getKey() {
+      return project.getKey();
+    }
+
+    void associateToXooProfile(String name) {
+      tester.wsClient().qualityprofiles().addProject(new AddProjectRequest()
+        .setProject(project.getKey())
+        .setLanguage("xoo")
+        .setQualityProfile(name));
+    }
+
+    void analyzeAndWait() {
+      orchestrator.executeBuild(SonarScanner.create(dir), true);
+    }
+
+    void analyze() {
+      orchestrator.executeBuild(SonarScanner.create(dir), false);
+    }
+  }
 }