]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10593 CE should ignore issues on inactive rules
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Thu, 19 Apr 2018 12:28:00 +0000 (14:28 +0200)
committerSonarTech <sonartech@sonarsource.com>
Thu, 10 May 2018 18:20:54 +0000 (20:20 +0200)
36 files changed:
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IssueCreationDateCalculator.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IssueVisitor.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactory.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/IntegrateIssuesVisitorTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerRawInputFactoryTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/qualityprofile/AlwaysActiveRulesHolderImpl.java [new file with mode: 0644]
settings.gradle
tests/build.gradle
tests/plugins/blue-green-plugin-v1/build.gradle [new file with mode: 0644]
tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/BlueGreenPlugin.java [new file with mode: 0644]
tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/BuiltInProfilesV1.java [new file with mode: 0644]
tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/PageDefinitionV1.java [new file with mode: 0644]
tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/RuleSensorV1.java [new file with mode: 0644]
tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/RulesDefinitionV1.java [new file with mode: 0644]
tests/plugins/blue-green-plugin-v1/src/main/java/org/sonarqube/qa/bluegreen/package-info.java [new file with mode: 0644]
tests/plugins/blue-green-plugin-v1/src/main/resources/static/global_page.js [new file with mode: 0644]
tests/plugins/blue-green-plugin-v2/build.gradle [new file with mode: 0644]
tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/BlueGreenPlugin.java [new file with mode: 0644]
tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/BuiltInProfilesV2.java [new file with mode: 0644]
tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/PageDefinitionV2.java [new file with mode: 0644]
tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/RuleSensorV2.java [new file with mode: 0644]
tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/RulesDefinitionV2.java [new file with mode: 0644]
tests/plugins/blue-green-plugin-v2/src/main/java/org/sonarqube/qa/bluegreen/package-info.java [new file with mode: 0644]
tests/plugins/blue-green-plugin-v2/src/main/resources/static/global_page.js [new file with mode: 0644]
tests/plugins/blue-green-plugin/build.gradle [new file with mode: 0644]
tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/BlueGreenPlugin.java [new file with mode: 0644]
tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/BuiltInProfilesV1.java [new file with mode: 0644]
tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/BuiltInProfilesV2.java [new file with mode: 0644]
tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/RuleSensorV1.java [new file with mode: 0644]
tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/RuleSensorV2.java [new file with mode: 0644]
tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/RulesDefinitionV1.java [new file with mode: 0644]
tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/RulesDefinitionV2.java [new file with mode: 0644]
tests/plugins/blue-green-plugin/src/main/java/org/sonarqube/qa/bluegreen/package-info.java [new file with mode: 0644]
tests/src/test/java/org/sonarqube/tests/Category5Suite.java
tests/src/test/java/org/sonarqube/tests/serverSystem/BlueGreenTest.java [new file with mode: 0644]
tests/src/test/java/util/XooProjectBuilder.java

index a43250189d3849f73b4394482fa69895cd29b105..43fab81a51e2273b21579f0ebefc7b0b10557737 100644 (file)
@@ -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));
   }
index f403d50e50aed98caee6e7dd47452a8a76378708..d974dc76eea1b03e5cd6da8b73243820c73a4f28 100644 (file)
@@ -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) {
 
index 878651b2c00a480ef10c7e38339f5a6d90ee5405..84a1cab92deda5ebcc894127629d7db1dbd923bc 100644 (file)
@@ -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.
index 085820dae944d85246f4f4b6d8184ea850e8ca62..a19a9a940f208ab6fe49e781d3c52e02cc92a904 100644 (file)
@@ -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<>());
index e04d29817883b1536f753e01519679b5034d6693..3da31e3a7c2e1103ff7576783da76aa23abf44b0 100644 (file)
@@ -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 (file)
index 0000000..088138a
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.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));
+  }
+
+}
index a3f0c94d68593d6d9d5c759c8814265d5354dead..bc05b4e8080173cd51ea0fc33c9333ce67f5ed57 100644 (file)
@@ -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'
index 8164dfebb19bbc145d0fce0d9d87b5149caa0741..1d9605e8593cb23b0538946728414e25c6472baa 100644 (file)
@@ -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 (file)
index 0000000..e2fef43
--- /dev/null
@@ -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 (file)
index 0000000..ea0eea8
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonarqube.qa.bluegreen;
+
+import 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 (file)
index 0000000..1d19f4e
--- /dev/null
@@ -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 (file)
index 0000000..d7cb207
--- /dev/null
@@ -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 (file)
index 0000000..1d37782
--- /dev/null
@@ -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 (file)
index 0000000..e6fbc56
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonarqube.qa.bluegreen;
+
+import 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 (file)
index 0000000..86d3578
--- /dev/null
@@ -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 (file)
index 0000000..257440f
--- /dev/null
@@ -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 (file)
index 0000000..0730c13
--- /dev/null
@@ -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 (file)
index 0000000..156bf7a
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonarqube.qa.bluegreen;
+
+import 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 (file)
index 0000000..ccb8e09
--- /dev/null
@@ -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 (file)
index 0000000..d9d6410
--- /dev/null
@@ -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 (file)
index 0000000..5dde5dd
--- /dev/null
@@ -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 (file)
index 0000000..3e04908
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonarqube.qa.bluegreen;
+
+import 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 (file)
index 0000000..86d3578
--- /dev/null
@@ -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 (file)
index 0000000..2bf90ef
--- /dev/null
@@ -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 (file)
index 0000000..833f88f
--- /dev/null
@@ -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 (file)
index 0000000..f4ec4e5
--- /dev/null
@@ -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 (file)
index 0000000..79e14e0
--- /dev/null
@@ -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 (file)
index 0000000..131f171
--- /dev/null
@@ -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 (file)
index 0000000..9ecea9b
--- /dev/null
@@ -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 (file)
index 0000000..d3c18d6
--- /dev/null
@@ -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 (file)
index 0000000..af58aeb
--- /dev/null
@@ -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 (file)
index 0000000..8b39095
--- /dev/null
@@ -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 (file)
index 0000000..86d3578
--- /dev/null
@@ -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;
index 0f1cc1381abb74fa6bc87b9a606149d9377eea1b..d45b79800ccee45b3429ea1027347d9eb810ef19 100644 (file)
@@ -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 (file)
index 0000000..106a47a
--- /dev/null
@@ -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());
+  }
+}
index 0eaf934572b31f9de99e8f052b5f5f4e27132971..c9e8c8265b8be4837ba8da1f867b055dffd44a5d 100644 (file)
@@ -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);