]> source.dussan.org Git - sonarqube.git/blob
ae12303dc0aab16bcd641001eb93bcbc1c819977
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2023 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.ce.task.projectanalysis.step;
21
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.mockito.ArgumentCaptor;
31 import org.sonar.api.issue.impact.Severity;
32 import org.sonar.api.issue.impact.SoftwareQuality;
33 import org.sonar.api.rule.RuleKey;
34 import org.sonar.api.rules.RuleType;
35 import org.sonar.api.utils.System2;
36 import org.sonar.ce.task.projectanalysis.batch.BatchReportReaderRule;
37 import org.sonar.ce.task.projectanalysis.issue.AdHocRuleCreator;
38 import org.sonar.ce.task.projectanalysis.issue.ProtoIssueCache;
39 import org.sonar.ce.task.projectanalysis.issue.RuleRepositoryImpl;
40 import org.sonar.ce.task.projectanalysis.issue.UpdateConflictResolver;
41 import org.sonar.ce.task.projectanalysis.period.Period;
42 import org.sonar.ce.task.projectanalysis.period.PeriodHolderRule;
43 import org.sonar.ce.task.projectanalysis.util.cache.DiskCache;
44 import org.sonar.ce.task.step.ComputationStep;
45 import org.sonar.ce.task.step.TestComputationStepContext;
46 import org.sonar.core.issue.DefaultIssue;
47 import org.sonar.core.issue.DefaultIssueComment;
48 import org.sonar.core.issue.FieldDiffs;
49 import org.sonar.core.util.UuidFactoryImpl;
50 import org.sonar.db.DbClient;
51 import org.sonar.db.DbSession;
52 import org.sonar.db.DbTester;
53 import org.sonar.db.component.ComponentDto;
54 import org.sonar.db.issue.AnticipatedTransitionDto;
55 import org.sonar.db.issue.IssueChangeDto;
56 import org.sonar.db.issue.IssueDao;
57 import org.sonar.db.issue.IssueDto;
58 import org.sonar.db.newcodeperiod.NewCodePeriodType;
59 import org.sonar.db.rule.RuleDto;
60 import org.sonar.db.rule.RuleTesting;
61 import org.sonar.scanner.protocol.output.ScannerReport;
62 import org.sonar.server.issue.IssueStorage;
63
64 import static java.util.Collections.singletonList;
65 import static org.assertj.core.api.Assertions.assertThat;
66 import static org.assertj.core.api.Assertions.tuple;
67 import static org.assertj.core.data.MapEntry.entry;
68 import static org.mockito.ArgumentMatchers.any;
69 import static org.mockito.ArgumentMatchers.eq;
70 import static org.mockito.Mockito.mock;
71 import static org.mockito.Mockito.verify;
72 import static org.mockito.Mockito.when;
73 import static org.sonar.api.issue.Issue.RESOLUTION_FIXED;
74 import static org.sonar.api.issue.Issue.STATUS_CLOSED;
75 import static org.sonar.api.issue.Issue.STATUS_OPEN;
76 import static org.sonar.api.rule.Severity.BLOCKER;
77 import static org.sonar.db.component.ComponentTesting.newFileDto;
78 import static org.sonar.db.issue.IssueTesting.newCodeReferenceIssue;
79
80 public class PersistIssuesStepIT extends BaseStepTest {
81
82   private static final long NOW = 1_400_000_000_000L;
83
84   @Rule
85   public TemporaryFolder temp = new TemporaryFolder();
86   @Rule
87   public DbTester db = DbTester.create(System2.INSTANCE);
88   @Rule
89   public BatchReportReaderRule reportReader = new BatchReportReaderRule();
90   @Rule
91   public PeriodHolderRule periodHolder = new PeriodHolderRule();
92
93   private System2 system2 = mock(System2.class);
94   private DbSession session = db.getSession();
95   private DbClient dbClient = db.getDbClient();
96   private UpdateConflictResolver conflictResolver = mock(UpdateConflictResolver.class);
97   private ProtoIssueCache protoIssueCache;
98   private ComputationStep underTest;
99
100   private AdHocRuleCreator adHocRuleCreator = mock(AdHocRuleCreator.class);
101
102   @Override
103   protected ComputationStep step() {
104     return underTest;
105   }
106
107   @Before
108   public void setup() throws Exception {
109     periodHolder.setPeriod(new Period(NewCodePeriodType.NUMBER_OF_DAYS.name(), "10", 1000L));
110
111     protoIssueCache = new ProtoIssueCache(temp.newFile(), System2.INSTANCE);
112     reportReader.setMetadata(ScannerReport.Metadata.getDefaultInstance());
113
114     underTest = new PersistIssuesStep(dbClient, system2, conflictResolver, new RuleRepositoryImpl(adHocRuleCreator, dbClient), periodHolder,
115       protoIssueCache, new IssueStorage(), UuidFactoryImpl.INSTANCE);
116   }
117
118   @After
119   public void tearDown() {
120     session.close();
121   }
122
123   @Test
124   public void insert_copied_issue() {
125     RuleDto rule = RuleTesting.newRule(RuleKey.of("xoo", "S01"));
126     db.rules().insert(rule);
127     ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
128     ComponentDto file = db.components().insertComponent(newFileDto(project));
129     when(system2.now()).thenReturn(NOW);
130     String issueKey = "ISSUE-1";
131
132     protoIssueCache.newAppender().append(new DefaultIssue()
133         .setKey(issueKey)
134         .setType(RuleType.CODE_SMELL)
135         .setRuleKey(rule.getKey())
136         .setComponentUuid(file.uuid())
137         .setComponentKey(file.getKey())
138         .setProjectUuid(project.uuid())
139         .setProjectKey(project.getKey())
140         .setSeverity(BLOCKER)
141         .setStatus(STATUS_OPEN)
142         .setTags(singletonList("test"))
143         .setNew(false)
144         .setCopied(true)
145         .setType(RuleType.BUG)
146         .setCreationDate(new Date(NOW))
147         .setSelectedAt(NOW)
148         .addComment(new DefaultIssueComment()
149           .setKey("COMMENT")
150           .setIssueKey(issueKey)
151           .setUserUuid("john_uuid")
152           .setMarkdownText("Some text")
153           .setCreatedAt(new Date(NOW))
154           .setUpdatedAt(new Date(NOW))
155           .setNew(true))
156         .setCurrentChange(
157           new FieldDiffs()
158             .setIssueKey(issueKey)
159             .setUserUuid("john_uuid")
160             .setDiff("technicalDebt", null, 1L)
161             .setCreationDate(new Date(NOW))))
162       .close();
163
164     TestComputationStepContext context = new TestComputationStepContext();
165     underTest.execute(context);
166
167     IssueDto result = dbClient.issueDao().selectOrFailByKey(session, issueKey);
168
169     assertThat(result.getKey()).isEqualTo(issueKey);
170     assertThat(result.getRuleKey()).isEqualTo(rule.getKey());
171     assertThat(result.getComponentUuid()).isEqualTo(file.uuid());
172     assertThat(result.getProjectUuid()).isEqualTo(project.uuid());
173     assertThat(result.getSeverity()).isEqualTo(BLOCKER);
174     assertThat(result.getStatus()).isEqualTo(STATUS_OPEN);
175     assertThat(result.getType()).isEqualTo(RuleType.BUG.getDbConstant());
176     assertThat(result.getTags()).containsExactlyInAnyOrder("test");
177     assertThat(result.isNewCodeReferenceIssue()).isFalse();
178
179     List<IssueChangeDto> changes = dbClient.issueChangeDao().selectByIssueKeys(session, Arrays.asList(issueKey));
180     assertThat(changes).extracting(IssueChangeDto::getChangeType).containsExactly(IssueChangeDto.TYPE_COMMENT, IssueChangeDto.TYPE_FIELD_CHANGE);
181     assertThat(context.getStatistics().getAll()).contains(
182       entry("inserts", "1"), entry("updates", "0"), entry("merged", "0"));
183   }
184
185   @Test
186   public void insert_copied_issue_with_minimal_info() {
187     periodHolder.setPeriod(new Period(NewCodePeriodType.REFERENCE_BRANCH.name(), "master", null));
188
189     RuleDto rule = RuleTesting.newRule(RuleKey.of("xoo", "S01"));
190     db.rules().insert(rule);
191     ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
192     ComponentDto file = db.components().insertComponent(newFileDto(project));
193     when(system2.now()).thenReturn(NOW);
194     String issueKey = "ISSUE-2";
195
196     protoIssueCache.newAppender().append(new DefaultIssue()
197         .setKey(issueKey)
198         .setType(RuleType.CODE_SMELL)
199         .setRuleKey(rule.getKey())
200         .setComponentUuid(file.uuid())
201         .setComponentKey(file.getKey())
202         .setProjectUuid(project.uuid())
203         .setProjectKey(project.getKey())
204         .setSeverity(BLOCKER)
205         .setStatus(STATUS_OPEN)
206         .setNew(false)
207         .setCopied(true)
208         .setType(RuleType.BUG)
209         .setCreationDate(new Date(NOW))
210         .setSelectedAt(NOW))
211       .close();
212
213     TestComputationStepContext context = new TestComputationStepContext();
214     underTest.execute(context);
215
216     IssueDto result = dbClient.issueDao().selectOrFailByKey(session, issueKey);
217     assertThat(result.getKey()).isEqualTo(issueKey);
218     assertThat(result.getRuleKey()).isEqualTo(rule.getKey());
219     assertThat(result.getComponentUuid()).isEqualTo(file.uuid());
220     assertThat(result.getProjectUuid()).isEqualTo(project.uuid());
221     assertThat(result.getSeverity()).isEqualTo(BLOCKER);
222     assertThat(result.getStatus()).isEqualTo(STATUS_OPEN);
223     assertThat(result.getType()).isEqualTo(RuleType.BUG.getDbConstant());
224     assertThat(result.getTags()).isEmpty();
225     assertThat(result.isNewCodeReferenceIssue()).isFalse();
226
227     assertThat(dbClient.issueChangeDao().selectByIssueKeys(session, Arrays.asList(issueKey))).isEmpty();
228     assertThat(context.getStatistics().getAll()).contains(
229       entry("inserts", "1"), entry("updates", "0"), entry("merged", "0"));
230   }
231
232   @Test
233   public void insert_merged_issue() {
234     periodHolder.setPeriod(new Period(NewCodePeriodType.REFERENCE_BRANCH.name(), "master", null));
235     RuleDto rule = RuleTesting.newRule(RuleKey.of("xoo", "S01"));
236     db.rules().insert(rule);
237     ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
238     ComponentDto file = db.components().insertComponent(newFileDto(project));
239     when(system2.now()).thenReturn(NOW);
240     String issueKey = "ISSUE-3";
241
242     protoIssueCache.newAppender().append(new DefaultIssue()
243         .setKey(issueKey)
244         .setType(RuleType.CODE_SMELL)
245         .setRuleKey(rule.getKey())
246         .setComponentUuid(file.uuid())
247         .setComponentKey(file.getKey())
248         .setProjectUuid(project.uuid())
249         .setProjectKey(project.getKey())
250         .setSeverity(BLOCKER)
251         .setStatus(STATUS_OPEN)
252         .setNew(true)
253         .setIsOnChangedLine(true)
254         .setCopied(true)
255         .setType(RuleType.BUG)
256         .setCreationDate(new Date(NOW))
257         .setSelectedAt(NOW)
258         .addComment(new DefaultIssueComment()
259           .setKey("COMMENT")
260           .setIssueKey(issueKey)
261           .setUserUuid("john_uuid")
262           .setMarkdownText("Some text")
263           .setUpdatedAt(new Date(NOW))
264           .setCreatedAt(new Date(NOW))
265           .setNew(true))
266         .setCurrentChange(new FieldDiffs()
267           .setIssueKey(issueKey)
268           .setUserUuid("john_uuid")
269           .setDiff("technicalDebt", null, 1L)
270           .setCreationDate(new Date(NOW))))
271       .close();
272
273     TestComputationStepContext context = new TestComputationStepContext();
274     underTest.execute(context);
275
276     IssueDto result = dbClient.issueDao().selectOrFailByKey(session, issueKey);
277     assertThat(result.getKey()).isEqualTo(issueKey);
278     assertThat(result.getRuleKey()).isEqualTo(rule.getKey());
279     assertThat(result.getComponentUuid()).isEqualTo(file.uuid());
280     assertThat(result.getProjectUuid()).isEqualTo(project.uuid());
281     assertThat(result.getSeverity()).isEqualTo(BLOCKER);
282     assertThat(result.getStatus()).isEqualTo(STATUS_OPEN);
283     assertThat(result.getType()).isEqualTo(RuleType.BUG.getDbConstant());
284     assertThat(result.isNewCodeReferenceIssue()).isTrue();
285
286     List<IssueChangeDto> changes = dbClient.issueChangeDao().selectByIssueKeys(session, Arrays.asList(issueKey));
287     assertThat(changes).extracting(IssueChangeDto::getChangeType).containsExactly(IssueChangeDto.TYPE_COMMENT, IssueChangeDto.TYPE_FIELD_CHANGE);
288     assertThat(context.getStatistics().getAll()).contains(
289       entry("inserts", "1"), entry("updates", "0"), entry("merged", "0"));
290   }
291
292   @Test
293   public void update_conflicting_issue() {
294     RuleDto rule = RuleTesting.newRule(RuleKey.of("xoo", "S01"));
295     db.rules().insert(rule);
296     ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
297     ComponentDto file = db.components().insertComponent(newFileDto(project));
298     IssueDto issue = db.issues().insert(rule, project, file,
299       i -> i.setStatus(STATUS_OPEN)
300         .setResolution(null)
301         .setCreatedAt(NOW - 1_000_000_000L)
302         // simulate the issue has been updated after the analysis ran
303         .setUpdatedAt(NOW + 1_000_000_000L));
304     issue = dbClient.issueDao().selectByKey(db.getSession(), issue.getKey()).get();
305     DiskCache.CacheAppender issueCacheAppender = protoIssueCache.newAppender();
306     when(system2.now()).thenReturn(NOW);
307
308     DefaultIssue defaultIssue = issue.toDefaultIssue()
309       .setStatus(STATUS_CLOSED)
310       .setResolution(RESOLUTION_FIXED)
311       .setSelectedAt(NOW)
312       .setNew(false)
313       .setChanged(true);
314     issueCacheAppender.append(defaultIssue).close();
315
316     TestComputationStepContext context = new TestComputationStepContext();
317     underTest.execute(context);
318
319     ArgumentCaptor<IssueDto> issueDtoCaptor = ArgumentCaptor.forClass(IssueDto.class);
320     verify(conflictResolver).resolve(eq(defaultIssue), issueDtoCaptor.capture(), any(IssueDao.class), any(DbSession.class));
321     assertThat(issueDtoCaptor.getValue().getKey()).isEqualTo(issue.getKey());
322     assertThat(context.getStatistics().getAll()).contains(
323       entry("inserts", "0"), entry("updates", "1"), entry("merged", "1"));
324   }
325
326   @Test
327   public void insert_new_issue() {
328     periodHolder.setPeriod(new Period(NewCodePeriodType.REFERENCE_BRANCH.name(), "master", null));
329     RuleDto rule = RuleTesting.newRule(RuleKey.of("xoo", "S01"));
330     db.rules().insert(rule);
331     ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
332     ComponentDto file = db.components().insertComponent(newFileDto(project));
333     session.commit();
334     String issueKey = "ISSUE-4";
335
336     protoIssueCache.newAppender().append(new DefaultIssue()
337       .setKey(issueKey)
338       .setType(RuleType.CODE_SMELL)
339       .setRuleKey(rule.getKey())
340       .setComponentUuid(file.uuid())
341       .setComponentKey(file.getKey())
342       .setProjectUuid(project.uuid())
343       .setProjectKey(project.getKey())
344       .setSeverity(BLOCKER)
345       .setStatus(STATUS_OPEN)
346       .setCreationDate(new Date(NOW))
347       .setNew(true)
348       .setIsOnChangedLine(true)
349       .addImpact(SoftwareQuality.SECURITY, Severity.MEDIUM)
350       .setType(RuleType.BUG)).close();
351
352     TestComputationStepContext context = new TestComputationStepContext();
353     underTest.execute(context);
354
355     IssueDto result = dbClient.issueDao().selectOrFailByKey(session, issueKey);
356     assertThat(result.getKey()).isEqualTo(issueKey);
357     assertThat(result.getRuleKey()).isEqualTo(rule.getKey());
358     assertThat(result.getComponentUuid()).isEqualTo(file.uuid());
359     assertThat(result.getProjectUuid()).isEqualTo(project.uuid());
360     assertThat(result.getSeverity()).isEqualTo(BLOCKER);
361     assertThat(result.getStatus()).isEqualTo(STATUS_OPEN);
362     assertThat(result.getType()).isEqualTo(RuleType.BUG.getDbConstant());
363     assertThat(result.getImpacts()).extracting(i -> i.getSoftwareQuality(), i -> i.getSeverity())
364       .containsExactly(tuple(SoftwareQuality.SECURITY, Severity.MEDIUM));
365     assertThat(context.getStatistics().getAll()).contains(
366       entry("inserts", "1"), entry("updates", "0"), entry("merged", "0"));
367     assertThat(result.isNewCodeReferenceIssue()).isTrue();
368   }
369
370   @Test
371   public void close_issue() {
372     ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
373     ComponentDto file = db.components().insertComponent(newFileDto(project));
374     RuleDto rule = db.rules().insert();
375     IssueDto issue = db.issues().insert(rule, project, file,
376       i -> i.setStatus(STATUS_OPEN)
377         .setResolution(null)
378         .setCreatedAt(NOW - 1_000_000_000L)
379         .setUpdatedAt(NOW - 1_000_000_000L));
380     DiskCache.CacheAppender issueCacheAppender = protoIssueCache.newAppender();
381
382     issueCacheAppender.append(
383         issue.toDefaultIssue()
384           .setStatus(STATUS_CLOSED)
385           .setResolution(RESOLUTION_FIXED)
386           .setSelectedAt(NOW)
387           .setNew(false)
388           .setChanged(true))
389       .close();
390
391     TestComputationStepContext context = new TestComputationStepContext();
392     underTest.execute(context);
393
394     IssueDto issueReloaded = db.getDbClient().issueDao().selectByKey(db.getSession(), issue.getKey()).get();
395     assertThat(issueReloaded.getStatus()).isEqualTo(STATUS_CLOSED);
396     assertThat(issueReloaded.getResolution()).isEqualTo(RESOLUTION_FIXED);
397     assertThat(context.getStatistics().getAll()).contains(
398       entry("inserts", "0"), entry("updates", "1"), entry("merged", "0"));
399   }
400
401   @Test
402   public void handle_no_longer_new_issue() {
403     periodHolder.setPeriod(new Period(NewCodePeriodType.REFERENCE_BRANCH.name(), "master", null));
404     RuleDto rule = RuleTesting.newRule(RuleKey.of("xoo", "S01"));
405     db.rules().insert(rule);
406     ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
407     ComponentDto file = db.components().insertComponent(newFileDto(project));
408     when(system2.now()).thenReturn(NOW);
409     String issueKey = "ISSUE-5";
410
411     DefaultIssue defaultIssue = new DefaultIssue()
412       .setKey(issueKey)
413       .setType(RuleType.CODE_SMELL)
414       .setRuleKey(rule.getKey())
415       .setComponentUuid(file.uuid())
416       .setComponentKey(file.getKey())
417       .setProjectUuid(project.uuid())
418       .setProjectKey(project.getKey())
419       .setSeverity(BLOCKER)
420       .setStatus(STATUS_OPEN)
421       .setNew(true)
422       .setIsOnChangedLine(true)
423       .setIsNewCodeReferenceIssue(true)
424       .setIsNoLongerNewCodeReferenceIssue(false)
425       .setCopied(false)
426       .setType(RuleType.BUG)
427       .setCreationDate(new Date(NOW))
428       .setSelectedAt(NOW);
429
430     IssueDto issueDto = IssueDto.toDtoForComputationInsert(defaultIssue, rule.getUuid(), NOW);
431     dbClient.issueDao().insert(session, issueDto);
432     dbClient.issueDao().insertAsNewCodeOnReferenceBranch(session, newCodeReferenceIssue(issueDto));
433     session.commit();
434
435     IssueDto result = dbClient.issueDao().selectOrFailByKey(session, issueKey);
436     assertThat(result.isNewCodeReferenceIssue()).isTrue();
437
438     protoIssueCache.newAppender().append(defaultIssue.setNew(false)
439         .setIsOnChangedLine(false)
440         .setIsNewCodeReferenceIssue(false)
441         .setIsNoLongerNewCodeReferenceIssue(true))
442       .close();
443
444     TestComputationStepContext context = new TestComputationStepContext();
445     underTest.execute(context);
446
447     assertThat(context.getStatistics().getAll()).contains(
448       entry("inserts", "0"), entry("updates", "1"), entry("merged", "0"));
449
450     result = dbClient.issueDao().selectOrFailByKey(session, issueKey);
451     assertThat(result.isNewCodeReferenceIssue()).isFalse();
452   }
453
454   @Test
455   public void handle_existing_new_code_issue_migration() {
456     periodHolder.setPeriod(new Period(NewCodePeriodType.REFERENCE_BRANCH.name(), "master", null));
457     RuleDto rule = RuleTesting.newRule(RuleKey.of("xoo", "S01"));
458     db.rules().insert(rule);
459     ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
460     ComponentDto file = db.components().insertComponent(newFileDto(project));
461     when(system2.now()).thenReturn(NOW);
462     String issueKey = "ISSUE-6";
463
464     DefaultIssue defaultIssue = new DefaultIssue()
465       .setKey(issueKey)
466       .setType(RuleType.CODE_SMELL)
467       .setRuleKey(rule.getKey())
468       .setComponentUuid(file.uuid())
469       .setComponentKey(file.getKey())
470       .setProjectUuid(project.uuid())
471       .setProjectKey(project.getKey())
472       .setSeverity(BLOCKER)
473       .setStatus(STATUS_OPEN)
474       .setNew(true)
475       .setCopied(false)
476       .setType(RuleType.BUG)
477       .setCreationDate(new Date(NOW))
478       .setSelectedAt(NOW);
479
480     IssueDto issueDto = IssueDto.toDtoForComputationInsert(defaultIssue, rule.getUuid(), NOW);
481     dbClient.issueDao().insert(session, issueDto);
482     session.commit();
483
484     IssueDto result = dbClient.issueDao().selectOrFailByKey(session, issueKey);
485     assertThat(result.isNewCodeReferenceIssue()).isFalse();
486
487     protoIssueCache.newAppender().append(defaultIssue.setNew(false)
488         .setIsOnChangedLine(true)
489         .setIsNewCodeReferenceIssue(false)
490         .setIsNoLongerNewCodeReferenceIssue(false))
491       .close();
492
493     TestComputationStepContext context = new TestComputationStepContext();
494     underTest.execute(context);
495
496     assertThat(context.getStatistics().getAll()).contains(
497       entry("inserts", "0"), entry("updates", "1"), entry("merged", "0"));
498
499     result = dbClient.issueDao().selectOrFailByKey(session, issueKey);
500     assertThat(result.isNewCodeReferenceIssue()).isTrue();
501   }
502
503   @Test
504   public void handle_existing_without_need_for_new_code_issue_migration() {
505     periodHolder.setPeriod(new Period(NewCodePeriodType.REFERENCE_BRANCH.name(), "master", null));
506     RuleDto rule = RuleTesting.newRule(RuleKey.of("xoo", "S01"));
507     db.rules().insert(rule);
508     ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
509     ComponentDto file = db.components().insertComponent(newFileDto(project));
510     when(system2.now()).thenReturn(NOW);
511     String issueKey = "ISSUE-7";
512
513     DefaultIssue defaultIssue = new DefaultIssue()
514       .setKey(issueKey)
515       .setType(RuleType.CODE_SMELL)
516       .setRuleKey(rule.getKey())
517       .setComponentUuid(file.uuid())
518       .setComponentKey(file.getKey())
519       .setProjectUuid(project.uuid())
520       .setProjectKey(project.getKey())
521       .setSeverity(BLOCKER)
522       .setStatus(STATUS_OPEN)
523       .setNew(true)
524       .setIsOnChangedLine(true)
525       .setIsNewCodeReferenceIssue(true)
526       .setIsNoLongerNewCodeReferenceIssue(false)
527       .setCopied(false)
528       .setType(RuleType.BUG)
529       .setCreationDate(new Date(NOW))
530       .setSelectedAt(NOW);
531
532     IssueDto issueDto = IssueDto.toDtoForComputationInsert(defaultIssue, rule.getUuid(), NOW);
533     dbClient.issueDao().insert(session, issueDto);
534     dbClient.issueDao().insertAsNewCodeOnReferenceBranch(session, newCodeReferenceIssue(issueDto));
535     session.commit();
536
537     IssueDto result = dbClient.issueDao().selectOrFailByKey(session, issueKey);
538     assertThat(result.isNewCodeReferenceIssue()).isTrue();
539
540     protoIssueCache.newAppender().append(defaultIssue.setNew(false)
541         .setIsOnChangedLine(false)
542         .setIsNewCodeReferenceIssue(true)
543         .setIsOnChangedLine(true)
544         .setIsNoLongerNewCodeReferenceIssue(false))
545       .close();
546
547     TestComputationStepContext context = new TestComputationStepContext();
548     underTest.execute(context);
549
550     assertThat(context.getStatistics().getAll()).contains(
551       entry("inserts", "0"), entry("updates", "0"), entry("merged", "0"));
552
553     result = dbClient.issueDao().selectOrFailByKey(session, issueKey);
554     assertThat(result.isNewCodeReferenceIssue()).isTrue();
555   }
556
557   @Test
558   public void add_comment() {
559     ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
560     ComponentDto file = db.components().insertComponent(newFileDto(project));
561     RuleDto rule = db.rules().insert();
562     IssueDto issue = db.issues().insert(rule, project, file,
563       i -> i.setStatus(STATUS_OPEN)
564         .setResolution(null)
565         .setCreatedAt(NOW - 1_000_000_000L)
566         .setUpdatedAt(NOW - 1_000_000_000L));
567     DiskCache.CacheAppender issueCacheAppender = protoIssueCache.newAppender();
568
569     issueCacheAppender.append(
570         issue.toDefaultIssue()
571           .setStatus(STATUS_CLOSED)
572           .setResolution(RESOLUTION_FIXED)
573           .setSelectedAt(NOW)
574           .setNew(false)
575           .setChanged(true)
576           .addComment(new DefaultIssueComment()
577             .setKey("COMMENT")
578             .setIssueKey(issue.getKey())
579             .setUserUuid("john_uuid")
580             .setMarkdownText("Some text")
581             .setCreatedAt(new Date(NOW))
582             .setUpdatedAt(new Date(NOW))
583             .setNew(true)))
584       .close();
585
586     TestComputationStepContext context = new TestComputationStepContext();
587     underTest.execute(context);
588
589     IssueChangeDto issueChangeDto = db.getDbClient().issueChangeDao().selectByIssueKeys(db.getSession(), singletonList(issue.getKey())).get(0);
590     assertThat(issueChangeDto)
591       .extracting(IssueChangeDto::getChangeType, IssueChangeDto::getUserUuid, IssueChangeDto::getChangeData, IssueChangeDto::getIssueKey,
592         IssueChangeDto::getIssueChangeCreationDate)
593       .containsOnly(IssueChangeDto.TYPE_COMMENT, "john_uuid", "Some text", issue.getKey(), NOW);
594     assertThat(context.getStatistics().getAll()).contains(
595       entry("inserts", "0"), entry("updates", "1"), entry("merged", "0"));
596   }
597
598   @Test
599   public void add_change() {
600     ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
601     ComponentDto file = db.components().insertComponent(newFileDto(project));
602     RuleDto rule = db.rules().insert();
603     IssueDto issue = db.issues().insert(rule, project, file,
604       i -> i.setStatus(STATUS_OPEN)
605         .setResolution(null)
606         .setCreatedAt(NOW - 1_000_000_000L)
607         .setUpdatedAt(NOW - 1_000_000_000L));
608     DiskCache.CacheAppender issueCacheAppender = protoIssueCache.newAppender();
609
610     issueCacheAppender.append(
611         issue.toDefaultIssue()
612           .setStatus(STATUS_CLOSED)
613           .setResolution(RESOLUTION_FIXED)
614           .setSelectedAt(NOW)
615           .setNew(false)
616           .setChanged(true)
617           .setIsOnChangedLine(false)
618           .setIsNewCodeReferenceIssue(false)
619           .setCurrentChange(new FieldDiffs()
620             .setIssueKey("ISSUE")
621             .setUserUuid("john_uuid")
622             .setDiff("technicalDebt", null, 1L)
623             .setCreationDate(new Date(NOW))))
624       .close();
625
626     TestComputationStepContext context = new TestComputationStepContext();
627     underTest.execute(context);
628
629     IssueChangeDto issueChangeDto = db.getDbClient().issueChangeDao().selectByIssueKeys(db.getSession(), singletonList(issue.getKey())).get(0);
630     assertThat(issueChangeDto)
631       .extracting(IssueChangeDto::getChangeType, IssueChangeDto::getUserUuid, IssueChangeDto::getChangeData, IssueChangeDto::getIssueKey,
632         IssueChangeDto::getIssueChangeCreationDate)
633       .containsOnly(IssueChangeDto.TYPE_FIELD_CHANGE, "john_uuid", "technicalDebt=1", issue.getKey(), NOW);
634     assertThat(context.getStatistics().getAll()).contains(
635       entry("inserts", "0"), entry("updates", "1"), entry("merged", "0"));
636   }
637
638   @Test
639   public void when_anticipatedTransitionIsPresent_ItShouldBeDeleted() {
640     periodHolder.setPeriod(new Period(NewCodePeriodType.REFERENCE_BRANCH.name(), "master", null));
641     RuleDto rule = RuleTesting.newRule(RuleKey.of("xoo", "S01"));
642     db.rules().insert(rule);
643     ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
644     ComponentDto file = db.components().insertComponent(newFileDto(project));
645     session.commit();
646     String issueKey = "ISSUE-4";
647
648     DefaultIssue newIssue = new DefaultIssue()
649       .setKey(issueKey)
650       .setType(RuleType.CODE_SMELL)
651       .setRuleKey(rule.getKey())
652       .setComponentUuid(file.uuid())
653       .setComponentKey(file.getKey())
654       .setProjectUuid(project.uuid())
655       .setProjectKey(project.getKey())
656       .setSeverity(BLOCKER)
657       .setStatus(STATUS_OPEN)
658       .setCreationDate(new Date(NOW))
659       .setNew(true)
660       .setIsOnChangedLine(true)
661       .setType(RuleType.BUG);
662
663     AnticipatedTransitionDto atDto = db.anticipatedTransitions().createForIssue(newIssue, "test_uuid", file.name());
664     newIssue.setAnticipatedTransitionUuid(atDto.getUuid());
665
666     var defaultIssueCacheAppender = protoIssueCache.newAppender();
667     defaultIssueCacheAppender.append(newIssue).close();
668
669     TestComputationStepContext context = new TestComputationStepContext();
670     underTest.execute(context);
671
672     IssueDto result = dbClient.issueDao().selectOrFailByKey(session, issueKey);
673     assertThat(result.getKey()).isEqualTo(issueKey);
674     assertThat(result.getRuleKey()).isEqualTo(rule.getKey());
675     assertThat(result.getComponentUuid()).isEqualTo(file.uuid());
676     assertThat(result.getProjectUuid()).isEqualTo(project.uuid());
677     assertThat(result.getSeverity()).isEqualTo(BLOCKER);
678     assertThat(result.getStatus()).isEqualTo(STATUS_OPEN);
679     assertThat(result.getType()).isEqualTo(RuleType.BUG.getDbConstant());
680     assertThat(context.getStatistics().getAll()).contains(
681       entry("inserts", "1"), entry("updates", "0"), entry("merged", "0"));
682     assertThat(result.isNewCodeReferenceIssue()).isTrue();
683
684     assertThat(db.anticipatedTransitions().selectByProjectUuid(project.uuid())).isEmpty();
685   }
686 }