aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IssueCreationDateCalculator.java8
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IssueVisitor.java3
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactory.java14
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/IntegrateIssuesVisitorTest.java41
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactoryTest.java112
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/qualityprofile/AlwaysActiveRulesHolderImpl.java34
-rw-r--r--settings.gradle2
-rw-r--r--tests/build.gradle2
-rw-r--r--tests/plugins/blue-green-plugin-v1/build.gradle26
-rw-r--r--tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/BlueGreenPlugin.java35
-rw-r--r--tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/BuiltInProfilesV1.java33
-rw-r--r--tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/PageDefinitionV1.java32
-rw-r--r--tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/RuleSensorV1.java55
-rw-r--r--tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/RulesDefinitionV1.java35
-rw-r--r--tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/package-info.java23
-rw-r--r--tests/plugins/blue-green-plugin-v1/src/main/resources/static/global_page.js23
-rw-r--r--tests/plugins/blue-green-plugin-v2/build.gradle26
-rw-r--r--tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/BlueGreenPlugin.java35
-rw-r--r--tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/BuiltInProfilesV2.java33
-rw-r--r--tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/PageDefinitionV2.java32
-rw-r--r--tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/RuleSensorV2.java55
-rw-r--r--tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/RulesDefinitionV2.java35
-rw-r--r--tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/package-info.java23
-rw-r--r--tests/plugins/blue-green-plugin-v2/src/main/resources/static/global_page.js23
-rw-r--r--tests/plugins/blue-green-plugin/build.gradle29
-rw-r--r--tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/BlueGreenPlugin.java41
-rw-r--r--tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/BuiltInProfilesV1.java4
-rw-r--r--tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/BuiltInProfilesV2.java15
-rw-r--r--tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/RuleSensorV1.java64
-rw-r--r--tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/RuleSensorV2.java55
-rw-r--r--tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/RulesDefinitionV1.java4
-rw-r--r--tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/RulesDefinitionV2.java14
-rw-r--r--tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/package-info.java23
-rw-r--r--tests/src/test/java/org/sonarqube/tests/Category5Suite.java2
-rw-r--r--tests/src/test/java/org/sonarqube/tests/serverSystem/BlueGreenTest.java134
-rw-r--r--tests/src/test/java/util/XooProjectBuilder.java4
36 files changed, 1074 insertions, 55 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IssueCreationDateCalculator.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IssueCreationDateCalculator.java
index a43250189d3..43fab81a51e 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IssueCreationDateCalculator.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IssueCreationDateCalculator.java
@@ -90,8 +90,8 @@ public class IssueCreationDateCalculator extends IssueVisitor {
if (rule.isExternal()) {
getScmChangeDate(component, issue).ifPresent(changeDate -> updateDate(issue, changeDate));
} else {
- ActiveRule activeRule = toJavaUtilOptional(activeRulesHolder.get(issue.getRuleKey()))
- .orElseThrow(illegalStateException("The rule %s raised an issue, but is not one of the active rules.", issue.getRuleKey()));
+ // Rule can't be inactive (see contract of IssueVisitor)
+ ActiveRule activeRule = activeRulesHolder.get(issue.getRuleKey()).get();
if (firstAnalysis || activeRuleIsNew(activeRule, lastAnalysisOptional.get())
|| ruleImplementationChanged(activeRule.getRuleKey(), activeRule.getPluginKey(), lastAnalysisOptional.get())) {
getScmChangeDate(component, issue).ifPresent(changeDate -> updateDate(issue, changeDate));
@@ -182,10 +182,6 @@ public class IssueCreationDateCalculator extends IssueVisitor {
issueUpdater.setCreationDate(issue, scmDate, changeContext);
}
- private static <T> Optional<T> toJavaUtilOptional(com.google.common.base.Optional<T> scmInfo) {
- return scmInfo.transform(Optional::of).or(Optional::empty);
- }
-
private static Supplier<? extends IllegalStateException> illegalStateException(String str, Object... args) {
return () -> new IllegalStateException(String.format(str, args));
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IssueVisitor.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IssueVisitor.java
index f403d50e50a..d974dc76eea 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IssueVisitor.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IssueVisitor.java
@@ -36,6 +36,9 @@ public abstract class IssueVisitor {
* This method is called for each issue of a component when tracking is done and issue is initialized.
* That means that the following fields are set: resolution, status, line, creation date, uuid
* and all the fields merged from base issues.
+ * <br/>
+ * The related rule is active in the Quality profile. Issues on inactive rules
+ * are ignored.
*/
public void onIssue(Component component, DefaultIssue issue) {
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactory.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactory.java
index 878651b2c00..84a1cab92de 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactory.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactory.java
@@ -42,6 +42,7 @@ import org.sonar.server.computation.task.projectanalysis.component.Component;
import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolder;
import org.sonar.server.computation.task.projectanalysis.issue.commonrule.CommonRuleEngine;
import org.sonar.server.computation.task.projectanalysis.issue.filter.IssueFilter;
+import org.sonar.server.computation.task.projectanalysis.qualityprofile.ActiveRulesHolder;
import org.sonar.server.computation.task.projectanalysis.source.SourceLinesHashRepository;
import org.sonar.server.rule.CommonRuleKeys;
@@ -55,15 +56,18 @@ public class TrackerRawInputFactory {
private final IssueFilter issueFilter;
private final SourceLinesHashRepository sourceLinesHash;
private final RuleRepository ruleRepository;
+ private final ActiveRulesHolder activeRulesHolder;
public TrackerRawInputFactory(TreeRootHolder treeRootHolder, BatchReportReader reportReader,
- SourceLinesHashRepository sourceLinesHash, CommonRuleEngine commonRuleEngine, IssueFilter issueFilter, RuleRepository ruleRepository) {
+ SourceLinesHashRepository sourceLinesHash, CommonRuleEngine commonRuleEngine, IssueFilter issueFilter, RuleRepository ruleRepository,
+ ActiveRulesHolder activeRulesHolder) {
this.treeRootHolder = treeRootHolder;
this.reportReader = reportReader;
this.sourceLinesHash = sourceLinesHash;
this.commonRuleEngine = commonRuleEngine;
this.issueFilter = issueFilter;
this.ruleRepository = ruleRepository;
+ this.activeRulesHolder = activeRulesHolder;
}
public Input<DefaultIssue> create(Component component) {
@@ -100,6 +104,9 @@ public class TrackerRawInputFactory {
// as late as possible
while (reportIssues.hasNext()) {
ScannerReport.Issue reportIssue = reportIssues.next();
+ if (isOnInactiveRule(reportIssue)) {
+ continue;
+ }
if (!isIssueOnUnsupportedCommonRule(reportIssue)) {
Loggers.get(getClass()).debug("Ignored issue from analysis report on rule {}:{}", reportIssue.getRuleRepository(), reportIssue.getRuleKey());
continue;
@@ -123,6 +130,11 @@ public class TrackerRawInputFactory {
return result;
}
+ private boolean isOnInactiveRule(ScannerReport.Issue reportIssue) {
+ RuleKey ruleKey = RuleKey.of(reportIssue.getRuleRepository(), reportIssue.getRuleKey());
+ return !activeRulesHolder.get(ruleKey).isPresent();
+ }
+
private boolean isIssueOnUnsupportedCommonRule(ScannerReport.Issue issue) {
// issues on batch common rules are ignored. This feature
// is natively supported by compute engine since 5.2.
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/IntegrateIssuesVisitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/IntegrateIssuesVisitorTest.java
index 085820dae94..a19a9a940f2 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/IntegrateIssuesVisitorTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/IntegrateIssuesVisitorTest.java
@@ -53,8 +53,10 @@ import org.sonar.server.computation.task.projectanalysis.component.TypeAwareVisi
import org.sonar.server.computation.task.projectanalysis.filemove.MovedFilesRepository;
import org.sonar.server.computation.task.projectanalysis.issue.commonrule.CommonRuleEngineImpl;
import org.sonar.server.computation.task.projectanalysis.issue.filter.IssueFilter;
+import org.sonar.server.computation.task.projectanalysis.qualityprofile.ActiveRulesHolder;
import org.sonar.server.computation.task.projectanalysis.qualityprofile.ActiveRulesHolderRule;
import org.sonar.server.computation.task.projectanalysis.source.SourceLinesHashRepository;
+import org.sonar.server.computation.task.projectanalysis.qualityprofile.AlwaysActiveRulesHolderImpl;
import org.sonar.server.computation.task.projectanalysis.source.SourceLinesRepositoryRule;
import static com.google.common.collect.Lists.newArrayList;
@@ -69,21 +71,21 @@ import static org.sonar.server.computation.task.projectanalysis.component.Report
public class IntegrateIssuesVisitorTest {
- static final String FILE_UUID = "FILE_UUID";
- static final String FILE_UUID_ON_BRANCH = "FILE_UUID_BRANCH";
- static final String FILE_KEY = "FILE_KEY";
- static final int FILE_REF = 2;
+ private static final String FILE_UUID = "FILE_UUID";
+ private static final String FILE_UUID_ON_BRANCH = "FILE_UUID_BRANCH";
+ private static final String FILE_KEY = "FILE_KEY";
+ private static final int FILE_REF = 2;
- static final Component FILE = builder(Component.Type.FILE, FILE_REF)
+ private static final Component FILE = builder(Component.Type.FILE, FILE_REF)
.setKey(FILE_KEY)
.setUuid(FILE_UUID)
.build();
- static final String PROJECT_KEY = "PROJECT_KEY";
- static final String PROJECT_UUID = "PROJECT_UUID";
- static final String PROJECT_UUID_ON_BRANCH = "PROJECT_UUID_BRANCH";
- static final int PROJECT_REF = 1;
- static final Component PROJECT = builder(Component.Type.PROJECT, PROJECT_REF)
+ private static final String PROJECT_KEY = "PROJECT_KEY";
+ private static final String PROJECT_UUID = "PROJECT_UUID";
+ private static final String PROJECT_UUID_ON_BRANCH = "PROJECT_UUID_BRANCH";
+ private static final int PROJECT_REF = 1;
+ private static final Component PROJECT = builder(Component.Type.PROJECT, PROJECT_REF)
.setKey(PROJECT_KEY)
.setUuid(PROJECT_UUID)
.addChildren(FILE)
@@ -116,16 +118,17 @@ public class IntegrateIssuesVisitorTest {
private MergeBranchComponentUuids mergeBranchComponentUuids = mock(MergeBranchComponentUuids.class);
private SourceLinesHashRepository sourceLinesHash = mock(SourceLinesHashRepository.class);
- ArgumentCaptor<DefaultIssue> defaultIssueCaptor;
+ private ArgumentCaptor<DefaultIssue> defaultIssueCaptor;
- ComponentIssuesLoader issuesLoader = new ComponentIssuesLoader(dbTester.getDbClient(), ruleRepositoryRule, activeRulesHolderRule);
- IssueTrackingDelegator trackingDelegator;
- TrackerExecution tracker;
- ShortBranchTrackerExecution shortBranchTracker;
- MergeBranchTrackerExecution mergeBranchTracker;
- IssueCache issueCache;
+ private ComponentIssuesLoader issuesLoader = new ComponentIssuesLoader(dbTester.getDbClient(), ruleRepositoryRule, activeRulesHolderRule);
+ private IssueTrackingDelegator trackingDelegator;
+ private TrackerExecution tracker;
+ private ShortBranchTrackerExecution shortBranchTracker;
+ private MergeBranchTrackerExecution mergeBranchTracker;
+ private ActiveRulesHolder activeRulesHolder = new AlwaysActiveRulesHolderImpl();
+ private IssueCache issueCache;
- TypeAwareVisitor underTest;
+ private TypeAwareVisitor underTest;
@Before
public void setUp() throws Exception {
@@ -134,7 +137,7 @@ public class IntegrateIssuesVisitorTest {
defaultIssueCaptor = ArgumentCaptor.forClass(DefaultIssue.class);
when(movedFilesRepository.getOriginalFile(any(Component.class))).thenReturn(Optional.absent());
- TrackerRawInputFactory rawInputFactory = new TrackerRawInputFactory(treeRootHolder, reportReader, sourceLinesHash, new CommonRuleEngineImpl(), issueFilter, ruleRepository);
+ TrackerRawInputFactory rawInputFactory = new TrackerRawInputFactory(treeRootHolder, reportReader, sourceLinesHash, new CommonRuleEngineImpl(), issueFilter, ruleRepository, activeRulesHolder);
TrackerBaseInputFactory baseInputFactory = new TrackerBaseInputFactory(issuesLoader, dbTester.getDbClient(), movedFilesRepository);
TrackerMergeBranchInputFactory mergeInputFactory = new TrackerMergeBranchInputFactory(issuesLoader, mergeBranchComponentsUuids, dbTester.getDbClient());
tracker = new TrackerExecution(baseInputFactory, rawInputFactory, new Tracker<>());
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactoryTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactoryTest.java
index e04d2981788..3da31e3a7c2 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactoryTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactoryTest.java
@@ -39,10 +39,14 @@ import org.sonar.server.computation.task.projectanalysis.component.ReportCompone
import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
import org.sonar.server.computation.task.projectanalysis.issue.commonrule.CommonRuleEngine;
import org.sonar.server.computation.task.projectanalysis.issue.filter.IssueFilter;
+import org.sonar.server.computation.task.projectanalysis.qualityprofile.ActiveRule;
+import org.sonar.server.computation.task.projectanalysis.qualityprofile.ActiveRulesHolderRule;
import org.sonar.server.computation.task.projectanalysis.source.SourceLinesHashRepository;
import org.sonar.server.rule.CommonRuleKeys;
import static java.util.Arrays.asList;
+import static java.util.Collections.emptyMap;
+import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
@@ -58,17 +62,18 @@ public class TrackerRawInputFactoryTest {
@Rule
public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule().setRoot(PROJECT);
-
@Rule
public BatchReportReaderRule reportReader = new BatchReportReaderRule();
-
+ @Rule
+ public ActiveRulesHolderRule activeRulesHolder = new ActiveRulesHolderRule();
@Rule
public RuleRepositoryRule ruleRepository = new RuleRepositoryRule();
- SourceLinesHashRepository sourceLinesHash = mock(SourceLinesHashRepository.class);
- CommonRuleEngine commonRuleEngine = mock(CommonRuleEngine.class);
- IssueFilter issueFilter = mock(IssueFilter.class);
- TrackerRawInputFactory underTest = new TrackerRawInputFactory(treeRootHolder, reportReader, sourceLinesHash, commonRuleEngine, issueFilter, ruleRepository);
+ private SourceLinesHashRepository sourceLinesHash = mock(SourceLinesHashRepository.class);
+ private CommonRuleEngine commonRuleEngine = mock(CommonRuleEngine.class);
+ private IssueFilter issueFilter = mock(IssueFilter.class);
+ private TrackerRawInputFactory underTest = new TrackerRawInputFactory(treeRootHolder, reportReader, sourceLinesHash,
+ commonRuleEngine, issueFilter, ruleRepository, activeRulesHolder);
@Test
public void load_source_hash_sequences() {
@@ -93,17 +98,20 @@ public class TrackerRawInputFactoryTest {
@Test
public void load_issues_from_report() {
- when(issueFilter.accept(any(DefaultIssue.class), eq(FILE))).thenReturn(true);
+ RuleKey ruleKey = RuleKey.of("java", "S001");
+ markRuleAsActive(ruleKey);
+ when(issueFilter.accept(any(), eq(FILE))).thenReturn(true);
+
when(sourceLinesHash.getLineHashesMatchingDBVersion(FILE)).thenReturn(Collections.singletonList("line"));
ScannerReport.Issue reportIssue = ScannerReport.Issue.newBuilder()
.setTextRange(TextRange.newBuilder().setStartLine(2).build())
.setMsg("the message")
- .setRuleRepository("java")
- .setRuleKey("S001")
+ .setRuleRepository(ruleKey.repository())
+ .setRuleKey(ruleKey.rule())
.setSeverity(Constants.Severity.BLOCKER)
.setGap(3.14)
.build();
- reportReader.putIssues(FILE.getReportAttributes().getRef(), asList(reportIssue));
+ reportReader.putIssues(FILE.getReportAttributes().getRef(), singletonList(reportIssue));
Input<DefaultIssue> input = underTest.create(FILE);
Collection<DefaultIssue> issues = input.getIssues();
@@ -111,7 +119,7 @@ public class TrackerRawInputFactoryTest {
DefaultIssue issue = Iterators.getOnlyElement(issues.iterator());
// fields set by analysis report
- assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("java", "S001"));
+ assertThat(issue.ruleKey()).isEqualTo(ruleKey);
assertThat(issue.severity()).isEqualTo(Severity.BLOCKER);
assertThat(issue.line()).isEqualTo(2);
assertThat(issue.effortToFix()).isEqualTo(3.14);
@@ -153,7 +161,7 @@ public class TrackerRawInputFactoryTest {
// fields set by compute engine
assertThat(issue.checksum()).isEqualTo(input.getLineHashSequence().getHashForLine(2));
assertThat(issue.tags()).isEmpty();
- assertInitializedIssue(issue);
+ assertInitializedExternalIssue(issue);
}
@Test
@@ -183,22 +191,24 @@ public class TrackerRawInputFactoryTest {
// fields set by compute engine
assertThat(issue.checksum()).isEqualTo(input.getLineHashSequence().getHashForLine(2));
assertThat(issue.tags()).isEmpty();
- assertInitializedIssue(issue);
+ assertInitializedExternalIssue(issue);
}
@Test
- public void ignore_issue_from_report() {
- when(issueFilter.accept(any(DefaultIssue.class), eq(FILE))).thenReturn(false);
+ public void excludes_issues_on_inactive_rules() {
+ RuleKey ruleKey = RuleKey.of("java", "S001");
+ when(issueFilter.accept(any(), eq(FILE))).thenReturn(true);
+
when(sourceLinesHash.getLineHashesMatchingDBVersion(FILE)).thenReturn(Collections.singletonList("line"));
ScannerReport.Issue reportIssue = ScannerReport.Issue.newBuilder()
.setTextRange(TextRange.newBuilder().setStartLine(2).build())
.setMsg("the message")
- .setRuleRepository("java")
- .setRuleKey("S001")
+ .setRuleRepository(ruleKey.repository())
+ .setRuleKey(ruleKey.rule())
.setSeverity(Constants.Severity.BLOCKER)
.setGap(3.14)
.build();
- reportReader.putIssues(FILE.getReportAttributes().getRef(), asList(reportIssue));
+ reportReader.putIssues(FILE.getReportAttributes().getRef(), singletonList(reportIssue));
Input<DefaultIssue> input = underTest.create(FILE);
Collection<DefaultIssue> issues = input.getIssues();
@@ -206,15 +216,38 @@ public class TrackerRawInputFactoryTest {
}
@Test
- public void ignore_report_issues_on_common_rules() {
+ public void filter_excludes_issues_from_report() {
+ RuleKey ruleKey = RuleKey.of("java", "S001");
+ markRuleAsActive(ruleKey);
+ when(issueFilter.accept(any(), eq(FILE))).thenReturn(false);
when(sourceLinesHash.getLineHashesMatchingDBVersion(FILE)).thenReturn(Collections.singletonList("line"));
ScannerReport.Issue reportIssue = ScannerReport.Issue.newBuilder()
+ .setTextRange(TextRange.newBuilder().setStartLine(2).build())
.setMsg("the message")
- .setRuleRepository(CommonRuleKeys.commonRepositoryForLang("java"))
- .setRuleKey("S001")
+ .setRuleRepository(ruleKey.repository())
+ .setRuleKey(ruleKey.rule())
+ .setSeverity(Constants.Severity.BLOCKER)
+ .setGap(3.14)
+ .build();
+ reportReader.putIssues(FILE.getReportAttributes().getRef(), singletonList(reportIssue));
+ Input<DefaultIssue> input = underTest.create(FILE);
+
+ Collection<DefaultIssue> issues = input.getIssues();
+ assertThat(issues).isEmpty();
+ }
+
+ @Test
+ public void exclude_issues_on_common_rules() {
+ RuleKey ruleKey = RuleKey.of(CommonRuleKeys.commonRepositoryForLang("java"), "S001");
+ markRuleAsActive(ruleKey);
+ when(sourceLinesHash.getLineHashesMatchingDBVersion(FILE)).thenReturn(Collections.singletonList("line"));
+ ScannerReport.Issue reportIssue = ScannerReport.Issue.newBuilder()
+ .setMsg("the message")
+ .setRuleRepository(ruleKey.repository())
+ .setRuleKey(ruleKey.rule())
.setSeverity(Constants.Severity.BLOCKER)
.build();
- reportReader.putIssues(FILE.getReportAttributes().getRef(), asList(reportIssue));
+ reportReader.putIssues(FILE.getReportAttributes().getRef(), singletonList(reportIssue));
Input<DefaultIssue> input = underTest.create(FILE);
@@ -223,13 +256,15 @@ public class TrackerRawInputFactoryTest {
@Test
public void load_issues_of_compute_engine_common_rules() {
- when(issueFilter.accept(any(DefaultIssue.class), eq(FILE))).thenReturn(true);
+ RuleKey ruleKey = RuleKey.of(CommonRuleKeys.commonRepositoryForLang("java"), "InsufficientCoverage");
+ markRuleAsActive(ruleKey);
+ when(issueFilter.accept(any(), eq(FILE))).thenReturn(true);
when(sourceLinesHash.getLineHashesMatchingDBVersion(FILE)).thenReturn(Collections.singletonList("line"));
DefaultIssue ceIssue = new DefaultIssue()
- .setRuleKey(RuleKey.of(CommonRuleKeys.commonRepositoryForLang("java"), "InsufficientCoverage"))
+ .setRuleKey(ruleKey)
.setMessage("not enough coverage")
.setGap(10.0);
- when(commonRuleEngine.process(FILE)).thenReturn(asList(ceIssue));
+ when(commonRuleEngine.process(FILE)).thenReturn(singletonList(ceIssue));
Input<DefaultIssue> input = underTest.create(FILE);
@@ -238,14 +273,16 @@ public class TrackerRawInputFactoryTest {
}
@Test
- public void ignore_issue_from_common_rule() {
- when(issueFilter.accept(any(DefaultIssue.class), eq(FILE))).thenReturn(false);
+ public void filter_exclude_issues_on_common_rule() {
+ RuleKey ruleKey = RuleKey.of(CommonRuleKeys.commonRepositoryForLang("java"), "InsufficientCoverage");
+ markRuleAsActive(ruleKey);
+ when(issueFilter.accept(any(), eq(FILE))).thenReturn(false);
when(sourceLinesHash.getLineHashesMatchingDBVersion(FILE)).thenReturn(Collections.singletonList("line"));
DefaultIssue ceIssue = new DefaultIssue()
- .setRuleKey(RuleKey.of(CommonRuleKeys.commonRepositoryForLang("java"), "InsufficientCoverage"))
+ .setRuleKey(ruleKey)
.setMessage("not enough coverage")
.setGap(10.0);
- when(commonRuleEngine.process(FILE)).thenReturn(asList(ceIssue));
+ when(commonRuleEngine.process(FILE)).thenReturn(singletonList(ceIssue));
Input<DefaultIssue> input = underTest.create(FILE);
@@ -260,5 +297,22 @@ public class TrackerRawInputFactoryTest {
assertThat(issue.status()).isEqualTo(Issue.STATUS_OPEN);
assertThat(issue.key()).isNull();
assertThat(issue.authorLogin()).isNull();
+ assertThat(issue.effort()).isNull();
+ assertThat(issue.effortInMinutes()).isNull();
+ assertThat(issue.debt()).isNull();
+ }
+
+ private void assertInitializedExternalIssue(DefaultIssue issue) {
+ assertThat(issue.projectKey()).isEqualTo(PROJECT.getPublicKey());
+ assertThat(issue.componentKey()).isEqualTo(FILE.getPublicKey());
+ assertThat(issue.componentUuid()).isEqualTo(FILE.getUuid());
+ assertThat(issue.resolution()).isNull();
+ assertThat(issue.status()).isEqualTo(Issue.STATUS_OPEN);
+ assertThat(issue.key()).isNull();
+ assertThat(issue.authorLogin()).isNull();
+ }
+
+ private void markRuleAsActive(RuleKey ruleKey) {
+ activeRulesHolder.put(new ActiveRule(ruleKey, Severity.CRITICAL, emptyMap(), 1_000L, null));
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/qualityprofile/AlwaysActiveRulesHolderImpl.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/qualityprofile/AlwaysActiveRulesHolderImpl.java
new file mode 100644
index 00000000000..088138a8c53
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/qualityprofile/AlwaysActiveRulesHolderImpl.java
@@ -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.sonar.server.computation.task.projectanalysis.qualityprofile;
+
+import com.google.common.base.Optional;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.Severity;
+
+import static java.util.Collections.emptyMap;
+
+public class AlwaysActiveRulesHolderImpl implements ActiveRulesHolder {
+ @Override
+ public Optional<ActiveRule> get(RuleKey ruleKey) {
+ return Optional.of(new ActiveRule(ruleKey, Severity.MAJOR, emptyMap(), 1_000L, null));
+ }
+
+}
diff --git a/settings.gradle b/settings.gradle
index a3f0c94d685..bc05b4e8080 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -36,6 +36,8 @@ include 'tests:plugins:backdating-plugin-v1'
include 'tests:plugins:backdating-plugin-v2'
include 'tests:plugins:base-auth-plugin'
include 'tests:plugins:batch-plugin'
+include 'tests:plugins:blue-green-plugin-v1'
+include 'tests:plugins:blue-green-plugin-v2'
include 'tests:plugins:extension-lifecycle-plugin'
include 'tests:plugins:fake-billing-plugin'
include 'tests:plugins:fake-governance-plugin'
diff --git a/tests/build.gradle b/tests/build.gradle
index 8164dfebb19..1d9605e8593 100644
--- a/tests/build.gradle
+++ b/tests/build.gradle
@@ -16,6 +16,8 @@ def pluginsForITs = [
':tests:plugins:backdating-customplugin',
':tests:plugins:base-auth-plugin',
':tests:plugins:batch-plugin',
+ ':tests:plugins:blue-green-plugin-v1',
+ ':tests:plugins:blue-green-plugin-v2',
':tests:plugins:extension-lifecycle-plugin',
':tests:plugins:fake-billing-plugin',
':tests:plugins:fake-governance-plugin',
diff --git a/tests/plugins/blue-green-plugin-v1/build.gradle b/tests/plugins/blue-green-plugin-v1/build.gradle
new file mode 100644
index 00000000000..e2fef432b88
--- /dev/null
+++ b/tests/plugins/blue-green-plugin-v1/build.gradle
@@ -0,0 +1,26 @@
+sonarqube {
+ skipProject = true
+}
+
+dependencies {
+ compileOnly 'com.google.code.findbugs:jsr305'
+ compileOnly project(path: ':sonar-plugin-api', configuration: 'shadow')
+}
+
+jar {
+ manifest {
+ attributes(
+ 'Plugin-Key': 'bluegreen',
+ 'Plugin-Version': '1.0',
+ 'Plugin-Class': 'org.sonarqube.qa.bluegreen.BlueGreenPlugin',
+ 'Plugin-ChildFirstClassLoader': 'false',
+ 'Sonar-Version': version,
+ 'SonarLint-Supported': 'false',
+ 'Plugin-Name': 'BlueGreen',
+ 'Plugin-License': 'GNU LGPL 3'
+ )
+ }
+ into('META-INF/lib') {
+ from configurations.compile
+ }
+}
diff --git a/tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/BlueGreenPlugin.java b/tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/BlueGreenPlugin.java
new file mode 100644
index 00000000000..ea0eea80322
--- /dev/null
+++ b/tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/BlueGreenPlugin.java
@@ -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 org.sonar.api.Plugin;
+
+public class BlueGreenPlugin implements Plugin {
+
+ @Override
+ public void define(Context context) {
+ context.addExtensions(
+ BuiltInProfilesV1.class,
+ PageDefinitionV1.class,
+ RulesDefinitionV1.class,
+ RuleSensorV1.class);
+ }
+
+}
diff --git a/tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/BuiltInProfilesV1.java b/tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/BuiltInProfilesV1.java
new file mode 100644
index 00000000000..1d19f4e5ad9
--- /dev/null
+++ b/tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/BuiltInProfilesV1.java
@@ -0,0 +1,33 @@
+/*
+ * 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.server.profile.BuiltInQualityProfilesDefinition;
+
+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.done();
+ }
+}
+
diff --git a/tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/PageDefinitionV1.java b/tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/PageDefinitionV1.java
new file mode 100644
index 00000000000..d7cb207aa41
--- /dev/null
+++ b/tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/PageDefinitionV1.java
@@ -0,0 +1,32 @@
+/*
+ * 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.web.page.Context;
+import org.sonar.api.web.page.Page;
+import org.sonar.api.web.page.PageDefinition;
+
+public class PageDefinitionV1 implements PageDefinition {
+ @Override
+ public void define(Context context) {
+ context
+ .addPage(Page.builder("bluegreen/global_page").setName("Blue Green Page").build());
+ }
+}
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
new file mode 100644
index 00000000000..1d377825a3f
--- /dev/null
+++ b/tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/RuleSensorV1.java
@@ -0,0 +1,55 @@
+/*
+ * 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();
+ }
+
+}
diff --git a/tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/RulesDefinitionV1.java b/tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/RulesDefinitionV1.java
new file mode 100644
index 00000000000..e6fbc56bbe4
--- /dev/null
+++ b/tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/RulesDefinitionV1.java
@@ -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 org.sonar.api.server.rule.RulesDefinition;
+
+public class RulesDefinitionV1 implements RulesDefinition {
+
+ public static final String REPOSITORY_KEY = "bluegreen";
+
+ @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.done();
+ }
+}
diff --git a/tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/package-info.java b/tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/package-info.java
new file mode 100644
index 00000000000..86d3578aa72
--- /dev/null
+++ b/tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+@ParametersAreNonnullByDefault
+package org.sonarqube.qa.bluegreen;
+
+import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/tests/plugins/blue-green-plugin-v1/src/main/resources/static/global_page.js b/tests/plugins/blue-green-plugin-v1/src/main/resources/static/global_page.js
new file mode 100644
index 00000000000..257440f340b
--- /dev/null
+++ b/tests/plugins/blue-green-plugin-v1/src/main/resources/static/global_page.js
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+window.registerExtension('bluegreen/global_page', function (options) {
+ options.el.textContent = 'BLUE';
+ return function () {};
+});
diff --git a/tests/plugins/blue-green-plugin-v2/build.gradle b/tests/plugins/blue-green-plugin-v2/build.gradle
new file mode 100644
index 00000000000..0730c13d390
--- /dev/null
+++ b/tests/plugins/blue-green-plugin-v2/build.gradle
@@ -0,0 +1,26 @@
+sonarqube {
+ skipProject = true
+}
+
+dependencies {
+ compileOnly 'com.google.code.findbugs:jsr305'
+ compileOnly project(path: ':sonar-plugin-api', configuration: 'shadow')
+}
+
+jar {
+ manifest {
+ attributes(
+ 'Plugin-Key': 'bluegreen',
+ 'Plugin-Version': '2.0',
+ 'Plugin-Class': 'org.sonarqube.qa.bluegreen.BlueGreenPlugin',
+ 'Plugin-ChildFirstClassLoader': 'false',
+ 'Sonar-Version': version,
+ 'SonarLint-Supported': 'false',
+ 'Plugin-Name': 'BlueGreen',
+ 'Plugin-License': 'GNU LGPL 3'
+ )
+ }
+ into('META-INF/lib') {
+ from configurations.compile
+ }
+}
diff --git a/tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/BlueGreenPlugin.java b/tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/BlueGreenPlugin.java
new file mode 100644
index 00000000000..156bf7a612f
--- /dev/null
+++ b/tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/BlueGreenPlugin.java
@@ -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 org.sonar.api.Plugin;
+
+public class BlueGreenPlugin implements Plugin {
+
+ @Override
+ public void define(Context context) {
+ context.addExtensions(
+ BuiltInProfilesV2.class,
+ PageDefinitionV2.class,
+ RulesDefinitionV2.class,
+ RuleSensorV2.class);
+ }
+
+}
diff --git a/tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/BuiltInProfilesV2.java b/tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/BuiltInProfilesV2.java
new file mode 100644
index 00000000000..ccb8e096010
--- /dev/null
+++ b/tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/BuiltInProfilesV2.java
@@ -0,0 +1,33 @@
+/*
+ * 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.server.profile.BuiltInQualityProfilesDefinition;
+
+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");
+ 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/PageDefinitionV2.java b/tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/PageDefinitionV2.java
new file mode 100644
index 00000000000..d9d64100abb
--- /dev/null
+++ b/tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/PageDefinitionV2.java
@@ -0,0 +1,32 @@
+/*
+ * 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.web.page.Context;
+import org.sonar.api.web.page.Page;
+import org.sonar.api.web.page.PageDefinition;
+
+public class PageDefinitionV2 implements PageDefinition {
+ @Override
+ public void define(Context context) {
+ context
+ .addPage(Page.builder("bluegreen/global_page").setName("Blue Green Page").build());
+ }
+}
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
new file mode 100644
index 00000000000..5dde5ddd1b2
--- /dev/null
+++ b/tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/RuleSensorV2.java
@@ -0,0 +1,55 @@
+/*
+ * 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();
+ }
+
+}
diff --git a/tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/RulesDefinitionV2.java b/tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/RulesDefinitionV2.java
new file mode 100644
index 00000000000..3e04908a570
--- /dev/null
+++ b/tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/RulesDefinitionV2.java
@@ -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 org.sonar.api.server.rule.RulesDefinition;
+
+public class RulesDefinitionV2 implements RulesDefinition {
+
+ public static final String REPOSITORY_KEY = "bluegreen";
+
+ @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");
+ repo.done();
+ }
+}
diff --git a/tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/package-info.java b/tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/package-info.java
new file mode 100644
index 00000000000..86d3578aa72
--- /dev/null
+++ b/tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+@ParametersAreNonnullByDefault
+package org.sonarqube.qa.bluegreen;
+
+import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/tests/plugins/blue-green-plugin-v2/src/main/resources/static/global_page.js b/tests/plugins/blue-green-plugin-v2/src/main/resources/static/global_page.js
new file mode 100644
index 00000000000..2bf90efe4ed
--- /dev/null
+++ b/tests/plugins/blue-green-plugin-v2/src/main/resources/static/global_page.js
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+window.registerExtension('bluegreen/global_page', function (options) {
+ options.el.textContent = 'GREEN';
+ return function () {};
+});
diff --git a/tests/plugins/blue-green-plugin/build.gradle b/tests/plugins/blue-green-plugin/build.gradle
new file mode 100644
index 00000000000..833f88f3230
--- /dev/null
+++ b/tests/plugins/blue-green-plugin/build.gradle
@@ -0,0 +1,29 @@
+sonarqube {
+ skipProject = true
+}
+
+dependencies {
+ compile 'com.google.guava:guava'
+ compile 'commons-io:commons-io'
+ compile 'commons-lang:commons-lang'
+ compileOnly 'com.google.code.findbugs:jsr305'
+ compileOnly project(path: ':sonar-plugin-api', configuration: 'shadow')
+}
+
+jar {
+ manifest {
+ attributes(
+ 'Plugin-Key': 'bluegreen',
+ 'Plugin-Version': version,
+ 'Plugin-Class': 'org.sonarqube.qa.bluegreen',
+ 'Plugin-ChildFirstClassLoader': 'false',
+ 'Sonar-Version': version,
+ 'SonarLint-Supported': 'false',
+ 'Plugin-Name': 'Foo',
+ 'Plugin-License': 'GNU LGPL 3'
+ )
+ }
+ into('META-INF/lib') {
+ from configurations.compile
+ }
+}
diff --git a/tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/BlueGreenPlugin.java b/tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/BlueGreenPlugin.java
new file mode 100644
index 00000000000..f4ec4e56925
--- /dev/null
+++ b/tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/BlueGreenPlugin.java
@@ -0,0 +1,41 @@
+/*
+ * 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.Optional;
+import org.sonar.api.Plugin;
+
+public class BlueGreenPlugin implements Plugin {
+
+ @Override
+ public void define(Context context) {
+ Optional<String> version = context.getBootConfiguration().get("bluegreenplugin.version");
+ if (version.isPresent()) {
+ if (version.get().equals("1")) {
+ context.addExtension(RulesDefinitionV1.class);
+
+ } else if (version.get().equals("2")) {
+ context.addExtension(RulesDefinitionV2.class);
+
+ }
+ }
+ }
+
+}
diff --git a/tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/BuiltInProfilesV1.java b/tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/BuiltInProfilesV1.java
new file mode 100644
index 00000000000..79e14e0f947
--- /dev/null
+++ b/tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/BuiltInProfilesV1.java
@@ -0,0 +1,4 @@
+package org.sonarqube.qa.bluegreen;
+
+public class BuiltInProfileV1 {
+}
diff --git a/tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/BuiltInProfilesV2.java b/tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/BuiltInProfilesV2.java
new file mode 100644
index 00000000000..131f1711d47
--- /dev/null
+++ b/tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/BuiltInProfilesV2.java
@@ -0,0 +1,15 @@
+package org.sonarqube.qa.bluegreen;
+
+import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
+
+public class BuiltInProfilesV2 implements BuiltInQualityProfilesDefinition {
+ @Override
+ public void define(Context context) {
+ NewBuiltInQualityProfile profile = context.createBuiltInQualityProfile("Profile One", "xoo");
+ profile.setDefault(true);
+ profile.activateRule(RulesDefinitionV1.REPOSITORY_KEY, "a").overrideSeverity("BLOCKER");
+ profile.activateRule(RulesDefinitionV1.REPOSITORY_KEY, "b").overrideSeverity("CRITICAL");
+ profile.done();
+ }
+}
+
diff --git a/tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/RuleSensorV1.java b/tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/RuleSensorV1.java
new file mode 100644
index 00000000000..9ecea9bf5c2
--- /dev/null
+++ b/tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/RuleSensorV1.java
@@ -0,0 +1,64 @@
+/*
+ * 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.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+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 org.sonar.plugins.backdating.rule.BackRulesDefinition;
+
+public class RuleSensorV1 implements Sensor {
+
+ @Override
+ public void describe(SensorDescriptor descriptor) {
+ descriptor.createIssuesForRuleRepositories(BackRulesDefinition.BACK_REPOSITORY)
+ .onlyOnLanguage("xoo")
+ .name("Back V1");
+ }
+
+ @Override
+ public void execute(SensorContext context) {
+ for (InputFile inputFile : context.fileSystem().inputFiles(context.fileSystem().predicates().hasLanguage("xoo"))) {
+ int lineNb = 0;
+ try {
+ BufferedReader reader = new BufferedReader(new StringReader(inputFile.contents()));
+ String line;
+ while ((line = reader.readLine()) != null) {
+ lineNb++;
+ if (line.contains("BACKV1")) {
+ NewIssue newIssue = context.newIssue();
+ newIssue.at(newIssue.newLocation().on(inputFile).at(inputFile.selectLine(lineNb)))
+ .forRule(RuleKey.of(BackRulesDefinition.BACK_REPOSITORY, BackRulesDefinition.RULE_KEY))
+ .save();
+ }
+ }
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+
+}
diff --git a/tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/RuleSensorV2.java b/tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/RuleSensorV2.java
new file mode 100644
index 00000000000..d3c18d64cb2
--- /dev/null
+++ b/tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/RuleSensorV2.java
@@ -0,0 +1,55 @@
+/*
+ * 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 RuleSensorV2 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();
+ }
+
+}
diff --git a/tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/RulesDefinitionV1.java b/tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/RulesDefinitionV1.java
new file mode 100644
index 00000000000..af58aeb2f0d
--- /dev/null
+++ b/tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/RulesDefinitionV1.java
@@ -0,0 +1,4 @@
+package org.sonarqube.qa.bluegreen;
+
+public class RulesDefinitionV1 {
+}
diff --git a/tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/RulesDefinitionV2.java b/tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/RulesDefinitionV2.java
new file mode 100644
index 00000000000..8b39095b356
--- /dev/null
+++ b/tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/RulesDefinitionV2.java
@@ -0,0 +1,14 @@
+package org.sonarqube.qa.bluegreen;
+
+import org.sonar.api.server.rule.RulesDefinition;
+
+public class RulesDefinitionV2 implements RulesDefinition {
+
+ @Override
+ public void define(Context context) {
+ NewRepository repo = context.createRepository("bluegreen", "xoo").setName("BlueGreen");
+ repo.createRule("a").setName("Rule A").setHtmlDescription("Rule A");
+ repo.createRule("b").setName("Rule B").setHtmlDescription("Rule B");
+ repo.done();
+ }
+}
diff --git a/tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/package-info.java b/tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/package-info.java
new file mode 100644
index 00000000000..86d3578aa72
--- /dev/null
+++ b/tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+@ParametersAreNonnullByDefault
+package org.sonarqube.qa.bluegreen;
+
+import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/tests/src/test/java/org/sonarqube/tests/Category5Suite.java b/tests/src/test/java/org/sonarqube/tests/Category5Suite.java
index 0f1cc1381ab..d45b79800cc 100644
--- a/tests/src/test/java/org/sonarqube/tests/Category5Suite.java
+++ b/tests/src/test/java/org/sonarqube/tests/Category5Suite.java
@@ -29,6 +29,7 @@ import org.sonarqube.tests.marketplace.UpdateCenterTest;
import org.sonarqube.tests.qualityProfile.ActiveRuleEsResilienceTest;
import org.sonarqube.tests.qualityProfile.BuiltInQualityProfilesNotificationTest;
import org.sonarqube.tests.rule.RuleEsResilienceTest;
+import org.sonarqube.tests.serverSystem.BlueGreenTest;
import org.sonarqube.tests.serverSystem.RestartTest;
import org.sonarqube.tests.serverSystem.ServerSystemRestartingOrchestrator;
import org.sonarqube.tests.serverSystem.SystemStateTest;
@@ -52,6 +53,7 @@ import org.sonarqube.tests.user.UserEsResilienceTest;
@Deprecated
@RunWith(Suite.class)
@Suite.SuiteClasses({
+ BlueGreenTest.class,
ServerSystemRestartingOrchestrator.class,
RestartTest.class,
SettingsTestRestartingOrchestrator.class,
diff --git a/tests/src/test/java/org/sonarqube/tests/serverSystem/BlueGreenTest.java b/tests/src/test/java/org/sonarqube/tests/serverSystem/BlueGreenTest.java
new file mode 100644
index 00000000000..106a47a1e82
--- /dev/null
+++ b/tests/src/test/java/org/sonarqube/tests/serverSystem/BlueGreenTest.java
@@ -0,0 +1,134 @@
+/*
+ * 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.tests.serverSystem;
+
+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;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.DisableOnDebug;
+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.qualityprofiles.AddProjectRequest;
+import util.XooProjectBuilder;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static util.ItUtils.newOrchestratorBuilder;
+import static util.ItUtils.pluginArtifact;
+import static util.ItUtils.xooPlugin;
+
+public class BlueGreenTest {
+
+ @Rule
+ public TestRule safeguard = new DisableOnDebug(Timeout.seconds(600));
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ private Orchestrator orchestrator;
+ private Tester tester;
+
+ @After
+ public void tearDown() {
+ if (tester != null) {
+ tester.after();
+ }
+ if (orchestrator != null) {
+ orchestrator.stop();
+ }
+ }
+
+ @Test
+ public void test_change_of_version_at_runtime() throws Exception {
+ orchestrator = newOrchestratorBuilder()
+ .addPlugin(pluginArtifact("blue-green-plugin-v1"))
+ .addPlugin(xooPlugin())
+ .build();
+ tester = new Tester(orchestrator).disableOrganizations();
+ 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);
+
+ // open browser
+ Navigation browser = tester.openBrowser();
+
+
+ // upgrade plugin
+ 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);
+
+ resumeAndWaitForCeQueueEmpty();
+
+ // 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);
+ }
+
+ private void associateProjectToProfile(Projects.CreateWsResponse.Project project, String xooProfileName) {
+ tester.wsClient().qualityprofiles().addProject(new AddProjectRequest()
+ .setProject(project.getKey())
+ .setLanguage("xoo")
+ .setQualityProfile(xooProfileName));
+ }
+
+ private void resumeAndWaitForCeQueueEmpty() {
+ tester.wsClient().ce().resume();
+ while (true) {
+ Ce.ActivityStatusWsResponse activity = loadCeActivity();
+ if (activity.getPending() + activity.getInProgress() == 0) {
+ return;
+ }
+ Uninterruptibles.sleepUninterruptibly(100, TimeUnit.MILLISECONDS);
+ }
+ }
+
+ private Ce.ActivityStatusWsResponse loadCeActivity() {
+ return tester.wsClient().ce().activityStatus(new ActivityStatusRequest());
+ }
+}
diff --git a/tests/src/test/java/util/XooProjectBuilder.java b/tests/src/test/java/util/XooProjectBuilder.java
index 0eaf934572b..c9e8c8265b8 100644
--- a/tests/src/test/java/util/XooProjectBuilder.java
+++ b/tests/src/test/java/util/XooProjectBuilder.java
@@ -67,6 +67,10 @@ public class XooProjectBuilder {
for (int i = 0; i < filesPerModule; i++) {
File sourceFile = new File(sourceDir, "File" + i + ".xoo");
FileUtils.write(sourceFile, "content of " + sourceFile.getName());
+
+ File measuresFile = new File(sourceFile + ".measures");
+ FileUtils.write(measuresFile, "ncloc:10\n" +
+ "comment_lines:3\n");
}
Properties props = new Properties();
props.setProperty("sonar.projectKey", key);