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;
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;
@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();
}
/**
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;
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;
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;
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;
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"));
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()));
@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) {
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);
+ }
+ }
}
public void define(Context context) {
context.addExtensions(
BuiltInProfilesV1.class,
+ MetricsDefinitionV1.class,
PageDefinitionV1.class,
RulesDefinitionV1.class,
- RuleSensorV1.class);
+ SensorV1.class);
}
}
@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();
}
}
--- /dev/null
+/*
+ * 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());
+ }
+}
+++ /dev/null
-/*
- * 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();
- }
-
-}
*/
package org.sonarqube.qa.bluegreen;
+import org.sonar.api.rules.RuleType;
import org.sonar.api.server.rule.RulesDefinition;
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();
}
}
--- /dev/null
+/*
+ * 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();
+ }
+
+}
public void define(Context context) {
context.addExtensions(
BuiltInProfilesV2.class,
+ MetricsDefinitionV2.class,
PageDefinitionV2.class,
RulesDefinitionV2.class,
- RuleSensorV2.class);
+ SensorV2.class);
}
}
@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();
}
--- /dev/null
+/*
+ * 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());
+ }
+}
+++ /dev/null
-/*
- * 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();
- }
-
-}
*/
package org.sonarqube.qa.bluegreen;
+import org.sonar.api.rules.RuleType;
import org.sonar.api.server.rule.RulesDefinition;
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();
}
}
--- /dev/null
+/*
+ * 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();
+ }
+
+}
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;
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;
}
@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())
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() {
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);
+ }
+ }
}