aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorDuarte Meneses <duarte.meneses@sonarsource.com>2017-08-09 15:32:47 +0200
committerJanos Gyerik <janos.gyerik@sonarsource.com>2017-09-12 10:55:10 +0200
commit8f27cc5968df9f258f94fbdc1de47a1784dfafb9 (patch)
treebe81b1df3becad47a0e24b10ec7eed231e04fcea /server
parentdd47b17bb4259ce422e3a643d07178f21185a406 (diff)
downloadsonarqube-8f27cc5968df9f258f94fbdc1de47a1784dfafb9.tar.gz
sonarqube-8f27cc5968df9f258f94fbdc1de47a1784dfafb9.zip
SONAR-9692 - Perform issue tracking for short living branches
Diffstat (limited to 'server')
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulator.java12
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/BaseIssuesLoader.java39
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/CloseIssuesOnRemovedComponentsVisitor.java8
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/ComponentIssuesLoader.java67
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/DefaultTrackingInput.java55
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IntegrateIssuesVisitor.java65
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IssueLifecycle.java4
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IssueTrackingDelegator.java52
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/MergeBranchIssuesLoader.java71
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RemoveProcessedComponentsVisitor.java44
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/ShortBranchTrackerExecution.java63
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerBaseInputFactory.java8
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerExecution.java6
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerMergeBranchInputFactory.java76
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/CloseIssuesOnRemovedComponentsVisitorTest.java6
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/DefaultTrackingInputTest.java54
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/IntegrateIssuesVisitorTest.java65
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/IssueTrackingDelegatorTest.java78
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/RemoveProcessedComponentsVisitorTest.java72
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/ShortBranchTrackerExecutionTest.java132
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerBaseInputFactoryTest.java16
21 files changed, 850 insertions, 143 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulator.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulator.java
index d4d2b580bda..f0c8946a452 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulator.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulator.java
@@ -49,6 +49,7 @@ import org.sonar.server.computation.task.projectanalysis.filemove.SourceSimilari
import org.sonar.server.computation.task.projectanalysis.filesystem.ComputationTempFolderProvider;
import org.sonar.server.computation.task.projectanalysis.issue.BaseIssuesLoader;
import org.sonar.server.computation.task.projectanalysis.issue.CloseIssuesOnRemovedComponentsVisitor;
+import org.sonar.server.computation.task.projectanalysis.issue.ComponentIssuesLoader;
import org.sonar.server.computation.task.projectanalysis.issue.ComponentIssuesRepositoryImpl;
import org.sonar.server.computation.task.projectanalysis.issue.ComponentsWithUnprocessedIssues;
import org.sonar.server.computation.task.projectanalysis.issue.DebtCalculator;
@@ -60,19 +61,24 @@ import org.sonar.server.computation.task.projectanalysis.issue.IssueCache;
import org.sonar.server.computation.task.projectanalysis.issue.IssueCounter;
import org.sonar.server.computation.task.projectanalysis.issue.IssueCreationDateCalculator;
import org.sonar.server.computation.task.projectanalysis.issue.IssueLifecycle;
+import org.sonar.server.computation.task.projectanalysis.issue.IssueTrackingDelegator;
import org.sonar.server.computation.task.projectanalysis.issue.IssueVisitors;
import org.sonar.server.computation.task.projectanalysis.issue.IssuesRepositoryVisitor;
import org.sonar.server.computation.task.projectanalysis.issue.LoadComponentUuidsHavingOpenIssuesVisitor;
+import org.sonar.server.computation.task.projectanalysis.issue.MergeBranchIssuesLoader;
import org.sonar.server.computation.task.projectanalysis.issue.MovedIssueVisitor;
import org.sonar.server.computation.task.projectanalysis.issue.NewEffortAggregator;
import org.sonar.server.computation.task.projectanalysis.issue.NewEffortCalculator;
+import org.sonar.server.computation.task.projectanalysis.issue.RemoveProcessedComponentsVisitor;
import org.sonar.server.computation.task.projectanalysis.issue.RuleRepositoryImpl;
import org.sonar.server.computation.task.projectanalysis.issue.RuleTagsCopier;
import org.sonar.server.computation.task.projectanalysis.issue.RuleTypeCopier;
import org.sonar.server.computation.task.projectanalysis.issue.ScmAccountToUser;
import org.sonar.server.computation.task.projectanalysis.issue.ScmAccountToUserLoader;
+import org.sonar.server.computation.task.projectanalysis.issue.ShortBranchTrackerExecution;
import org.sonar.server.computation.task.projectanalysis.issue.TrackerBaseInputFactory;
import org.sonar.server.computation.task.projectanalysis.issue.TrackerExecution;
+import org.sonar.server.computation.task.projectanalysis.issue.TrackerMergeBranchInputFactory;
import org.sonar.server.computation.task.projectanalysis.issue.TrackerRawInputFactory;
import org.sonar.server.computation.task.projectanalysis.issue.UpdateConflictResolver;
import org.sonar.server.computation.task.projectanalysis.issue.commonrule.BranchCoverageRule;
@@ -212,6 +218,7 @@ public final class ProjectAnalysisTaskContainerPopulator implements ContainerPop
IssueCounter.class,
MovedIssueVisitor.class,
IssuesRepositoryVisitor.class,
+ RemoveProcessedComponentsVisitor.class,
// visitors : order is important, measure computers must be executed at the end in order to access to every measures / issues
LoadComponentUuidsHavingOpenIssuesVisitor.class,
@@ -227,9 +234,14 @@ public final class ProjectAnalysisTaskContainerPopulator implements ContainerPop
UpdateConflictResolver.class,
TrackerBaseInputFactory.class,
TrackerRawInputFactory.class,
+ TrackerMergeBranchInputFactory.class,
Tracker.class,
TrackerExecution.class,
+ ShortBranchTrackerExecution.class,
+ ComponentIssuesLoader.class,
BaseIssuesLoader.class,
+ MergeBranchIssuesLoader.class,
+ IssueTrackingDelegator.class,
// filemove
SourceSimilarityImpl.class,
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/BaseIssuesLoader.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/BaseIssuesLoader.java
index eef3eea4d0b..359be376b16 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/BaseIssuesLoader.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/BaseIssuesLoader.java
@@ -19,59 +19,22 @@
*/
package org.sonar.server.computation.task.projectanalysis.issue;
-import java.util.ArrayList;
-import java.util.List;
import java.util.Set;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rule.RuleStatus;
-import org.sonar.core.issue.DefaultIssue;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
-import org.sonar.db.issue.IssueMapper;
import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolder;
-import org.sonar.server.computation.task.projectanalysis.qualityprofile.ActiveRulesHolder;
/**
* Loads all the project open issues from database, including manual issues.
- *
*/
public class BaseIssuesLoader {
private final TreeRootHolder treeRootHolder;
private final DbClient dbClient;
- private final RuleRepository ruleRepository;
- private final ActiveRulesHolder activeRulesHolder;
- public BaseIssuesLoader(TreeRootHolder treeRootHolder,
- DbClient dbClient, RuleRepository ruleRepository, ActiveRulesHolder activeRulesHolder) {
- this.activeRulesHolder = activeRulesHolder;
+ public BaseIssuesLoader(TreeRootHolder treeRootHolder, DbClient dbClient) {
this.treeRootHolder = treeRootHolder;
this.dbClient = dbClient;
- this.ruleRepository = ruleRepository;
- }
-
- public List<DefaultIssue> loadForComponentUuid(String componentUuid) {
- try (DbSession dbSession = dbClient.openSession(false)) {
- List<DefaultIssue> result = new ArrayList<>();
- dbSession.getMapper(IssueMapper.class).scrollNonClosedByComponentUuid(componentUuid, resultContext -> {
- DefaultIssue issue = (resultContext.getResultObject()).toDefaultIssue();
-
- // TODO this field should be set outside this class
- if (!isActive(issue.ruleKey()) || ruleRepository.getByKey(issue.ruleKey()).getStatus() == RuleStatus.REMOVED) {
- issue.setOnDisabledRule(true);
- // TODO to be improved, why setOnDisabledRule(true) is not enough ?
- issue.setBeingClosed(true);
- }
- // FIXME
- issue.setSelectedAt(System.currentTimeMillis());
- result.add(issue);
- });
- return result;
- }
- }
-
- private boolean isActive(RuleKey ruleKey) {
- return activeRulesHolder.get(ruleKey).isPresent();
}
/**
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/CloseIssuesOnRemovedComponentsVisitor.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/CloseIssuesOnRemovedComponentsVisitor.java
index f74bcdb5ac5..7b178613b15 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/CloseIssuesOnRemovedComponentsVisitor.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/CloseIssuesOnRemovedComponentsVisitor.java
@@ -34,15 +34,15 @@ import static org.sonar.server.computation.task.projectanalysis.component.Compon
*/
public class CloseIssuesOnRemovedComponentsVisitor extends TypeAwareVisitorAdapter {
- private final BaseIssuesLoader baseIssuesLoader;
+ private final ComponentIssuesLoader issuesLoader;
private final ComponentsWithUnprocessedIssues componentsWithUnprocessedIssues;
private final IssueCache issueCache;
private final IssueLifecycle issueLifecycle;
- public CloseIssuesOnRemovedComponentsVisitor(BaseIssuesLoader baseIssuesLoader, ComponentsWithUnprocessedIssues componentsWithUnprocessedIssues, IssueCache issueCache,
+ public CloseIssuesOnRemovedComponentsVisitor(ComponentIssuesLoader issuesLoader, ComponentsWithUnprocessedIssues componentsWithUnprocessedIssues, IssueCache issueCache,
IssueLifecycle issueLifecycle) {
super(CrawlerDepthLimit.PROJECT, POST_ORDER);
- this.baseIssuesLoader = baseIssuesLoader;
+ this.issuesLoader = issuesLoader;
this.componentsWithUnprocessedIssues = componentsWithUnprocessedIssues;
this.issueCache = issueCache;
this.issueLifecycle = issueLifecycle;
@@ -57,7 +57,7 @@ public class CloseIssuesOnRemovedComponentsVisitor extends TypeAwareVisitorAdapt
DiskCache<DefaultIssue>.DiskAppender cacheAppender = issueCache.newAppender();
try {
for (String deletedComponentUuid : deletedComponentUuids) {
- List<DefaultIssue> issues = baseIssuesLoader.loadForComponentUuid(deletedComponentUuid);
+ List<DefaultIssue> issues = issuesLoader.loadForComponentUuid(deletedComponentUuid);
for (DefaultIssue issue : issues) {
issue.setBeingClosed(true);
// TODO should be renamed
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/ComponentIssuesLoader.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/ComponentIssuesLoader.java
new file mode 100644
index 00000000000..2ae00cdd153
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/ComponentIssuesLoader.java
@@ -0,0 +1,67 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.task.projectanalysis.issue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.core.issue.DefaultIssue;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.issue.IssueMapper;
+import org.sonar.server.computation.task.projectanalysis.qualityprofile.ActiveRulesHolder;
+
+public class ComponentIssuesLoader {
+ private final DbClient dbClient;
+ private final RuleRepository ruleRepository;
+ private final ActiveRulesHolder activeRulesHolder;
+
+ public ComponentIssuesLoader(DbClient dbClient, RuleRepository ruleRepository, ActiveRulesHolder activeRulesHolder) {
+ this.activeRulesHolder = activeRulesHolder;
+ this.dbClient = dbClient;
+ this.ruleRepository = ruleRepository;
+ }
+
+ public List<DefaultIssue> loadForComponentUuid(String componentUuid) {
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ List<DefaultIssue> result = new ArrayList<>();
+ dbSession.getMapper(IssueMapper.class).scrollNonClosedByComponentUuid(componentUuid, resultContext -> {
+ DefaultIssue issue = (resultContext.getResultObject()).toDefaultIssue();
+
+ // TODO this field should be set outside this class
+ if (!isActive(issue.ruleKey()) || ruleRepository.getByKey(issue.ruleKey()).getStatus() == RuleStatus.REMOVED) {
+ issue.setOnDisabledRule(true);
+ // TODO to be improved, why setOnDisabledRule(true) is not enough ?
+ issue.setBeingClosed(true);
+ }
+ // FIXME
+ issue.setSelectedAt(System.currentTimeMillis());
+ result.add(issue);
+ });
+ return result;
+ }
+ }
+
+ private boolean isActive(RuleKey ruleKey) {
+ return activeRulesHolder.get(ruleKey).isPresent();
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/DefaultTrackingInput.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/DefaultTrackingInput.java
new file mode 100644
index 00000000000..5ac2a68ec25
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/DefaultTrackingInput.java
@@ -0,0 +1,55 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.task.projectanalysis.issue;
+
+import java.util.Collection;
+
+import org.sonar.core.issue.DefaultIssue;
+import org.sonar.core.issue.tracking.BlockHashSequence;
+import org.sonar.core.issue.tracking.Input;
+import org.sonar.core.issue.tracking.LineHashSequence;
+
+public class DefaultTrackingInput implements Input<DefaultIssue> {
+ private final Collection<DefaultIssue> issues;
+ private final LineHashSequence lineHashes;
+ private final BlockHashSequence blockHashes;
+
+ public DefaultTrackingInput(Collection<DefaultIssue> issues, LineHashSequence lineHashes, BlockHashSequence blockHashes) {
+ this.issues = issues;
+ this.lineHashes = lineHashes;
+ this.blockHashes = blockHashes;
+ }
+
+ @Override
+ public LineHashSequence getLineHashSequence() {
+ return lineHashes;
+ }
+
+ @Override
+ public BlockHashSequence getBlockHashSequence() {
+ return blockHashes;
+ }
+
+ @Override
+ public Collection<DefaultIssue> getIssues() {
+ return issues;
+ }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IntegrateIssuesVisitor.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IntegrateIssuesVisitor.java
index b0bdbe309d7..528372d82e3 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IntegrateIssuesVisitor.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IntegrateIssuesVisitor.java
@@ -21,6 +21,7 @@ package org.sonar.server.computation.task.projectanalysis.issue;
import static org.sonar.server.computation.task.projectanalysis.component.ComponentVisitor.Order.POST_ORDER;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -31,64 +32,45 @@ import org.sonar.server.computation.task.projectanalysis.component.Component;
import org.sonar.server.computation.task.projectanalysis.component.Component.Status;
import org.sonar.server.computation.task.projectanalysis.component.CrawlerDepthLimit;
import org.sonar.server.computation.task.projectanalysis.component.TypeAwareVisitorAdapter;
-import org.sonar.server.computation.task.projectanalysis.filemove.MovedFilesRepository;
import org.sonar.server.util.cache.DiskCache;
-import com.google.common.base.Optional;
-
public class IntegrateIssuesVisitor extends TypeAwareVisitorAdapter {
- private final TrackerExecution tracker;
private final IssueCache issueCache;
private final IssueLifecycle issueLifecycle;
private final IssueVisitors issueVisitors;
- private final ComponentsWithUnprocessedIssues componentsWithUnprocessedIssues;
- private final MovedFilesRepository movedFilesRepository;
- private final BaseIssuesLoader baseIssuesLoader;
+ private final ComponentIssuesLoader issuesLoader;
private final AnalysisMetadataHolder analysisMetadataHolder;
+ private final IssueTrackingDelegator issueTracking;
- public IntegrateIssuesVisitor(TrackerExecution tracker, IssueCache issueCache, IssueLifecycle issueLifecycle, IssueVisitors issueVisitors,
- ComponentsWithUnprocessedIssues componentsWithUnprocessedIssues, MovedFilesRepository movedFilesRepository, BaseIssuesLoader baseIssuesLoader,
- AnalysisMetadataHolder analysisMetadataHolder) {
+ public IntegrateIssuesVisitor(IssueCache issueCache, IssueLifecycle issueLifecycle, IssueVisitors issueVisitors, ComponentIssuesLoader issuesLoader,
+ AnalysisMetadataHolder analysisMetadataHolder, IssueTrackingDelegator issueTracking) {
super(CrawlerDepthLimit.FILE, POST_ORDER);
- this.tracker = tracker;
this.issueCache = issueCache;
this.issueLifecycle = issueLifecycle;
this.issueVisitors = issueVisitors;
- this.componentsWithUnprocessedIssues = componentsWithUnprocessedIssues;
- this.movedFilesRepository = movedFilesRepository;
- this.baseIssuesLoader = baseIssuesLoader;
+ this.issuesLoader = issuesLoader;
this.analysisMetadataHolder = analysisMetadataHolder;
+ this.issueTracking = issueTracking;
}
@Override
public void visitAny(Component component) {
- processIssues(component);
-
- componentsWithUnprocessedIssues.remove(component.getUuid());
- Optional<MovedFilesRepository.OriginalFile> originalFile = movedFilesRepository.getOriginalFile(component);
- if (originalFile.isPresent()) {
- componentsWithUnprocessedIssues.remove(originalFile.get().getUuid());
- }
- }
-
- private void processIssues(Component component) {
- DiskCache<DefaultIssue>.DiskAppender cacheAppender = issueCache.newAppender();
- try {
+ try (DiskCache<DefaultIssue>.DiskAppender cacheAppender = issueCache.newAppender()) {
issueVisitors.beforeComponent(component);
+
if (isIncremental(component)) {
- fillIncrementalOpenIssues(component, cacheAppender);
+ List<DefaultIssue> issues = issuesLoader.loadForComponentUuid(component.getUuid());
+ fillIncrementalOpenIssues(component, issues, cacheAppender);
} else {
- Tracking<DefaultIssue, DefaultIssue> tracking = tracker.track(component);
- fillNewOpenIssues(component, tracking, cacheAppender);
- fillExistingOpenIssues(component, tracking, cacheAppender);
- closeUnmatchedBaseIssues(component, tracking, cacheAppender);
+ Tracking<DefaultIssue, DefaultIssue> tracking = issueTracking.track(component);
+ fillNewOpenIssues(component, tracking.getUnmatchedRaws(), cacheAppender);
+ fillExistingOpenIssues(component, tracking.getMatchedRaws(), cacheAppender);
+ closeUnmatchedBaseIssues(component, tracking.getUnmatchedBases(), cacheAppender);
}
issueVisitors.afterComponent(component);
} catch (Exception e) {
throw new IllegalStateException(String.format("Fail to process issues of component '%s'", component.getKey()), e);
- } finally {
- cacheAppender.close();
}
}
@@ -96,24 +78,21 @@ public class IntegrateIssuesVisitor extends TypeAwareVisitorAdapter {
return analysisMetadataHolder.isIncrementalAnalysis() && component.getStatus() == Status.SAME;
}
- private void fillNewOpenIssues(Component component, Tracking<DefaultIssue, DefaultIssue> tracking, DiskCache<DefaultIssue>.DiskAppender cacheAppender) {
- for (DefaultIssue issue : tracking.getUnmatchedRaws()) {
+ private void fillNewOpenIssues(Component component, Iterable<DefaultIssue> issues, DiskCache<DefaultIssue>.DiskAppender cacheAppender) {
+ for (DefaultIssue issue : issues) {
issueLifecycle.initNewOpenIssue(issue);
process(component, issue, cacheAppender);
}
}
- private void fillIncrementalOpenIssues(Component component, DiskCache<DefaultIssue>.DiskAppender cacheAppender) {
- List<DefaultIssue> issues = baseIssuesLoader.loadForComponentUuid(component.getUuid());
-
+ private void fillIncrementalOpenIssues(Component component, Collection<DefaultIssue> issues, DiskCache<DefaultIssue>.DiskAppender cacheAppender) {
for (DefaultIssue issue : issues) {
- issueLifecycle.updateExistingOpenissue(issue);
process(component, issue, cacheAppender);
}
}
- private void fillExistingOpenIssues(Component component, Tracking<DefaultIssue, DefaultIssue> tracking, DiskCache<DefaultIssue>.DiskAppender cacheAppender) {
- for (Map.Entry<DefaultIssue, DefaultIssue> entry : tracking.getMatchedRaws().entrySet()) {
+ private void fillExistingOpenIssues(Component component, Map<DefaultIssue, DefaultIssue> matched, DiskCache<DefaultIssue>.DiskAppender cacheAppender) {
+ for (Map.Entry<DefaultIssue, DefaultIssue> entry : matched.entrySet()) {
DefaultIssue raw = entry.getKey();
DefaultIssue base = entry.getValue();
issueLifecycle.mergeExistingOpenIssue(raw, base);
@@ -121,8 +100,8 @@ public class IntegrateIssuesVisitor extends TypeAwareVisitorAdapter {
}
}
- private void closeUnmatchedBaseIssues(Component component, Tracking<DefaultIssue, DefaultIssue> tracking, DiskCache<DefaultIssue>.DiskAppender cacheAppender) {
- for (DefaultIssue issue : tracking.getUnmatchedBases()) {
+ private void closeUnmatchedBaseIssues(Component component, Iterable<DefaultIssue> issues, DiskCache<DefaultIssue>.DiskAppender cacheAppender) {
+ for (DefaultIssue issue : issues) {
// TODO should replace flag "beingClosed" by express call to transition "automaticClose"
issue.setBeingClosed(true);
// TODO manual issues -> was updater.setResolution(newIssue, Issue.RESOLUTION_REMOVED, changeContext);. Is it a problem ?
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IssueLifecycle.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IssueLifecycle.java
index 6942c5c58c0..6ee0a12e76c 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IssueLifecycle.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IssueLifecycle.java
@@ -64,10 +64,6 @@ public class IssueLifecycle {
issue.setStatus(Issue.STATUS_OPEN);
issue.setEffort(debtCalculator.calculate(issue));
}
-
- public void updateExistingOpenissue(DefaultIssue base) {
- // nothing to do
- }
public void mergeExistingOpenIssue(DefaultIssue raw, DefaultIssue base) {
raw.setNew(false);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IssueTrackingDelegator.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IssueTrackingDelegator.java
new file mode 100644
index 00000000000..5e51c6c6982
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/IssueTrackingDelegator.java
@@ -0,0 +1,52 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.task.projectanalysis.issue;
+
+import org.sonar.core.issue.DefaultIssue;
+import org.sonar.core.issue.tracking.Tracking;
+import org.sonar.db.component.BranchType;
+import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolder;
+import org.sonar.server.computation.task.projectanalysis.analysis.Branch;
+import org.sonar.server.computation.task.projectanalysis.component.Component;
+
+public class IssueTrackingDelegator {
+ private final ShortBranchTrackerExecution shortBranchTracker;
+ private final TrackerExecution tracker;
+ private final AnalysisMetadataHolder analysisMetadataHolder;
+
+ public IssueTrackingDelegator(ShortBranchTrackerExecution shortBranchTracker, TrackerExecution tracker, AnalysisMetadataHolder analysisMetadataHolder) {
+ this.shortBranchTracker = shortBranchTracker;
+ this.tracker = tracker;
+ this.analysisMetadataHolder = analysisMetadataHolder;
+ }
+
+ private boolean isShortLivingBranch() {
+ java.util.Optional<Branch> branch = analysisMetadataHolder.getBranch();
+ return branch.isPresent() && branch.get().getType() == BranchType.SHORT;
+ }
+
+ public Tracking<DefaultIssue, DefaultIssue> track(Component component) {
+ if (isShortLivingBranch()) {
+ return shortBranchTracker.track(component);
+ } else {
+ return tracker.track(component);
+ }
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/MergeBranchIssuesLoader.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/MergeBranchIssuesLoader.java
new file mode 100644
index 00000000000..b32e08c43c7
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/MergeBranchIssuesLoader.java
@@ -0,0 +1,71 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.task.projectanalysis.issue;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.sonar.core.issue.DefaultIssue;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolder;
+
+public class MergeBranchIssuesLoader {
+ private final DbClient dbClient;
+ private final ComponentIssuesLoader issuesLoader;
+ private final AnalysisMetadataHolder analysisMetadataHolder;
+ private Map<String, String> uuidsByKey;
+
+ public MergeBranchIssuesLoader(DbClient dbClient, ComponentIssuesLoader issuesLoader, AnalysisMetadataHolder analysisMetadataHolder) {
+ this.dbClient = dbClient;
+ this.issuesLoader = issuesLoader;
+ this.analysisMetadataHolder = analysisMetadataHolder;
+ }
+
+ public void loadMergeBranchComponents() {
+ String mergeBranchUuid = analysisMetadataHolder.getBranch().get().getMergeBranchUuid().get();
+
+ uuidsByKey = new HashMap<>();
+ try (DbSession dbSession = dbClient.openSession(false)) {
+
+ List<ComponentDto> components = dbClient.componentDao().selectByProjectUuid(mergeBranchUuid, dbSession);
+ for (ComponentDto dto : components) {
+ uuidsByKey.put(dto.getDbKey(), dto.uuid());
+ }
+ }
+ }
+
+ public List<DefaultIssue> loadForKey(String componentKey) {
+ if (uuidsByKey == null) {
+ loadMergeBranchComponents();
+ }
+
+ String componentUuid = uuidsByKey.get(componentKey);
+
+ if (componentUuid == null) {
+ return Collections.emptyList();
+ }
+
+ return issuesLoader.loadForComponentUuid(componentUuid);
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RemoveProcessedComponentsVisitor.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RemoveProcessedComponentsVisitor.java
new file mode 100644
index 00000000000..afff2f07464
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/RemoveProcessedComponentsVisitor.java
@@ -0,0 +1,44 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.task.projectanalysis.issue;
+
+import org.sonar.server.computation.task.projectanalysis.component.Component;
+import org.sonar.server.computation.task.projectanalysis.filemove.MovedFilesRepository;
+
+import com.google.common.base.Optional;
+
+public class RemoveProcessedComponentsVisitor extends IssueVisitor {
+ private final ComponentsWithUnprocessedIssues componentsWithUnprocessedIssues;
+ private final MovedFilesRepository movedFilesRepository;
+
+ public RemoveProcessedComponentsVisitor(ComponentsWithUnprocessedIssues componentsWithUnprocessedIssues, MovedFilesRepository movedFilesRepository) {
+ this.componentsWithUnprocessedIssues = componentsWithUnprocessedIssues;
+ this.movedFilesRepository = movedFilesRepository;
+ }
+
+ @Override
+ public void afterComponent(Component component) {
+ componentsWithUnprocessedIssues.remove(component.getUuid());
+ Optional<MovedFilesRepository.OriginalFile> originalFile = movedFilesRepository.getOriginalFile(component);
+ if (originalFile.isPresent()) {
+ componentsWithUnprocessedIssues.remove(originalFile.get().getUuid());
+ }
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/ShortBranchTrackerExecution.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/ShortBranchTrackerExecution.java
new file mode 100644
index 00000000000..1666e3ea1ab
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/ShortBranchTrackerExecution.java
@@ -0,0 +1,63 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.task.projectanalysis.issue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.sonar.core.issue.DefaultIssue;
+import org.sonar.core.issue.tracking.Input;
+import org.sonar.core.issue.tracking.Tracker;
+import org.sonar.core.issue.tracking.Tracking;
+import org.sonar.server.computation.task.projectanalysis.component.Component;
+
+public class ShortBranchTrackerExecution {
+ private TrackerBaseInputFactory baseInputFactory;
+ private TrackerRawInputFactory rawInputFactory;
+ private TrackerMergeBranchInputFactory mergeInputFactory;
+ private Tracker<DefaultIssue, DefaultIssue> tracker;
+
+ public ShortBranchTrackerExecution(TrackerBaseInputFactory baseInputFactory, TrackerRawInputFactory rawInputFactory, TrackerMergeBranchInputFactory mergeInputFactory,
+ Tracker<DefaultIssue, DefaultIssue> tracker) {
+ this.baseInputFactory = baseInputFactory;
+ this.rawInputFactory = rawInputFactory;
+ this.mergeInputFactory = mergeInputFactory;
+ this.tracker = tracker;
+ }
+
+ public Tracking<DefaultIssue, DefaultIssue> track(Component component) {
+ Input<DefaultIssue> rawInput = rawInputFactory.create(component);
+ Input<DefaultIssue> baseInput = baseInputFactory.create(component);
+ Input<DefaultIssue> mergeInput = mergeInputFactory.create(component);
+
+ Tracking<DefaultIssue, DefaultIssue> baseTracking = tracker.track(rawInput, mergeInput);
+ List<DefaultIssue> unmatchedRaws = toList(baseTracking.getUnmatchedRaws());
+ Input<DefaultIssue> unmatchedRawInput = new DefaultTrackingInput(unmatchedRaws, rawInput.getLineHashSequence(), rawInput.getBlockHashSequence());
+
+ // do second tracking with base branch using raws issues that are still unmatched
+ return tracker.track(unmatchedRawInput, baseInput);
+ }
+
+ private static <T> List<T> toList(Iterable<T> iterable) {
+ List<T> list = new ArrayList<>();
+ iterable.forEach(list::add);
+ return list;
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerBaseInputFactory.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerBaseInputFactory.java
index 01001bcdca8..f872f8e5f81 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerBaseInputFactory.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerBaseInputFactory.java
@@ -39,12 +39,12 @@ import org.sonar.server.computation.task.projectanalysis.filemove.MovedFilesRepo
public class TrackerBaseInputFactory {
private static final LineHashSequence EMPTY_LINE_HASH_SEQUENCE = new LineHashSequence(Collections.<String>emptyList());
- private final BaseIssuesLoader baseIssuesLoader;
+ private final ComponentIssuesLoader issuesLoader;
private final DbClient dbClient;
private final MovedFilesRepository movedFilesRepository;
- public TrackerBaseInputFactory(BaseIssuesLoader baseIssuesLoader, DbClient dbClient, MovedFilesRepository movedFilesRepository) {
- this.baseIssuesLoader = baseIssuesLoader;
+ public TrackerBaseInputFactory(ComponentIssuesLoader issuesLoader, DbClient dbClient, MovedFilesRepository movedFilesRepository) {
+ this.issuesLoader = issuesLoader;
this.dbClient = dbClient;
this.movedFilesRepository = movedFilesRepository;
}
@@ -80,7 +80,7 @@ public class TrackerBaseInputFactory {
@Override
protected List<DefaultIssue> loadIssues() {
- return baseIssuesLoader.loadForComponentUuid(effectiveUuid);
+ return issuesLoader.loadForComponentUuid(effectiveUuid);
}
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerExecution.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerExecution.java
index 60de97417ad..d62183f429c 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerExecution.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerExecution.java
@@ -26,9 +26,9 @@ import org.sonar.server.computation.task.projectanalysis.component.Component;
public class TrackerExecution {
- private final TrackerBaseInputFactory baseInputFactory;
- private final TrackerRawInputFactory rawInputFactory;
- private final Tracker<DefaultIssue, DefaultIssue> tracker;
+ protected final TrackerBaseInputFactory baseInputFactory;
+ protected final TrackerRawInputFactory rawInputFactory;
+ protected final Tracker<DefaultIssue, DefaultIssue> tracker;
public TrackerExecution(TrackerBaseInputFactory baseInputFactory, TrackerRawInputFactory rawInputFactory,
Tracker<DefaultIssue, DefaultIssue> tracker) {
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerMergeBranchInputFactory.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerMergeBranchInputFactory.java
new file mode 100644
index 00000000000..44f65e4a798
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerMergeBranchInputFactory.java
@@ -0,0 +1,76 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.task.projectanalysis.issue;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.sonar.core.issue.DefaultIssue;
+import org.sonar.core.issue.tracking.Input;
+import org.sonar.core.issue.tracking.LazyInput;
+import org.sonar.core.issue.tracking.LineHashSequence;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.server.computation.task.projectanalysis.component.Component;
+
+public class TrackerMergeBranchInputFactory {
+ private static final LineHashSequence EMPTY_LINE_HASH_SEQUENCE = new LineHashSequence(Collections.<String>emptyList());
+
+ private final MergeBranchIssuesLoader mergeIssuesLoader;
+ private final DbClient dbClient;
+
+ public TrackerMergeBranchInputFactory(MergeBranchIssuesLoader mergeIssuesLoader, DbClient dbClient) {
+ this.mergeIssuesLoader = mergeIssuesLoader;
+ this.dbClient = dbClient;
+ // TODO detect file moves?
+ }
+
+ public Input<DefaultIssue> create(Component component) {
+ return new MergeLazyInput(component);
+ }
+
+ private class MergeLazyInput extends LazyInput<DefaultIssue> {
+ private final Component component;
+
+ private MergeLazyInput(Component component) {
+ this.component = component;
+ }
+
+ @Override
+ protected LineHashSequence loadLineHashSequence() {
+ if (component.getType() != Component.Type.FILE) {
+ return EMPTY_LINE_HASH_SEQUENCE;
+ }
+
+ try (DbSession session = dbClient.openSession(false)) {
+ List<String> hashes = dbClient.fileSourceDao().selectLineHashes(session, component.getUuid());
+ if (hashes == null || hashes.isEmpty()) {
+ return EMPTY_LINE_HASH_SEQUENCE;
+ }
+ return new LineHashSequence(hashes);
+ }
+ }
+
+ @Override
+ protected List<DefaultIssue> loadIssues() {
+ return mergeIssuesLoader.loadForKey(component.getUuid());
+ }
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/CloseIssuesOnRemovedComponentsVisitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/CloseIssuesOnRemovedComponentsVisitorTest.java
index 92dc35229f5..3adcf83d6ca 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/CloseIssuesOnRemovedComponentsVisitorTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/CloseIssuesOnRemovedComponentsVisitorTest.java
@@ -48,7 +48,7 @@ public class CloseIssuesOnRemovedComponentsVisitorTest {
@Rule
public TemporaryFolder temp = new TemporaryFolder();
- BaseIssuesLoader baseIssuesLoader = mock(BaseIssuesLoader.class);
+ ComponentIssuesLoader issuesLoader = mock(ComponentIssuesLoader.class);
ComponentsWithUnprocessedIssues componentsWithUnprocessedIssues = mock(ComponentsWithUnprocessedIssues.class);
IssueLifecycle issueLifecycle = mock(IssueLifecycle.class);
IssueCache issueCache;
@@ -57,7 +57,7 @@ public class CloseIssuesOnRemovedComponentsVisitorTest {
@Before
public void setUp() throws Exception {
issueCache = new IssueCache(temp.newFile(), System2.INSTANCE);
- underTest = new VisitorsCrawler(Arrays.<ComponentVisitor>asList(new CloseIssuesOnRemovedComponentsVisitor(baseIssuesLoader, componentsWithUnprocessedIssues, issueCache, issueLifecycle)));
+ underTest = new VisitorsCrawler(Arrays.<ComponentVisitor>asList(new CloseIssuesOnRemovedComponentsVisitor(issuesLoader, componentsWithUnprocessedIssues, issueCache, issueLifecycle)));
}
@Test
@@ -67,7 +67,7 @@ public class CloseIssuesOnRemovedComponentsVisitorTest {
when(componentsWithUnprocessedIssues.getUuids()).thenReturn(newHashSet(fileUuid));
DefaultIssue issue = new DefaultIssue().setKey(issueUuid);
- when(baseIssuesLoader.loadForComponentUuid(fileUuid)).thenReturn(Collections.singletonList(issue));
+ when(issuesLoader.loadForComponentUuid(fileUuid)).thenReturn(Collections.singletonList(issue));
underTest.visit(ReportComponent.builder(PROJECT, 1).build());
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/DefaultTrackingInputTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/DefaultTrackingInputTest.java
new file mode 100644
index 00000000000..44e5cd2c08c
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/DefaultTrackingInputTest.java
@@ -0,0 +1,54 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.task.projectanalysis.issue;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Collection;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.sonar.core.issue.DefaultIssue;
+import org.sonar.core.issue.tracking.BlockHashSequence;
+import org.sonar.core.issue.tracking.LineHashSequence;
+
+public class DefaultTrackingInputTest {
+ @Mock
+ private Collection<DefaultIssue> issues;
+ @Mock
+ private BlockHashSequence blockHashes;
+ @Mock
+ private LineHashSequence lineHashes;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void test_getters() {
+ DefaultTrackingInput underTest = new DefaultTrackingInput(issues, lineHashes, blockHashes);
+ assertThat(underTest.getBlockHashSequence()).isEqualTo(blockHashes);
+ assertThat(underTest.getLineHashSequence()).isEqualTo(lineHashes);
+ assertThat(underTest.getIssues()).isEqualTo(issues);
+ }
+}
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 55a2d58583a..33f85ac5d33 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
@@ -20,7 +20,6 @@
package org.sonar.server.computation.task.projectanalysis.issue;
import static com.google.common.collect.Lists.newArrayList;
-import static com.google.common.collect.Sets.newHashSet;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.any;
@@ -29,7 +28,6 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.sonar.server.computation.task.projectanalysis.component.ReportComponent.builder;
-import java.util.Collections;
import java.util.List;
import org.junit.Before;
@@ -54,12 +52,13 @@ import org.sonar.db.rule.RuleDto;
import org.sonar.db.rule.RuleTesting;
import org.sonar.scanner.protocol.Constants;
import org.sonar.scanner.protocol.output.ScannerReport;
-import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
+import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolder;
import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReaderRule;
import org.sonar.server.computation.task.projectanalysis.component.Component;
+import org.sonar.server.computation.task.projectanalysis.component.Component.Status;
+import org.sonar.server.computation.task.projectanalysis.component.DefaultBranchImpl;
import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
import org.sonar.server.computation.task.projectanalysis.component.TypeAwareVisitor;
-import org.sonar.server.computation.task.projectanalysis.component.Component.Status;
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;
@@ -104,23 +103,24 @@ public class IntegrateIssuesVisitorTest {
public SourceLinesRepositoryRule fileSourceRepository = new SourceLinesRepositoryRule();
@Mock
- AnalysisMetadataHolderRule analysisMetadataHolder;
+ private AnalysisMetadataHolder analysisMetadataHolder;
@Mock
- IssueFilter issueFilter;
+ private IssueFilter issueFilter;
@Mock
- MovedFilesRepository movedFilesRepository;
+ private MovedFilesRepository movedFilesRepository;
@Mock
- IssueLifecycle issueLifecycle;
+ private IssueLifecycle issueLifecycle;
@Mock
- IssueVisitor issueVisitor;
+ private IssueVisitor issueVisitor;
ArgumentCaptor<DefaultIssue> defaultIssueCaptor = ArgumentCaptor.forClass(DefaultIssue.class);
- BaseIssuesLoader baseIssuesLoader = new BaseIssuesLoader(treeRootHolder, dbTester.getDbClient(), ruleRepositoryRule, activeRulesHolderRule);
-
+ ComponentIssuesLoader issuesLoader = new ComponentIssuesLoader(dbTester.getDbClient(), ruleRepositoryRule, activeRulesHolderRule);
+ MergeBranchIssuesLoader mergeIssuesLoader = new MergeBranchIssuesLoader(dbTester.getDbClient(), issuesLoader, analysisMetadataHolder);
+ IssueTrackingDelegator trackingDelegator;
TrackerExecution tracker;
+ ShortBranchTrackerExecution shortBranchTracker;
IssueCache issueCache;
- ComponentsWithUnprocessedIssues componentsWithUnprocessedIssues = new ComponentsWithUnprocessedIssues();
TypeAwareVisitor underTest;
@@ -129,23 +129,26 @@ public class IntegrateIssuesVisitorTest {
MockitoAnnotations.initMocks(this);
IssueVisitors issueVisitors = new IssueVisitors(new IssueVisitor[] {issueVisitor});
- tracker = new TrackerExecution(new TrackerBaseInputFactory(baseIssuesLoader, dbTester.getDbClient(), movedFilesRepository),
- new TrackerRawInputFactory(treeRootHolder, reportReader, fileSourceRepository, new CommonRuleEngineImpl(), issueFilter),
- new Tracker<>());
+ when(movedFilesRepository.getOriginalFile(any(Component.class))).thenReturn(Optional.<MovedFilesRepository.OriginalFile>absent());
+
+ TrackerRawInputFactory rawInputFactory = new TrackerRawInputFactory(treeRootHolder, reportReader, fileSourceRepository, new CommonRuleEngineImpl(), issueFilter);
+ TrackerBaseInputFactory baseInputFactory = new TrackerBaseInputFactory(issuesLoader, dbTester.getDbClient(), movedFilesRepository);
+ TrackerMergeBranchInputFactory mergeInputFactory = new TrackerMergeBranchInputFactory(mergeIssuesLoader, dbTester.getDbClient());
+ tracker = new TrackerExecution(baseInputFactory, rawInputFactory, new Tracker<>());
+ shortBranchTracker = new ShortBranchTrackerExecution(baseInputFactory, rawInputFactory, mergeInputFactory, new Tracker<>());
+ trackingDelegator = new IssueTrackingDelegator(shortBranchTracker, tracker, analysisMetadataHolder);
treeRootHolder.setRoot(PROJECT);
issueCache = new IssueCache(temp.newFile(), System2.INSTANCE);
when(analysisMetadataHolder.isIncrementalAnalysis()).thenReturn(false);
+ when(analysisMetadataHolder.getBranch()).thenReturn(java.util.Optional.of(new DefaultBranchImpl()));
when(issueFilter.accept(any(DefaultIssue.class), eq(FILE))).thenReturn(true);
- when(movedFilesRepository.getOriginalFile(any(Component.class))).thenReturn(Optional.<MovedFilesRepository.OriginalFile>absent());
- underTest = new IntegrateIssuesVisitor(tracker, issueCache, issueLifecycle, issueVisitors, componentsWithUnprocessedIssues,
- movedFilesRepository, baseIssuesLoader, analysisMetadataHolder);
+ underTest = new IntegrateIssuesVisitor(issueCache, issueLifecycle, issueVisitors, issuesLoader, analysisMetadataHolder, trackingDelegator);
}
@Test
public void process_issues_on_incremental_mode() {
when(analysisMetadataHolder.isIncrementalAnalysis()).thenReturn(true);
- componentsWithUnprocessedIssues.setUuids(Collections.singleton(FILE_UUID));
Component file = builder(Component.Type.FILE, FILE_REF)
.setKey(FILE_KEY)
@@ -157,20 +160,19 @@ public class IntegrateIssuesVisitorTest {
underTest.visitAny(file);
- verify(issueLifecycle).updateExistingOpenissue(defaultIssueCaptor.capture());
- assertThat(defaultIssueCaptor.getValue().ruleKey().rule()).isEqualTo("x1");
-
verify(issueLifecycle).doAutomaticTransition(defaultIssueCaptor.capture());
assertThat(defaultIssueCaptor.getValue().ruleKey().rule()).isEqualTo("x1");
assertThat(newArrayList(issueCache.traverse())).hasSize(1);
- assertThat(componentsWithUnprocessedIssues.getUuids()).isEmpty();
}
@Test
- public void process_new_issue() throws Exception {
- componentsWithUnprocessedIssues.setUuids(Collections.<String>emptySet());
+ public void process_short_branch_issues() {
+ //TODO
+ }
+ @Test
+ public void process_new_issue() throws Exception {
ScannerReport.Issue reportIssue = ScannerReport.Issue.newBuilder()
.setMsg("the message")
.setRuleRepository("xoo")
@@ -189,12 +191,10 @@ public class IntegrateIssuesVisitorTest {
assertThat(defaultIssueCaptor.getValue().ruleKey().rule()).isEqualTo("S001");
assertThat(newArrayList(issueCache.traverse())).hasSize(1);
- assertThat(componentsWithUnprocessedIssues.getUuids()).isEmpty();
}
@Test
public void process_existing_issue() throws Exception {
- componentsWithUnprocessedIssues.setUuids(newHashSet(FILE_UUID));
RuleKey ruleKey = RuleTesting.XOO_X1;
// Issue from db has severity major
@@ -224,12 +224,10 @@ public class IntegrateIssuesVisitorTest {
assertThat(issues).hasSize(1);
assertThat(issues.get(0).severity()).isEqualTo(Severity.BLOCKER);
- assertThat(componentsWithUnprocessedIssues.getUuids()).isEmpty();
}
@Test
public void execute_issue_visitors() throws Exception {
- componentsWithUnprocessedIssues.setUuids(Collections.<String>emptySet());
ScannerReport.Issue reportIssue = ScannerReport.Issue.newBuilder()
.setMsg("the message")
.setRuleRepository("xoo")
@@ -249,7 +247,6 @@ public class IntegrateIssuesVisitorTest {
@Test
public void close_unmatched_base_issue() throws Exception {
- componentsWithUnprocessedIssues.setUuids(newHashSet(FILE_UUID));
RuleKey ruleKey = RuleTesting.XOO_X1;
addBaseIssue(ruleKey);
@@ -261,20 +258,19 @@ public class IntegrateIssuesVisitorTest {
assertThat(defaultIssueCaptor.getValue().isBeingClosed()).isTrue();
List<DefaultIssue> issues = newArrayList(issueCache.traverse());
assertThat(issues).hasSize(1);
-
- assertThat(componentsWithUnprocessedIssues.getUuids()).isEmpty();
}
@Test
public void remove_uuid_of_original_file_from_componentsWithUnprocessedIssues_if_component_has_one() {
String originalFileUuid = "original file uuid";
- componentsWithUnprocessedIssues.setUuids(newHashSet(FILE_UUID, originalFileUuid));
when(movedFilesRepository.getOriginalFile(FILE))
.thenReturn(Optional.of(new MovedFilesRepository.OriginalFile(4851, originalFileUuid, "original file key")));
underTest.visitAny(FILE);
+ }
+
+ private void addMergeIssue(RuleKey ruleKey) {
- assertThat(componentsWithUnprocessedIssues.getUuids()).isEmpty();
}
private void addBaseIssue(RuleKey ruleKey) {
@@ -293,5 +289,4 @@ public class IntegrateIssuesVisitorTest {
dbTester.getDbClient().issueDao().insert(dbTester.getSession(), issue);
dbTester.getSession().commit();
}
-
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/IssueTrackingDelegatorTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/IssueTrackingDelegatorTest.java
new file mode 100644
index 00000000000..e484c69fb4a
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/IssueTrackingDelegatorTest.java
@@ -0,0 +1,78 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.task.projectanalysis.issue;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import java.util.Optional;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.sonar.db.component.BranchType;
+import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolder;
+import org.sonar.server.computation.task.projectanalysis.analysis.Branch;
+import org.sonar.server.computation.task.projectanalysis.component.Component;
+
+public class IssueTrackingDelegatorTest {
+ @Mock
+ private ShortBranchTrackerExecution shortBranchTracker;
+ @Mock
+ private TrackerExecution tracker;
+ @Mock
+ private AnalysisMetadataHolder analysisMetadataHolder;
+ @Mock
+ private Component component;
+
+ private IssueTrackingDelegator underTest;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ underTest = new IssueTrackingDelegator(shortBranchTracker, tracker, analysisMetadataHolder);
+ }
+
+ @Test
+ public void delegate_regular_tracker() {
+ when(analysisMetadataHolder.getBranch()).thenReturn(Optional.empty());
+
+ underTest.track(component);
+
+ verify(tracker).track(component);
+ verifyZeroInteractions(shortBranchTracker);
+ }
+
+ @Test
+ public void delegate_short_branch_tracker() {
+ Branch branch = mock(Branch.class);
+ when(branch.getType()).thenReturn(BranchType.SHORT);
+ when(analysisMetadataHolder.getBranch()).thenReturn(Optional.of(branch));
+
+ underTest.track(component);
+
+ verify(shortBranchTracker).track(component);
+ verifyZeroInteractions(tracker);
+
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/RemoveProcessedComponentsVisitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/RemoveProcessedComponentsVisitorTest.java
new file mode 100644
index 00000000000..366fa67a145
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/RemoveProcessedComponentsVisitorTest.java
@@ -0,0 +1,72 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.task.projectanalysis.issue;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.server.computation.task.projectanalysis.component.Component;
+import org.sonar.server.computation.task.projectanalysis.filemove.MovedFilesRepository;
+import org.sonar.server.computation.task.projectanalysis.filemove.MovedFilesRepository.OriginalFile;
+
+import com.google.common.base.Optional;
+
+public class RemoveProcessedComponentsVisitorTest {
+ private static final String UUID = "uuid";
+ private ComponentsWithUnprocessedIssues componentsWithUnprocessedIssues = mock(ComponentsWithUnprocessedIssues.class);
+ private MovedFilesRepository movedFilesRepository = mock(MovedFilesRepository.class);
+ private Component component = mock(Component.class);
+ private RemoveProcessedComponentsVisitor underTest = new RemoveProcessedComponentsVisitor(componentsWithUnprocessedIssues, movedFilesRepository);
+
+ @Before
+ public void setUp() {
+ when(component.getUuid()).thenReturn(UUID);
+ }
+
+ @Test
+ public void remove_processed_files() {
+ when(movedFilesRepository.getOriginalFile(any(Component.class))).thenReturn(Optional.absent());
+ underTest.afterComponent(component);
+
+ verify(movedFilesRepository).getOriginalFile(component);
+ verify(componentsWithUnprocessedIssues).remove(UUID);
+ verifyNoMoreInteractions(componentsWithUnprocessedIssues);
+ }
+
+ @Test
+ public void also_remove_moved_files() {
+ String uuid2 = "uuid2";
+ OriginalFile movedFile = new OriginalFile(0, uuid2, "key");
+ when(movedFilesRepository.getOriginalFile(any(Component.class))).thenReturn(Optional.of(movedFile));
+
+ underTest.afterComponent(component);
+
+ verify(movedFilesRepository).getOriginalFile(component);
+ verify(componentsWithUnprocessedIssues).remove(UUID);
+ verify(componentsWithUnprocessedIssues).remove(uuid2);
+
+ verifyNoMoreInteractions(componentsWithUnprocessedIssues);
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/ShortBranchTrackerExecutionTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/ShortBranchTrackerExecutionTest.java
new file mode 100644
index 00000000000..6947b4c4574
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/ShortBranchTrackerExecutionTest.java
@@ -0,0 +1,132 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.task.projectanalysis.issue;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.when;
+import static org.sonar.server.computation.task.projectanalysis.component.ReportComponent.builder;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.core.issue.DefaultIssue;
+import org.sonar.core.issue.tracking.BlockHashSequence;
+import org.sonar.core.issue.tracking.Input;
+import org.sonar.core.issue.tracking.LineHashSequence;
+import org.sonar.core.issue.tracking.Tracker;
+import org.sonar.core.issue.tracking.Tracking;
+import org.sonar.db.rule.RuleTesting;
+import org.sonar.server.computation.task.projectanalysis.component.Component;
+
+public class ShortBranchTrackerExecutionTest {
+ static final String FILE_UUID = "FILE_UUID";
+ static final String FILE_KEY = "FILE_KEY";
+ static final int FILE_REF = 2;
+
+ static final Component FILE = builder(Component.Type.FILE, FILE_REF)
+ .setKey(FILE_KEY)
+ .setUuid(FILE_UUID)
+ .build();
+
+ @Mock
+ private TrackerRawInputFactory rawFactory;
+ @Mock
+ private TrackerBaseInputFactory baseFactory;
+ @Mock
+ private TrackerMergeBranchInputFactory mergeFactory;
+
+ private ShortBranchTrackerExecution underTest;
+
+ private List<DefaultIssue> rawIssues = new ArrayList<>();
+ private List<DefaultIssue> baseIssues = new ArrayList<>();
+ private List<DefaultIssue> mergeBranchIssues = new ArrayList<>();
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ when(rawFactory.create(FILE)).thenReturn(createInput(rawIssues));
+ when(baseFactory.create(FILE)).thenReturn(createInput(baseIssues));
+ when(mergeFactory.create(FILE)).thenReturn(createInput(mergeBranchIssues));
+
+ Tracker<DefaultIssue, DefaultIssue> tracker = new Tracker<>();
+ underTest = new ShortBranchTrackerExecution(baseFactory, rawFactory, mergeFactory, tracker);
+ }
+
+ @Test
+ public void simple_tracking() {
+ rawIssues.add(createIssue(1, RuleTesting.XOO_X1));
+ Tracking<DefaultIssue, DefaultIssue> tracking = underTest.track(FILE);
+ assertThat(tracking.getUnmatchedBases()).isEmpty();
+ assertThat(tracking.getMatchedRaws()).isEmpty();
+ assertThat(tracking.getUnmatchedRaws()).containsOnly(rawIssues.get(0));
+ }
+
+ @Test
+ public void tracking_with_all_results() {
+ rawIssues.add(createIssue(1, RuleTesting.XOO_X1));
+ rawIssues.add(createIssue(2, RuleTesting.XOO_X2));
+ rawIssues.add(createIssue(3, RuleTesting.XOO_X3));
+
+ mergeBranchIssues.add(rawIssues.get(0));
+
+ baseIssues.add(rawIssues.get(0));
+ baseIssues.add(rawIssues.get(1));
+
+ Tracking<DefaultIssue, DefaultIssue> tracking = underTest.track(FILE);
+ assertThat(tracking.getMatchedRaws()).isEqualTo(Collections.singletonMap(rawIssues.get(1), rawIssues.get(1)));
+ assertThat(tracking.getUnmatchedRaws()).containsOnly(rawIssues.get(2));
+ }
+
+ private DefaultIssue createIssue(int line, RuleKey ruleKey) {
+ DefaultIssue issue = new DefaultIssue()
+ .setRuleKey(ruleKey)
+ .setLine(line)
+ .setMessage("msg" + line);
+ return issue;
+ }
+
+ private Input<DefaultIssue> createInput(Collection<DefaultIssue> issues) {
+ return new Input<DefaultIssue>() {
+ @Override
+ public LineHashSequence getLineHashSequence() {
+ return LineHashSequence.createForLines(Arrays.asList("line1", "line2", "line3"));
+ }
+
+ @Override
+ public BlockHashSequence getBlockHashSequence() {
+ return BlockHashSequence.create(getLineHashSequence());
+ }
+
+ @Override
+ public Collection<DefaultIssue> getIssues() {
+ return issues;
+ }
+ };
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerBaseInputFactoryTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerBaseInputFactoryTest.java
index db5b0aa1319..7fc57673ce0 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerBaseInputFactoryTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/issue/TrackerBaseInputFactoryTest.java
@@ -39,14 +39,14 @@ public class TrackerBaseInputFactoryTest {
private static final String FILE_UUID = "uuid";
private static final ReportComponent FILE = ReportComponent.builder(Component.Type.FILE, 1).setUuid(FILE_UUID).build();
- private BaseIssuesLoader baseIssuesLoader = mock(BaseIssuesLoader.class);
+ private ComponentIssuesLoader issuesLoader = mock(ComponentIssuesLoader.class);
private DbClient dbClient = mock(DbClient.class);
private DbSession dbSession = mock(DbSession.class);
private FileSourceDao fileSourceDao = mock(FileSourceDao.class);
private MovedFilesRepository movedFilesRepository = mock(MovedFilesRepository.class);
- private TrackerBaseInputFactory underTest = new TrackerBaseInputFactory(baseIssuesLoader, dbClient, movedFilesRepository);
+ private TrackerBaseInputFactory underTest = new TrackerBaseInputFactory(issuesLoader, dbClient, movedFilesRepository);
@Before
public void setUp() throws Exception {
@@ -68,8 +68,7 @@ public class TrackerBaseInputFactoryTest {
String originalUuid = "original uuid";
when(movedFilesRepository.getOriginalFile(FILE)).thenReturn(
- Optional.of(new MovedFilesRepository.OriginalFile(6542, originalUuid, "original key"))
- );
+ Optional.of(new MovedFilesRepository.OriginalFile(6542, originalUuid, "original key")));
underTest.create(FILE).getLineHashSequence();
@@ -81,7 +80,7 @@ public class TrackerBaseInputFactoryTest {
public void create_returns_Input_which_retrieves_issues_of_specified_file_component_when_it_has_no_original_file() {
underTest.create(FILE).getIssues();
- verify(baseIssuesLoader).loadForComponentUuid(FILE_UUID);
+ verify(issuesLoader).loadForComponentUuid(FILE_UUID);
}
@Test
@@ -89,12 +88,11 @@ public class TrackerBaseInputFactoryTest {
String originalUuid = "original uuid";
when(movedFilesRepository.getOriginalFile(FILE)).thenReturn(
- Optional.of(new MovedFilesRepository.OriginalFile(6542, originalUuid, "original key"))
- );
+ Optional.of(new MovedFilesRepository.OriginalFile(6542, originalUuid, "original key")));
underTest.create(FILE).getIssues();
- verify(baseIssuesLoader).loadForComponentUuid(originalUuid);
- verify(baseIssuesLoader, times(0)).loadForComponentUuid(FILE_UUID);
+ verify(issuesLoader).loadForComponentUuid(originalUuid);
+ verify(issuesLoader, times(0)).loadForComponentUuid(FILE_UUID);
}
}