]> source.dussan.org Git - sonarqube.git/blob
5b13b2ea7f84c4d8a728488ccd3258e6062ed7dd
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2017 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
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.
10  *
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.
15  *
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.
19  */
20 package org.sonar.server.computation.task.projectanalysis.issue;
21
22 import com.google.common.collect.ImmutableMap;
23 import java.util.Date;
24 import org.junit.Rule;
25 import org.junit.Test;
26 import org.sonar.api.utils.Duration;
27 import org.sonar.core.issue.DefaultIssue;
28 import org.sonar.core.issue.DefaultIssueComment;
29 import org.sonar.core.issue.IssueChangeContext;
30 import org.sonar.db.protobuf.DbCommons;
31 import org.sonar.db.protobuf.DbIssues;
32 import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
33 import org.sonar.server.computation.task.projectanalysis.analysis.Branch;
34 import org.sonar.server.issue.IssueFieldsSetter;
35 import org.sonar.server.issue.workflow.IssueWorkflow;
36
37 import static com.google.common.collect.Lists.newArrayList;
38 import static org.assertj.core.api.Assertions.assertThat;
39 import static org.mockito.Mockito.mock;
40 import static org.mockito.Mockito.never;
41 import static org.mockito.Mockito.verify;
42 import static org.mockito.Mockito.verifyZeroInteractions;
43 import static org.mockito.Mockito.when;
44 import static org.sonar.api.issue.Issue.RESOLUTION_FIXED;
45 import static org.sonar.api.issue.Issue.STATUS_CLOSED;
46 import static org.sonar.api.issue.Issue.STATUS_OPEN;
47 import static org.sonar.api.rule.Severity.BLOCKER;
48 import static org.sonar.api.utils.DateUtils.parseDate;
49
50 public class IssueLifecycleTest {
51
52   static final Date DEFAULT_DATE = new Date();
53
54   static final Duration DEFAULT_DURATION = Duration.create(10);
55
56   IssueChangeContext issueChangeContext = IssueChangeContext.createUser(DEFAULT_DATE, "julien");
57
58   IssueWorkflow workflow = mock(IssueWorkflow.class);
59
60   IssueFieldsSetter updater = mock(IssueFieldsSetter.class);
61
62   DebtCalculator debtCalculator = mock(DebtCalculator.class);
63
64   @Rule
65   public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
66
67   IssueLifecycle underTest = new IssueLifecycle(analysisMetadataHolder, issueChangeContext, workflow, updater, debtCalculator);
68
69   @Test
70   public void initNewOpenIssue() throws Exception {
71     DefaultIssue issue = new DefaultIssue();
72     when(debtCalculator.calculate(issue)).thenReturn(DEFAULT_DURATION);
73
74     underTest.initNewOpenIssue(issue);
75
76     assertThat(issue.key()).isNotNull();
77     assertThat(issue.creationDate()).isNotNull();
78     assertThat(issue.updateDate()).isNotNull();
79     assertThat(issue.status()).isEqualTo(STATUS_OPEN);
80     assertThat(issue.debt()).isEqualTo(DEFAULT_DURATION);
81     assertThat(issue.isNew()).isTrue();
82     assertThat(issue.isCopied()).isFalse();
83   }
84
85   @Test
86   public void mergeIssueFromShortLivingBranch() {
87     DefaultIssue raw = new DefaultIssue();
88     DefaultIssue fromShort = new DefaultIssue();
89     fromShort.setResolution("resolution");
90     fromShort.setStatus("status");
91
92     Date commentDate = new Date();
93     fromShort.addComment(new DefaultIssueComment()
94       .setIssueKey("short")
95       .setCreatedAt(commentDate)
96       .setUserLogin("user")
97       .setMarkdownText("A comment"));
98
99     Branch branch = mock(Branch.class);
100     when(branch.getName()).thenReturn("master");
101     analysisMetadataHolder.setBranch(branch);
102
103     underTest.mergeConfirmedOrResolvedFromShortLivingBranch(raw, fromShort, "feature/foo");
104     assertThat(raw.resolution()).isEqualTo("resolution");
105     assertThat(raw.status()).isEqualTo("status");
106     assertThat(raw.changes().get(0).get(IssueFieldsSetter.FROM_SHORT_BRANCH).oldValue()).isEqualTo("feature/foo");
107     assertThat(raw.changes().get(0).get(IssueFieldsSetter.FROM_SHORT_BRANCH).newValue()).isEqualTo("master");
108   }
109
110   @Test
111   public void copiedIssue() throws Exception {
112     DefaultIssue raw = new DefaultIssue()
113       .setNew(true)
114       .setKey("RAW_KEY")
115       .setCreationDate(parseDate("2015-10-01"))
116       .setUpdateDate(parseDate("2015-10-02"))
117       .setCloseDate(parseDate("2015-10-03"));
118
119     DbIssues.Locations issueLocations = DbIssues.Locations.newBuilder()
120       .setTextRange(DbCommons.TextRange.newBuilder()
121         .setStartLine(10)
122         .setEndLine(12)
123         .build())
124       .build();
125     DefaultIssue base = new DefaultIssue()
126       .setKey("BASE_KEY")
127       .setCreationDate(parseDate("2015-01-01"))
128       .setUpdateDate(parseDate("2015-01-02"))
129       .setCloseDate(parseDate("2015-01-03"))
130       .setResolution(RESOLUTION_FIXED)
131       .setStatus(STATUS_CLOSED)
132       .setSeverity(BLOCKER)
133       .setAssignee("base assignee")
134       .setAuthorLogin("base author")
135       .setTags(newArrayList("base tag"))
136       .setOnDisabledRule(true)
137       .setSelectedAt(1000L)
138       .setLine(10)
139       .setMessage("message")
140       .setGap(15d)
141       .setEffort(Duration.create(15L))
142       .setManualSeverity(false)
143       .setLocations(issueLocations);
144
145     when(debtCalculator.calculate(raw)).thenReturn(DEFAULT_DURATION);
146
147     Branch branch = mock(Branch.class);
148     when(branch.getName()).thenReturn("release-2.x");
149     analysisMetadataHolder.setBranch(branch);
150
151     underTest.copyExistingOpenIssueFromLongLivingBranch(raw, base, "master");
152
153     assertThat(raw.isNew()).isFalse();
154     assertThat(raw.isCopied()).isTrue();
155     assertThat(raw.key()).isNotNull();
156     assertThat(raw.key()).isNotEqualTo(base.key());
157     assertThat(raw.creationDate()).isEqualTo(base.creationDate());
158     assertThat(raw.updateDate()).isEqualTo(base.updateDate());
159     assertThat(raw.closeDate()).isEqualTo(base.closeDate());
160     assertThat(raw.resolution()).isEqualTo(RESOLUTION_FIXED);
161     assertThat(raw.status()).isEqualTo(STATUS_CLOSED);
162     assertThat(raw.assignee()).isEqualTo("base assignee");
163     assertThat(raw.authorLogin()).isEqualTo("base author");
164     assertThat(raw.tags()).containsOnly("base tag");
165     assertThat(raw.debt()).isEqualTo(DEFAULT_DURATION);
166     assertThat(raw.isOnDisabledRule()).isTrue();
167     assertThat(raw.selectedAt()).isEqualTo(1000L);
168     assertThat(raw.changes().get(0).get(IssueFieldsSetter.FROM_LONG_BRANCH).oldValue()).isEqualTo("master");
169     assertThat(raw.changes().get(0).get(IssueFieldsSetter.FROM_LONG_BRANCH).newValue()).isEqualTo("release-2.x");
170
171     verifyZeroInteractions(updater);
172   }
173
174   @Test
175   public void doAutomaticTransition() throws Exception {
176     DefaultIssue issue = new DefaultIssue();
177
178     underTest.doAutomaticTransition(issue);
179
180     verify(workflow).doAutomaticTransition(issue, issueChangeContext);
181   }
182
183   @Test
184   public void mergeExistingOpenIssue() throws Exception {
185     DefaultIssue raw = new DefaultIssue()
186       .setNew(true)
187       .setKey("RAW_KEY")
188       .setCreationDate(parseDate("2015-10-01"))
189       .setUpdateDate(parseDate("2015-10-02"))
190       .setCloseDate(parseDate("2015-10-03"));
191
192     DbIssues.Locations issueLocations = DbIssues.Locations.newBuilder()
193       .setTextRange(DbCommons.TextRange.newBuilder()
194         .setStartLine(10)
195         .setEndLine(12)
196         .build())
197       .build();
198     DefaultIssue base = new DefaultIssue()
199       .setKey("BASE_KEY")
200       .setCreationDate(parseDate("2015-01-01"))
201       .setUpdateDate(parseDate("2015-01-02"))
202       .setCloseDate(parseDate("2015-01-03"))
203       .setResolution(RESOLUTION_FIXED)
204       .setStatus(STATUS_CLOSED)
205       .setSeverity(BLOCKER)
206       .setAssignee("base assignee")
207       .setAuthorLogin("base author")
208       .setTags(newArrayList("base tag"))
209       .setOnDisabledRule(true)
210       .setSelectedAt(1000L)
211       .setLine(10)
212       .setMessage("message")
213       .setGap(15d)
214       .setEffort(Duration.create(15L))
215       .setManualSeverity(false)
216       .setLocations(issueLocations);
217
218     when(debtCalculator.calculate(raw)).thenReturn(DEFAULT_DURATION);
219
220     underTest.mergeExistingOpenIssue(raw, base);
221
222     assertThat(raw.isNew()).isFalse();
223     assertThat(raw.key()).isEqualTo("BASE_KEY");
224     assertThat(raw.creationDate()).isEqualTo(base.creationDate());
225     assertThat(raw.updateDate()).isEqualTo(base.updateDate());
226     assertThat(raw.closeDate()).isEqualTo(base.closeDate());
227     assertThat(raw.resolution()).isEqualTo(RESOLUTION_FIXED);
228     assertThat(raw.status()).isEqualTo(STATUS_CLOSED);
229     assertThat(raw.assignee()).isEqualTo("base assignee");
230     assertThat(raw.authorLogin()).isEqualTo("base author");
231     assertThat(raw.tags()).containsOnly("base tag");
232     assertThat(raw.debt()).isEqualTo(DEFAULT_DURATION);
233     assertThat(raw.isOnDisabledRule()).isTrue();
234     assertThat(raw.selectedAt()).isEqualTo(1000L);
235
236     verify(updater).setPastSeverity(raw, BLOCKER, issueChangeContext);
237     verify(updater).setPastLine(raw, 10);
238     verify(updater).setPastMessage(raw, "message", issueChangeContext);
239     verify(updater).setPastEffort(raw, Duration.create(15L), issueChangeContext);
240     verify(updater).setPastLocations(raw, issueLocations);
241   }
242
243   @Test
244   public void mergeExistingOpenIssue_with_manual_severity() throws Exception {
245     DefaultIssue raw = new DefaultIssue()
246       .setNew(true)
247       .setKey("RAW_KEY");
248     DefaultIssue base = new DefaultIssue()
249       .setKey("BASE_KEY")
250       .setResolution(RESOLUTION_FIXED)
251       .setStatus(STATUS_CLOSED)
252       .setSeverity(BLOCKER)
253       .setManualSeverity(true);
254
255     underTest.mergeExistingOpenIssue(raw, base);
256
257     assertThat(raw.manualSeverity()).isTrue();
258     assertThat(raw.severity()).isEqualTo(BLOCKER);
259
260     verify(updater, never()).setPastSeverity(raw, BLOCKER, issueChangeContext);
261   }
262
263   @Test
264   public void mergeExistingOpenIssue_with_attributes() throws Exception {
265     DefaultIssue raw = new DefaultIssue()
266       .setNew(true)
267       .setKey("RAW_KEY");
268     DefaultIssue base = new DefaultIssue()
269       .setKey("BASE_KEY")
270       .setResolution(RESOLUTION_FIXED)
271       .setStatus(STATUS_CLOSED)
272       .setSeverity(BLOCKER)
273       .setAttributes(ImmutableMap.of("JIRA", "SONAR-01"));
274
275     underTest.mergeExistingOpenIssue(raw, base);
276
277     assertThat(raw.attributes()).containsEntry("JIRA", "SONAR-01");
278   }
279 }