3 * Copyright (C) 2009-2017 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.server.computation.task.projectanalysis.issue;
22 import com.google.common.collect.ImmutableMap;
23 import java.util.Date;
24 import org.junit.Test;
25 import org.sonar.api.utils.Duration;
26 import org.sonar.core.issue.DefaultIssue;
27 import org.sonar.core.issue.IssueChangeContext;
28 import org.sonar.db.protobuf.DbCommons;
29 import org.sonar.db.protobuf.DbIssues;
30 import org.sonar.server.issue.IssueFieldsSetter;
31 import org.sonar.server.issue.workflow.IssueWorkflow;
33 import static com.google.common.collect.Lists.newArrayList;
34 import static org.assertj.core.api.Assertions.assertThat;
35 import static org.mockito.Mockito.mock;
36 import static org.mockito.Mockito.never;
37 import static org.mockito.Mockito.verify;
38 import static org.mockito.Mockito.verifyZeroInteractions;
39 import static org.mockito.Mockito.when;
40 import static org.sonar.api.issue.Issue.RESOLUTION_FIXED;
41 import static org.sonar.api.issue.Issue.STATUS_CLOSED;
42 import static org.sonar.api.issue.Issue.STATUS_OPEN;
43 import static org.sonar.api.rule.Severity.BLOCKER;
44 import static org.sonar.api.utils.DateUtils.parseDate;
46 public class IssueLifecycleTest {
48 static final Date DEFAULT_DATE = new Date();
50 static final Duration DEFAULT_DURATION = Duration.create(10);
52 IssueChangeContext issueChangeContext = IssueChangeContext.createUser(DEFAULT_DATE, "julien");
54 IssueWorkflow workflow = mock(IssueWorkflow.class);
56 IssueFieldsSetter updater = mock(IssueFieldsSetter.class);
58 DebtCalculator debtCalculator = mock(DebtCalculator.class);
60 IssueLifecycle underTest = new IssueLifecycle(issueChangeContext, workflow, updater, debtCalculator);
63 public void initNewOpenIssue() throws Exception {
64 DefaultIssue issue = new DefaultIssue();
65 when(debtCalculator.calculate(issue)).thenReturn(DEFAULT_DURATION);
67 underTest.initNewOpenIssue(issue);
69 assertThat(issue.key()).isNotNull();
70 assertThat(issue.creationDate()).isNotNull();
71 assertThat(issue.updateDate()).isNotNull();
72 assertThat(issue.status()).isEqualTo(STATUS_OPEN);
73 assertThat(issue.debt()).isEqualTo(DEFAULT_DURATION);
74 assertThat(issue.isNew()).isTrue();
75 assertThat(issue.isCopied()).isFalse();
79 public void mergeIssueFromShortLivingBranch() {
80 DefaultIssue raw = new DefaultIssue();
81 DefaultIssue fromShort = new DefaultIssue();
82 fromShort.setResolution("resolution");
83 fromShort.setStatus("status");
84 underTest.mergeIssueFromShortLivingBranch(raw, fromShort);
85 assertThat(raw.resolution()).isEqualTo("resolution");
86 assertThat(raw.status()).isEqualTo("status");
90 public void copiedIssue() throws Exception {
91 DefaultIssue raw = new DefaultIssue()
94 .setCreationDate(parseDate("2015-10-01"))
95 .setUpdateDate(parseDate("2015-10-02"))
96 .setCloseDate(parseDate("2015-10-03"));
98 DbIssues.Locations issueLocations = DbIssues.Locations.newBuilder()
99 .setTextRange(DbCommons.TextRange.newBuilder()
104 DefaultIssue base = new DefaultIssue()
106 .setCreationDate(parseDate("2015-01-01"))
107 .setUpdateDate(parseDate("2015-01-02"))
108 .setCloseDate(parseDate("2015-01-03"))
109 .setResolution(RESOLUTION_FIXED)
110 .setStatus(STATUS_CLOSED)
111 .setSeverity(BLOCKER)
112 .setAssignee("base assignee")
113 .setAuthorLogin("base author")
114 .setTags(newArrayList("base tag"))
115 .setOnDisabledRule(true)
116 .setSelectedAt(1000L)
118 .setMessage("message")
120 .setEffort(Duration.create(15L))
121 .setManualSeverity(false)
122 .setLocations(issueLocations);
124 when(debtCalculator.calculate(raw)).thenReturn(DEFAULT_DURATION);
126 underTest.copyExistingOpenIssueFromLongLivingBranch(raw, base);
128 assertThat(raw.isNew()).isFalse();
129 assertThat(raw.isCopied()).isTrue();
130 assertThat(raw.key()).isNotNull();
131 assertThat(raw.key()).isNotEqualTo(base.key());
132 assertThat(raw.creationDate()).isEqualTo(base.creationDate());
133 assertThat(raw.updateDate()).isEqualTo(base.updateDate());
134 assertThat(raw.closeDate()).isEqualTo(base.closeDate());
135 assertThat(raw.resolution()).isEqualTo(RESOLUTION_FIXED);
136 assertThat(raw.status()).isEqualTo(STATUS_CLOSED);
137 assertThat(raw.assignee()).isEqualTo("base assignee");
138 assertThat(raw.authorLogin()).isEqualTo("base author");
139 assertThat(raw.tags()).containsOnly("base tag");
140 assertThat(raw.debt()).isEqualTo(DEFAULT_DURATION);
141 assertThat(raw.isOnDisabledRule()).isTrue();
142 assertThat(raw.selectedAt()).isEqualTo(1000L);
144 verifyZeroInteractions(updater);
148 public void doAutomaticTransition() throws Exception {
149 DefaultIssue issue = new DefaultIssue();
151 underTest.doAutomaticTransition(issue);
153 verify(workflow).doAutomaticTransition(issue, issueChangeContext);
157 public void mergeExistingOpenIssue() throws Exception {
158 DefaultIssue raw = new DefaultIssue()
161 .setCreationDate(parseDate("2015-10-01"))
162 .setUpdateDate(parseDate("2015-10-02"))
163 .setCloseDate(parseDate("2015-10-03"));
165 DbIssues.Locations issueLocations = DbIssues.Locations.newBuilder()
166 .setTextRange(DbCommons.TextRange.newBuilder()
171 DefaultIssue base = new DefaultIssue()
173 .setCreationDate(parseDate("2015-01-01"))
174 .setUpdateDate(parseDate("2015-01-02"))
175 .setCloseDate(parseDate("2015-01-03"))
176 .setResolution(RESOLUTION_FIXED)
177 .setStatus(STATUS_CLOSED)
178 .setSeverity(BLOCKER)
179 .setAssignee("base assignee")
180 .setAuthorLogin("base author")
181 .setTags(newArrayList("base tag"))
182 .setOnDisabledRule(true)
183 .setSelectedAt(1000L)
185 .setMessage("message")
187 .setEffort(Duration.create(15L))
188 .setManualSeverity(false)
189 .setLocations(issueLocations);
191 when(debtCalculator.calculate(raw)).thenReturn(DEFAULT_DURATION);
193 underTest.mergeExistingOpenIssue(raw, base);
195 assertThat(raw.isNew()).isFalse();
196 assertThat(raw.key()).isEqualTo("BASE_KEY");
197 assertThat(raw.creationDate()).isEqualTo(base.creationDate());
198 assertThat(raw.updateDate()).isEqualTo(base.updateDate());
199 assertThat(raw.closeDate()).isEqualTo(base.closeDate());
200 assertThat(raw.resolution()).isEqualTo(RESOLUTION_FIXED);
201 assertThat(raw.status()).isEqualTo(STATUS_CLOSED);
202 assertThat(raw.assignee()).isEqualTo("base assignee");
203 assertThat(raw.authorLogin()).isEqualTo("base author");
204 assertThat(raw.tags()).containsOnly("base tag");
205 assertThat(raw.debt()).isEqualTo(DEFAULT_DURATION);
206 assertThat(raw.isOnDisabledRule()).isTrue();
207 assertThat(raw.selectedAt()).isEqualTo(1000L);
209 verify(updater).setPastSeverity(raw, BLOCKER, issueChangeContext);
210 verify(updater).setPastLine(raw, 10);
211 verify(updater).setPastMessage(raw, "message", issueChangeContext);
212 verify(updater).setPastEffort(raw, Duration.create(15L), issueChangeContext);
213 verify(updater).setPastLocations(raw, issueLocations);
217 public void mergeExistingOpenIssue_with_manual_severity() throws Exception {
218 DefaultIssue raw = new DefaultIssue()
221 DefaultIssue base = new DefaultIssue()
223 .setResolution(RESOLUTION_FIXED)
224 .setStatus(STATUS_CLOSED)
225 .setSeverity(BLOCKER)
226 .setManualSeverity(true);
228 underTest.mergeExistingOpenIssue(raw, base);
230 assertThat(raw.manualSeverity()).isTrue();
231 assertThat(raw.severity()).isEqualTo(BLOCKER);
233 verify(updater, never()).setPastSeverity(raw, BLOCKER, issueChangeContext);
237 public void mergeExistingOpenIssue_with_attributes() throws Exception {
238 DefaultIssue raw = new DefaultIssue()
241 DefaultIssue base = new DefaultIssue()
243 .setResolution(RESOLUTION_FIXED)
244 .setStatus(STATUS_CLOSED)
245 .setSeverity(BLOCKER)
246 .setAttributes(ImmutableMap.of("JIRA", "SONAR-01"));
248 underTest.mergeExistingOpenIssue(raw, base);
250 assertThat(raw.attributes()).containsEntry("JIRA", "SONAR-01");