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.step;
22 import java.util.Arrays;
23 import java.util.Date;
24 import java.util.List;
25 import org.junit.After;
26 import org.junit.Before;
27 import org.junit.Rule;
28 import org.junit.Test;
29 import org.junit.rules.TemporaryFolder;
30 import org.sonar.api.rule.RuleKey;
31 import org.sonar.api.rules.RuleType;
32 import org.sonar.api.utils.System2;
33 import org.sonar.core.issue.DefaultIssue;
34 import org.sonar.core.issue.DefaultIssueComment;
35 import org.sonar.core.issue.FieldDiffs;
36 import org.sonar.db.DbClient;
37 import org.sonar.db.DbSession;
38 import org.sonar.db.DbTester;
39 import org.sonar.db.component.ComponentDto;
40 import org.sonar.db.component.ComponentTesting;
41 import org.sonar.db.issue.IssueChangeDto;
42 import org.sonar.db.issue.IssueDto;
43 import org.sonar.db.organization.OrganizationDto;
44 import org.sonar.db.rule.RuleDefinitionDto;
45 import org.sonar.db.rule.RuleTesting;
46 import org.sonar.scanner.protocol.output.ScannerReport;
47 import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
48 import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReaderRule;
49 import org.sonar.server.computation.task.projectanalysis.issue.IssueCache;
50 import org.sonar.server.computation.task.projectanalysis.issue.RuleRepositoryImpl;
51 import org.sonar.server.computation.task.projectanalysis.issue.UpdateConflictResolver;
52 import org.sonar.server.computation.task.step.ComputationStep;
53 import org.sonar.server.util.cache.DiskCache;
55 import static java.util.Collections.singletonList;
56 import static org.assertj.core.api.Assertions.assertThat;
57 import static org.mockito.Mockito.mock;
58 import static org.mockito.Mockito.when;
59 import static org.sonar.api.issue.Issue.RESOLUTION_FIXED;
60 import static org.sonar.api.issue.Issue.STATUS_CLOSED;
61 import static org.sonar.api.issue.Issue.STATUS_OPEN;
62 import static org.sonar.api.rule.Severity.BLOCKER;
63 import static org.sonar.db.component.ComponentTesting.newFileDto;
65 public class PersistIssuesStepTest extends BaseStepTest {
67 public static final long NOW = 1400000000000L;
70 public TemporaryFolder temp = new TemporaryFolder();
72 public DbTester db = DbTester.create(System2.INSTANCE);
74 public BatchReportReaderRule reportReader = new BatchReportReaderRule();
76 public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule()
77 .setOrganizationUuid("org-1");
79 private DbSession session = db.getSession();
80 private DbClient dbClient = db.getDbClient();
81 private System2 system2;
82 private IssueCache issueCache;
83 private ComputationStep step;
86 protected ComputationStep step() {
91 public void setup() throws Exception {
92 issueCache = new IssueCache(temp.newFile(), System2.INSTANCE);
93 system2 = mock(System2.class);
94 when(system2.now()).thenReturn(NOW);
95 reportReader.setMetadata(ScannerReport.Metadata.getDefaultInstance());
97 step = new PersistIssuesStep(dbClient, system2, new UpdateConflictResolver(), new RuleRepositoryImpl(dbClient, analysisMetadataHolder), issueCache);
101 public void tearDown() {
106 public void insert_copied_issue() {
107 RuleDefinitionDto rule = RuleTesting.newRule(RuleKey.of("xoo", "S01"));
108 db.rules().insert(rule);
109 OrganizationDto organizationDto = db.organizations().insert();
110 ComponentDto project = ComponentTesting.newPrivateProjectDto(organizationDto);
111 dbClient.componentDao().insert(session, project);
112 ComponentDto file = newFileDto(project, null);
113 dbClient.componentDao().insert(session, file);
116 issueCache.newAppender().append(new DefaultIssue()
118 .setType(RuleType.CODE_SMELL)
119 .setRuleKey(rule.getKey())
120 .setComponentUuid(file.uuid())
121 .setProjectUuid(project.uuid())
122 .setSeverity(BLOCKER)
123 .setStatus(STATUS_OPEN)
126 .setType(RuleType.BUG)
127 .addComment(new DefaultIssueComment()
129 .setIssueKey("ISSUE")
130 .setUserLogin("john")
131 .setMarkdownText("Some text")
132 .setCreatedAt(new Date(NOW))
136 .setIssueKey("ISSUE")
137 .setUserLogin("john")
138 .setDiff("technicalDebt", null, 1L)
139 .setCreationDate(new Date(NOW))))
144 IssueDto result = dbClient.issueDao().selectOrFailByKey(session, "ISSUE");
145 assertThat(result.getKey()).isEqualTo("ISSUE");
146 assertThat(result.getRuleKey()).isEqualTo(rule.getKey());
147 assertThat(result.getComponentUuid()).isEqualTo(file.uuid());
148 assertThat(result.getProjectUuid()).isEqualTo(project.uuid());
149 assertThat(result.getSeverity()).isEqualTo(BLOCKER);
150 assertThat(result.getStatus()).isEqualTo(STATUS_OPEN);
151 assertThat(result.getType()).isEqualTo(RuleType.BUG.getDbConstant());
153 List<IssueChangeDto> changes = dbClient.issueChangeDao().selectByIssueKeys(session, Arrays.asList("ISSUE"));
154 assertThat(changes).extracting(IssueChangeDto::getChangeType).containsExactly(IssueChangeDto.TYPE_COMMENT, IssueChangeDto.TYPE_FIELD_CHANGE);
158 public void insert_merged_issue() {
159 RuleDefinitionDto rule = RuleTesting.newRule(RuleKey.of("xoo", "S01"));
160 db.rules().insert(rule);
161 OrganizationDto organizationDto = db.organizations().insert();
162 ComponentDto project = ComponentTesting.newPrivateProjectDto(organizationDto);
163 dbClient.componentDao().insert(session, project);
164 ComponentDto file = newFileDto(project, null);
165 dbClient.componentDao().insert(session, file);
168 issueCache.newAppender().append(new DefaultIssue()
170 .setType(RuleType.CODE_SMELL)
171 .setRuleKey(rule.getKey())
172 .setComponentUuid(file.uuid())
173 .setProjectUuid(project.uuid())
174 .setSeverity(BLOCKER)
175 .setStatus(STATUS_OPEN)
178 .setType(RuleType.BUG)
179 .addComment(new DefaultIssueComment()
181 .setIssueKey("ISSUE")
182 .setUserLogin("john")
183 .setMarkdownText("Some text")
184 .setCreatedAt(new Date(NOW))
186 .setCurrentChange(new FieldDiffs()
187 .setIssueKey("ISSUE")
188 .setUserLogin("john")
189 .setDiff("technicalDebt", null, 1L)
190 .setCreationDate(new Date(NOW))))
194 IssueDto result = dbClient.issueDao().selectOrFailByKey(session, "ISSUE");
195 assertThat(result.getKey()).isEqualTo("ISSUE");
196 assertThat(result.getRuleKey()).isEqualTo(rule.getKey());
197 assertThat(result.getComponentUuid()).isEqualTo(file.uuid());
198 assertThat(result.getProjectUuid()).isEqualTo(project.uuid());
199 assertThat(result.getSeverity()).isEqualTo(BLOCKER);
200 assertThat(result.getStatus()).isEqualTo(STATUS_OPEN);
201 assertThat(result.getType()).isEqualTo(RuleType.BUG.getDbConstant());
203 List<IssueChangeDto> changes = dbClient.issueChangeDao().selectByIssueKeys(session, Arrays.asList("ISSUE"));
204 assertThat(changes).extracting(IssueChangeDto::getChangeType).containsExactly(IssueChangeDto.TYPE_COMMENT, IssueChangeDto.TYPE_FIELD_CHANGE);
208 public void insert_new_issue() {
209 RuleDefinitionDto rule = RuleTesting.newRule(RuleKey.of("xoo", "S01"));
210 db.rules().insert(rule);
211 OrganizationDto organizationDto = db.organizations().insert();
212 ComponentDto project = ComponentTesting.newPrivateProjectDto(organizationDto);
213 dbClient.componentDao().insert(session, project);
214 ComponentDto file = newFileDto(project, null);
215 dbClient.componentDao().insert(session, file);
218 issueCache.newAppender().append(new DefaultIssue()
220 .setType(RuleType.CODE_SMELL)
221 .setRuleKey(rule.getKey())
222 .setComponentUuid(file.uuid())
223 .setProjectUuid(project.uuid())
224 .setSeverity(BLOCKER)
225 .setStatus(STATUS_OPEN)
227 .setType(RuleType.BUG)).close();
231 IssueDto result = dbClient.issueDao().selectOrFailByKey(session, "ISSUE");
232 assertThat(result.getKey()).isEqualTo("ISSUE");
233 assertThat(result.getRuleKey()).isEqualTo(rule.getKey());
234 assertThat(result.getComponentUuid()).isEqualTo(file.uuid());
235 assertThat(result.getProjectUuid()).isEqualTo(project.uuid());
236 assertThat(result.getSeverity()).isEqualTo(BLOCKER);
237 assertThat(result.getStatus()).isEqualTo(STATUS_OPEN);
238 assertThat(result.getType()).isEqualTo(RuleType.BUG.getDbConstant());
242 public void close_issue() {
243 ComponentDto project = db.components().insertPrivateProject();
244 ComponentDto file = db.components().insertComponent(newFileDto(project));
245 RuleDefinitionDto rule = db.rules().insert();
246 IssueDto issue = db.issues().insert(rule, project, file,
247 i -> i.setStatus(STATUS_OPEN)
249 .setCreatedAt(NOW - 1_000_000_000L)
250 .setUpdatedAt(NOW - 1_000_000_000L));
251 DiskCache<DefaultIssue>.DiskAppender issueCacheAppender = issueCache.newAppender();
253 issueCacheAppender.append(
254 issue.toDefaultIssue()
255 .setStatus(STATUS_CLOSED)
256 .setResolution(RESOLUTION_FIXED)
263 IssueDto issueReloaded = db.getDbClient().issueDao().selectByKey(db.getSession(), issue.getKey()).get();
264 assertThat(issueReloaded.getStatus()).isEqualTo(STATUS_CLOSED);
265 assertThat(issueReloaded.getResolution()).isEqualTo(RESOLUTION_FIXED);
269 public void add_comment() {
270 ComponentDto project = db.components().insertPrivateProject();
271 ComponentDto file = db.components().insertComponent(newFileDto(project));
272 RuleDefinitionDto rule = db.rules().insert();
273 IssueDto issue = db.issues().insert(rule, project, file,
274 i -> i.setStatus(STATUS_OPEN)
276 .setCreatedAt(NOW - 1_000_000_000L)
277 .setUpdatedAt(NOW - 1_000_000_000L));
278 DiskCache<DefaultIssue>.DiskAppender issueCacheAppender = issueCache.newAppender();
280 issueCacheAppender.append(
281 issue.toDefaultIssue()
282 .setStatus(STATUS_CLOSED)
283 .setResolution(RESOLUTION_FIXED)
287 .addComment(new DefaultIssueComment()
289 .setIssueKey(issue.getKey())
290 .setUserLogin("john")
291 .setMarkdownText("Some text")
292 .setCreatedAt(new Date(NOW))
297 IssueChangeDto issueChangeDto = db.getDbClient().issueChangeDao().selectByIssueKeys(db.getSession(), singletonList(issue.getKey())).get(0);
298 assertThat(issueChangeDto)
299 .extracting(IssueChangeDto::getChangeType, IssueChangeDto::getUserLogin, IssueChangeDto::getChangeData, IssueChangeDto::getIssueKey,
300 IssueChangeDto::getIssueChangeCreationDate)
301 .containsOnly(IssueChangeDto.TYPE_COMMENT, "john", "Some text", issue.getKey(), NOW);
305 public void add_change() {
306 ComponentDto project = db.components().insertPrivateProject();
307 ComponentDto file = db.components().insertComponent(newFileDto(project));
308 RuleDefinitionDto rule = db.rules().insert();
309 IssueDto issue = db.issues().insert(rule, project, file,
310 i -> i.setStatus(STATUS_OPEN)
312 .setCreatedAt(NOW - 1_000_000_000L)
313 .setUpdatedAt(NOW - 1_000_000_000L));
314 DiskCache<DefaultIssue>.DiskAppender issueCacheAppender = issueCache.newAppender();
316 issueCacheAppender.append(
317 issue.toDefaultIssue()
318 .setStatus(STATUS_CLOSED)
319 .setResolution(RESOLUTION_FIXED)
323 .setCurrentChange(new FieldDiffs()
324 .setIssueKey("ISSUE")
325 .setUserLogin("john")
326 .setDiff("technicalDebt", null, 1L)
327 .setCreationDate(new Date(NOW))))
331 IssueChangeDto issueChangeDto = db.getDbClient().issueChangeDao().selectByIssueKeys(db.getSession(), singletonList(issue.getKey())).get(0);
332 assertThat(issueChangeDto)
333 .extracting(IssueChangeDto::getChangeType, IssueChangeDto::getUserLogin, IssueChangeDto::getChangeData, IssueChangeDto::getIssueKey,
334 IssueChangeDto::getIssueChangeCreationDate)
335 .containsOnly(IssueChangeDto.TYPE_FIELD_CHANGE, "john", "technicalDebt=1", issue.getKey(), NOW);