aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-server
diff options
context:
space:
mode:
Diffstat (limited to 'server/sonar-server')
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueLifecycle.java13
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/issue/IssueLifecycleTest.java181
2 files changed, 190 insertions, 4 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueLifecycle.java b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueLifecycle.java
index 30b4ccac84b..93cbffd32cd 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueLifecycle.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueLifecycle.java
@@ -19,13 +19,14 @@
*/
package org.sonar.server.computation.issue;
+import com.google.common.annotations.VisibleForTesting;
import javax.annotation.Nullable;
import org.sonar.api.issue.Issue;
-import org.sonar.core.util.Uuids;
import org.sonar.core.issue.DefaultIssue;
import org.sonar.core.issue.IssueChangeContext;
import org.sonar.core.issue.IssueUpdater;
import org.sonar.core.issue.workflow.IssueWorkflow;
+import org.sonar.core.util.Uuids;
import org.sonar.server.computation.analysis.AnalysisMetadataHolder;
/**
@@ -44,10 +45,15 @@ public class IssueLifecycle {
private final DebtCalculator debtCalculator;
public IssueLifecycle(AnalysisMetadataHolder analysisMetadataHolder, IssueWorkflow workflow, IssueUpdater updater, DebtCalculator debtCalculator) {
+ this(IssueChangeContext.createScan(analysisMetadataHolder.getAnalysisDate()), workflow, updater, debtCalculator);
+ }
+
+ @VisibleForTesting
+ IssueLifecycle(IssueChangeContext changeContext, IssueWorkflow workflow, IssueUpdater updater, DebtCalculator debtCalculator) {
this.workflow = workflow;
this.updater = updater;
this.debtCalculator = debtCalculator;
- this.changeContext = IssueChangeContext.createScan(analysisMetadataHolder.getAnalysisDate());
+ this.changeContext = changeContext;
}
public void initNewOpenIssue(DefaultIssue issue) {
@@ -70,6 +76,7 @@ public class IssueLifecycle {
raw.setAssignee(base.assignee());
raw.setAuthorLogin(base.authorLogin());
raw.setTags(base.tags());
+ raw.setAttributes(base.attributes());
raw.setDebt(debtCalculator.calculate(raw));
raw.setOnDisabledRule(base.isOnDisabledRule());
if (base.manualSeverity()) {
@@ -79,8 +86,6 @@ public class IssueLifecycle {
updater.setPastSeverity(raw, base.severity(), changeContext);
}
- // TODO attributes
-
// fields coming from raw
updater.setPastLine(raw, base.getLine());
updater.setPastMessage(raw, base.getMessage(), changeContext);
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/issue/IssueLifecycleTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/issue/IssueLifecycleTest.java
new file mode 100644
index 00000000000..80fbd779a46
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/issue/IssueLifecycleTest.java
@@ -0,0 +1,181 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.issue;
+
+import com.google.common.collect.ImmutableMap;
+import java.util.Date;
+import org.junit.Test;
+import org.sonar.api.utils.Duration;
+import org.sonar.core.issue.DefaultIssue;
+import org.sonar.core.issue.IssueChangeContext;
+import org.sonar.core.issue.IssueUpdater;
+import org.sonar.core.issue.workflow.IssueWorkflow;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.sonar.api.issue.Issue.RESOLUTION_FIXED;
+import static org.sonar.api.issue.Issue.STATUS_CLOSED;
+import static org.sonar.api.issue.Issue.STATUS_OPEN;
+import static org.sonar.api.rule.Severity.BLOCKER;
+import static org.sonar.api.utils.DateUtils.parseDate;
+
+public class IssueLifecycleTest {
+
+ static final Date DEFAULT_DATE = new Date();
+
+ static final Duration DEFAULT_DURATION = Duration.create(10);
+
+ IssueChangeContext issueChangeContext = IssueChangeContext.createUser(DEFAULT_DATE, "julien");
+
+ IssueWorkflow workflow = mock(IssueWorkflow.class);
+
+ IssueUpdater updater = mock(IssueUpdater.class);
+
+ DebtCalculator debtCalculator = mock(DebtCalculator.class);
+
+ IssueLifecycle underTest = new IssueLifecycle(issueChangeContext, workflow, updater, debtCalculator);
+
+ @Test
+ public void initNewOpenIssue() throws Exception {
+ DefaultIssue issue = new DefaultIssue();
+ when(debtCalculator.calculate(issue)).thenReturn(DEFAULT_DURATION);
+
+ underTest.initNewOpenIssue(issue);
+
+ assertThat(issue.key()).isNotNull();
+ assertThat(issue.creationDate()).isNotNull();
+ assertThat(issue.updateDate()).isNotNull();
+ assertThat(issue.status()).isEqualTo(STATUS_OPEN);
+ assertThat(issue.debt()).isEqualTo(DEFAULT_DURATION);
+ }
+
+ @Test
+ public void moveOpenManualIssue() throws Exception {
+ DefaultIssue issue = new DefaultIssue();
+
+ underTest.moveOpenManualIssue(issue, 1);
+
+ verify(updater).setLine(issue, 1);
+ }
+
+ @Test
+ public void doAutomaticTransition() throws Exception {
+ DefaultIssue issue = new DefaultIssue();
+
+ underTest.doAutomaticTransition(issue);
+
+ verify(workflow).doAutomaticTransition(issue, issueChangeContext);
+ }
+
+ @Test
+ public void mergeExistingOpenIssue() throws Exception {
+ DefaultIssue raw = new DefaultIssue()
+ .setNew(true)
+ .setKey("RAW_KEY")
+ .setCreationDate(parseDate("2015-10-01"))
+ .setUpdateDate(parseDate("2015-10-02"))
+ .setCloseDate(parseDate("2015-10-03"));
+ DefaultIssue base = new DefaultIssue()
+ .setKey("BASE_KEY")
+ .setCreationDate(parseDate("2015-01-01"))
+ .setUpdateDate(parseDate("2015-01-02"))
+ .setCloseDate(parseDate("2015-01-03"))
+ .setActionPlanKey("BASE_ACTION_PLAN_KEY")
+ .setResolution(RESOLUTION_FIXED)
+ .setStatus(STATUS_CLOSED)
+ .setSeverity(BLOCKER)
+ .setAssignee("base assignee")
+ .setAuthorLogin("base author")
+ .setTags(newArrayList("base tag"))
+ .setOnDisabledRule(true)
+ .setSelectedAt(1000L)
+ .setLine(10)
+ .setMessage("message")
+ .setEffortToFix(15d)
+ .setDebt(Duration.create(15L))
+ .setManualSeverity(false);
+
+ when(debtCalculator.calculate(raw)).thenReturn(DEFAULT_DURATION);
+
+ underTest.mergeExistingOpenIssue(raw, base);
+
+ assertThat(raw.isNew()).isFalse();
+ assertThat(raw.key()).isEqualTo("BASE_KEY");
+ assertThat(raw.creationDate()).isEqualTo(base.creationDate());
+ assertThat(raw.updateDate()).isEqualTo(base.updateDate());
+ assertThat(raw.closeDate()).isEqualTo(base.closeDate());
+ assertThat(raw.actionPlanKey()).isEqualTo("BASE_ACTION_PLAN_KEY");
+ assertThat(raw.resolution()).isEqualTo(RESOLUTION_FIXED);
+ assertThat(raw.status()).isEqualTo(STATUS_CLOSED);
+ assertThat(raw.assignee()).isEqualTo("base assignee");
+ assertThat(raw.authorLogin()).isEqualTo("base author");
+ assertThat(raw.tags()).containsOnly("base tag");
+ assertThat(raw.debt()).isEqualTo(DEFAULT_DURATION);
+ assertThat(raw.isOnDisabledRule()).isTrue();
+ assertThat(raw.selectedAt()).isEqualTo(1000L);
+
+ verify(updater).setPastSeverity(raw, BLOCKER, issueChangeContext);
+ verify(updater).setPastLine(raw, 10);
+ verify(updater).setPastMessage(raw, "message", issueChangeContext);
+ verify(updater).setPastTechnicalDebt(raw, Duration.create(15L), issueChangeContext);
+ }
+
+ @Test
+ public void mergeExistingOpenIssue_with_manual_severity() throws Exception {
+ DefaultIssue raw = new DefaultIssue()
+ .setNew(true)
+ .setKey("RAW_KEY");
+ DefaultIssue base = new DefaultIssue()
+ .setKey("BASE_KEY")
+ .setResolution(RESOLUTION_FIXED)
+ .setStatus(STATUS_CLOSED)
+ .setSeverity(BLOCKER)
+ .setManualSeverity(true);
+
+ underTest.mergeExistingOpenIssue(raw, base);
+
+ assertThat(raw.manualSeverity()).isTrue();
+ assertThat(raw.severity()).isEqualTo(BLOCKER);
+
+ verify(updater, never()).setPastSeverity(raw, BLOCKER, issueChangeContext);
+ }
+
+ @Test
+ public void mergeExistingOpenIssue_with_attributes() throws Exception {
+ DefaultIssue raw = new DefaultIssue()
+ .setNew(true)
+ .setKey("RAW_KEY");
+ DefaultIssue base = new DefaultIssue()
+ .setKey("BASE_KEY")
+ .setResolution(RESOLUTION_FIXED)
+ .setStatus(STATUS_CLOSED)
+ .setSeverity(BLOCKER)
+ .setAttributes(ImmutableMap.of("JIRA", "SONAR-01"));
+
+ underTest.mergeExistingOpenIssue(raw, base);
+
+ assertThat(raw.attributes()).containsEntry("JIRA", "SONAR-01");
+ }
+}