From: Belen Pruvost Date: Tue, 29 Mar 2022 08:40:53 +0000 (+0200) Subject: SONAR-16039 - Migrate existing issues to new_code table X-Git-Tag: 9.4.0.54424~10 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=5db8293aeefbd683b9288bbc5d0dee5d9e407546;p=sonarqube.git SONAR-16039 - Migrate existing issues to new_code table --- diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/IntegrateIssuesVisitor.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/IntegrateIssuesVisitor.java index 47af93eaade..5a322ab7ca1 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/IntegrateIssuesVisitor.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/IntegrateIssuesVisitor.java @@ -127,7 +127,8 @@ public class IntegrateIssuesVisitor extends TypeAwareVisitorAdapter { private void process(Component component, DefaultIssue issue, CacheAppender cacheAppender) { issueLifecycle.doAutomaticTransition(issue); issueVisitors.onIssue(component, issue); - if (issue.isNew() || issue.isChanged() || issue.isCopied() || issue.isNoLongerNewCodeReferenceIssue()) { + if (issue.isNew() || issue.isChanged() || issue.isCopied() || + issue.isNoLongerNewCodeReferenceIssue() || issue.isToBeMigratedAsNewCodeReferenceIssue()) { cacheAppender.append(issue); } } diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/IssueOnReferenceBranchVisitor.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/IssueOnReferenceBranchVisitor.java index 61c78246511..8f2e811c997 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/IssueOnReferenceBranchVisitor.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/IssueOnReferenceBranchVisitor.java @@ -36,9 +36,7 @@ public class IssueOnReferenceBranchVisitor extends IssueVisitor { return; } - issue.setIsOnReferencedBranch(newIssueClassifier.isOnBranchUsingReferenceBranch()); - - if (issue.isOnReferencedBranch()) { + if (newIssueClassifier.isOnBranchUsingReferenceBranch()) { issue.setIsOnChangedLine(newIssueClassifier.hasAtLeastOneLocationOnChangedLines(component, issue)); if (issue.isNewCodeReferenceIssue() && !issue.isOnChangedLine()) { diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistIssuesStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistIssuesStep.java index c3721d357f8..379a7cc255b 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistIssuesStep.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistIssuesStep.java @@ -26,6 +26,7 @@ import org.sonar.api.utils.System2; import org.sonar.ce.task.projectanalysis.issue.ProtoIssueCache; import org.sonar.ce.task.projectanalysis.issue.RuleRepository; import org.sonar.ce.task.projectanalysis.issue.UpdateConflictResolver; +import org.sonar.ce.task.projectanalysis.period.PeriodHolder; import org.sonar.ce.task.step.ComputationStep; import org.sonar.core.issue.DefaultIssue; import org.sonar.core.util.CloseableIterator; @@ -37,6 +38,7 @@ import org.sonar.db.issue.IssueChangeMapper; import org.sonar.db.issue.IssueDto; import org.sonar.db.issue.IssueMapper; import org.sonar.db.issue.NewCodeReferenceIssueDto; +import org.sonar.db.newcodeperiod.NewCodePeriodType; import org.sonar.server.issue.IssueStorage; import static org.sonar.core.util.FileUtils.humanReadableByteCountSI; @@ -52,16 +54,19 @@ public class PersistIssuesStep implements ComputationStep { private final System2 system2; private final UpdateConflictResolver conflictResolver; private final RuleRepository ruleRepository; + private final PeriodHolder periodHolder; private final ProtoIssueCache protoIssueCache; private final IssueStorage issueStorage; private final UuidFactory uuidFactory; public PersistIssuesStep(DbClient dbClient, System2 system2, UpdateConflictResolver conflictResolver, - RuleRepository ruleRepository, ProtoIssueCache protoIssueCache, IssueStorage issueStorage, UuidFactory uuidFactory) { + RuleRepository ruleRepository, PeriodHolder periodHolder, ProtoIssueCache protoIssueCache, IssueStorage issueStorage, + UuidFactory uuidFactory) { this.dbClient = dbClient; this.system2 = system2; this.conflictResolver = conflictResolver; this.ruleRepository = ruleRepository; + this.periodHolder = periodHolder; this.protoIssueCache = protoIssueCache; this.issueStorage = issueStorage; this.uuidFactory = uuidFactory; @@ -76,6 +81,7 @@ public class PersistIssuesStep implements ComputationStep { List addedIssues = new ArrayList<>(ISSUE_BATCHING_SIZE); List updatedIssues = new ArrayList<>(ISSUE_BATCHING_SIZE); List noLongerNewIssues = new ArrayList<>(ISSUE_BATCHING_SIZE); + List newCodeIssuesToMigrate = new ArrayList<>(ISSUE_BATCHING_SIZE); IssueMapper mapper = dbSession.getMapper(IssueMapper.class); IssueChangeMapper changeMapper = dbSession.getMapper(IssueChangeMapper.class); @@ -93,17 +99,24 @@ public class PersistIssuesStep implements ComputationStep { persistUpdatedIssues(statistics, updatedIssues, mapper, changeMapper); updatedIssues.clear(); } - } else if (issue.isNoLongerNewCodeReferenceIssue()) { + } else if (isOnBranchUsingReferenceBranch() && issue.isNoLongerNewCodeReferenceIssue()) { noLongerNewIssues.add(issue); if (noLongerNewIssues.size() >= ISSUE_BATCHING_SIZE) { persistNoLongerNewIssues(statistics, noLongerNewIssues, mapper); noLongerNewIssues.clear(); } + } else if (isOnBranchUsingReferenceBranch() && issue.isToBeMigratedAsNewCodeReferenceIssue()) { + newCodeIssuesToMigrate.add(issue); + if (newCodeIssuesToMigrate.size() >= ISSUE_BATCHING_SIZE) { + persistNewCodeIssuesToMigrate(statistics, newCodeIssuesToMigrate, mapper); + newCodeIssuesToMigrate.clear(); + } } } persistNewIssues(statistics, addedIssues, mapper, changeMapper); persistUpdatedIssues(statistics, updatedIssues, mapper, changeMapper); persistNoLongerNewIssues(statistics, noLongerNewIssues, mapper); + persistNewCodeIssuesToMigrate(statistics, newCodeIssuesToMigrate, mapper); flushSession(dbSession); } finally { statistics.dumpTo(context); @@ -120,7 +133,7 @@ public class PersistIssuesStep implements ComputationStep { String ruleUuid = ruleRepository.getByKey(i.ruleKey()).getUuid(); IssueDto dto = IssueDto.toDtoForComputationInsert(i, ruleUuid, now); mapper.insert(dto); - if (i.isOnReferencedBranch() && i.isOnChangedLine()) { + if (isOnBranchUsingReferenceBranch() && i.isOnChangedLine()) { mapper.insertAsNewCodeOnReferenceBranch(NewCodeReferenceIssueDto.fromIssueDto(dto, now, uuidFactory)); } statistics.inserts++; @@ -169,11 +182,30 @@ public class PersistIssuesStep implements ComputationStep { } + private void persistNewCodeIssuesToMigrate(IssueStatistics statistics, List newCodeIssuesToMigrate, IssueMapper mapper) { + if (newCodeIssuesToMigrate.isEmpty()) { + return; + } + + long now = system2.now(); + newCodeIssuesToMigrate.forEach(i -> { + mapper.insertAsNewCodeOnReferenceBranch(NewCodeReferenceIssueDto.fromIssueKey(i.key(), now, uuidFactory)); + statistics.updates++; + }); + } + private static void flushSession(DbSession dbSession) { dbSession.flushStatements(); dbSession.commit(); } + private boolean isOnBranchUsingReferenceBranch() { + if (periodHolder.hasPeriod()) { + return periodHolder.getPeriod().getMode().equals(NewCodePeriodType.REFERENCE_BRANCH.name()); + } + return false; + } + @Override public String getDescription() { return "Persist issues"; diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/util/cache/ProtobufIssueDiskCache.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/util/cache/ProtobufIssueDiskCache.java index 452751ba1ce..74650b07818 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/util/cache/ProtobufIssueDiskCache.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/util/cache/ProtobufIssueDiskCache.java @@ -122,8 +122,8 @@ public class ProtobufIssueDiskCache implements DiskCache { defaultIssue.setCloseDate(next.hasCloseDate() ? new Date(next.getCloseDate()) : null); defaultIssue.setCurrentChangeWithoutAddChange(next.hasCurrentChanges() ? toDefaultIssueChanges(next.getCurrentChanges()) : null); defaultIssue.setNew(next.getIsNew()); - defaultIssue.setIsOnReferencedBranch(next.getIsOnReferencedBranch()); defaultIssue.setIsOnChangedLine(next.getIsOnChangedLine()); + defaultIssue.setIsNewCodeReferenceIssue(next.getIsNewCodeReferenceIssue()); defaultIssue.setCopied(next.getIsCopied()); defaultIssue.setBeingClosed(next.getBeingClosed()); defaultIssue.setOnDisabledRule(next.getOnDisabledRule()); @@ -172,8 +172,8 @@ public class ProtobufIssueDiskCache implements DiskCache { ofNullable(defaultIssue.closeDate()).map(Date::getTime).ifPresent(builder::setCloseDate); ofNullable(defaultIssue.currentChange()).ifPresent(c -> builder.setCurrentChanges(toProtoIssueChanges(c))); builder.setIsNew(defaultIssue.isNew()); - builder.setIsOnReferencedBranch(defaultIssue.isOnReferencedBranch()); builder.setIsOnChangedLine(defaultIssue.isOnChangedLine()); + builder.setIsNewCodeReferenceIssue(defaultIssue.isNewCodeReferenceIssue()); builder.setIsCopied(defaultIssue.isCopied()); builder.setBeingClosed(defaultIssue.isBeingClosed()); builder.setOnDisabledRule(defaultIssue.isOnDisabledRule()); diff --git a/server/sonar-ce-task-projectanalysis/src/main/protobuf/issue_cache.proto b/server/sonar-ce-task-projectanalysis/src/main/protobuf/issue_cache.proto index dbd6942998a..24b2198c4f6 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/protobuf/issue_cache.proto +++ b/server/sonar-ce-task-projectanalysis/src/main/protobuf/issue_cache.proto @@ -77,7 +77,8 @@ message Issue { optional bool isOnReferencedBranch = 40; optional bool isOnChangedLine = 41; - optional bool isNoLongerNewCodeReferenceIssue = 42; + optional bool isNewCodeReferenceIssue = 42; + optional bool isNoLongerNewCodeReferenceIssue = 43; } message Comment { diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/IssuesOnReferenceBranchVisitorTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/IssuesOnReferenceBranchVisitorTest.java index 1cb26f570b6..693d665fcb4 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/IssuesOnReferenceBranchVisitorTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/IssuesOnReferenceBranchVisitorTest.java @@ -51,8 +51,6 @@ public class IssuesOnReferenceBranchVisitorTest { when(newIssueClassifier.isOnBranchUsingReferenceBranch()).thenReturn(false); underTest.onIssue(component, issue); - verify(issue).setIsOnReferencedBranch(false); - verify(issue).isOnReferencedBranch(); verifyNoMoreInteractions(issue); } @@ -61,12 +59,9 @@ public class IssuesOnReferenceBranchVisitorTest { when(newIssueClassifier.isEnabled()).thenReturn(true); when(newIssueClassifier.isOnBranchUsingReferenceBranch()).thenReturn(true); when(newIssueClassifier.hasAtLeastOneLocationOnChangedLines(component, issue)).thenReturn(true); - when(issue.isOnReferencedBranch()).thenReturn(true); when(issue.isNewCodeReferenceIssue()).thenReturn(false); underTest.onIssue(component, issue); - verify(issue).setIsOnReferencedBranch(true); - verify(issue).isOnReferencedBranch(); verify(issue).setIsOnChangedLine(true); verify(issue).isNewCodeReferenceIssue(); verifyNoMoreInteractions(issue); @@ -77,13 +72,10 @@ public class IssuesOnReferenceBranchVisitorTest { when(newIssueClassifier.isEnabled()).thenReturn(true); when(newIssueClassifier.isOnBranchUsingReferenceBranch()).thenReturn(true); when(newIssueClassifier.hasAtLeastOneLocationOnChangedLines(component, issue)).thenReturn(true); - when(issue.isOnReferencedBranch()).thenReturn(true); when(issue.isNewCodeReferenceIssue()).thenReturn(true); when(issue.isOnChangedLine()).thenReturn(true); underTest.onIssue(component, issue); - verify(issue).setIsOnReferencedBranch(true); - verify(issue).isOnReferencedBranch(); verify(issue).setIsOnChangedLine(true); verify(issue).isNewCodeReferenceIssue(); verify(issue).isOnChangedLine(); @@ -95,13 +87,10 @@ public class IssuesOnReferenceBranchVisitorTest { when(newIssueClassifier.isEnabled()).thenReturn(true); when(newIssueClassifier.isOnBranchUsingReferenceBranch()).thenReturn(true); when(newIssueClassifier.hasAtLeastOneLocationOnChangedLines(component, issue)).thenReturn(false); - when(issue.isOnReferencedBranch()).thenReturn(true); when(issue.isNewCodeReferenceIssue()).thenReturn(true); when(issue.isOnChangedLine()).thenReturn(false); underTest.onIssue(component, issue); - verify(issue).setIsOnReferencedBranch(true); - verify(issue).isOnReferencedBranch(); verify(issue).setIsOnChangedLine(false); verify(issue).isNewCodeReferenceIssue(); verify(issue).setIsNoLongerNewCodeReferenceIssue(true); diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistIssuesStepTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistIssuesStepTest.java index dcc22097b8e..a3b66907a9b 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistIssuesStepTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistIssuesStepTest.java @@ -36,6 +36,8 @@ import org.sonar.ce.task.projectanalysis.issue.AdHocRuleCreator; import org.sonar.ce.task.projectanalysis.issue.ProtoIssueCache; import org.sonar.ce.task.projectanalysis.issue.RuleRepositoryImpl; import org.sonar.ce.task.projectanalysis.issue.UpdateConflictResolver; +import org.sonar.ce.task.projectanalysis.period.Period; +import org.sonar.ce.task.projectanalysis.period.PeriodHolderRule; import org.sonar.ce.task.projectanalysis.util.cache.DiskCache; import org.sonar.ce.task.step.ComputationStep; import org.sonar.ce.task.step.TestComputationStepContext; @@ -50,6 +52,7 @@ import org.sonar.db.component.ComponentDto; import org.sonar.db.issue.IssueChangeDto; import org.sonar.db.issue.IssueDto; import org.sonar.db.issue.IssueMapper; +import org.sonar.db.newcodeperiod.NewCodePeriodType; import org.sonar.db.rule.RuleDefinitionDto; import org.sonar.db.rule.RuleTesting; import org.sonar.scanner.protocol.output.ScannerReport; @@ -80,6 +83,8 @@ public class PersistIssuesStepTest extends BaseStepTest { public DbTester db = DbTester.create(System2.INSTANCE); @Rule public BatchReportReaderRule reportReader = new BatchReportReaderRule(); + @Rule + public PeriodHolderRule periodHolder = new PeriodHolderRule(); private System2 system2 = mock(System2.class); private DbSession session = db.getSession(); @@ -97,11 +102,13 @@ public class PersistIssuesStepTest extends BaseStepTest { @Before public void setup() throws Exception { + periodHolder.setPeriod(new Period(NewCodePeriodType.NUMBER_OF_DAYS.name(), "10", 1000L)); + protoIssueCache = new ProtoIssueCache(temp.newFile(), System2.INSTANCE); reportReader.setMetadata(ScannerReport.Metadata.getDefaultInstance()); - underTest = new PersistIssuesStep(dbClient, system2, conflictResolver, new RuleRepositoryImpl(adHocRuleCreator, dbClient), protoIssueCache, - new IssueStorage(), UuidFactoryImpl.INSTANCE); + underTest = new PersistIssuesStep(dbClient, system2, conflictResolver, new RuleRepositoryImpl(adHocRuleCreator, dbClient), periodHolder, + protoIssueCache, new IssueStorage(), UuidFactoryImpl.INSTANCE); } @After @@ -173,6 +180,8 @@ public class PersistIssuesStepTest extends BaseStepTest { @Test public void insert_copied_issue_with_minimal_info() { + periodHolder.setPeriod(new Period(NewCodePeriodType.REFERENCE_BRANCH.name(), "master", null)); + RuleDefinitionDto rule = RuleTesting.newRule(RuleKey.of("xoo", "S01")); db.rules().insert(rule); ComponentDto project = db.components().insertPrivateProject(); @@ -191,7 +200,6 @@ public class PersistIssuesStepTest extends BaseStepTest { .setSeverity(BLOCKER) .setStatus(STATUS_OPEN) .setNew(false) - .setIsOnReferencedBranch(true) .setCopied(true) .setType(RuleType.BUG) .setCreationDate(new Date(NOW)) @@ -219,6 +227,7 @@ public class PersistIssuesStepTest extends BaseStepTest { @Test public void insert_merged_issue() { + periodHolder.setPeriod(new Period(NewCodePeriodType.REFERENCE_BRANCH.name(), "master", null)); RuleDefinitionDto rule = RuleTesting.newRule(RuleKey.of("xoo", "S01")); db.rules().insert(rule); ComponentDto project = db.components().insertPrivateProject(); @@ -237,7 +246,6 @@ public class PersistIssuesStepTest extends BaseStepTest { .setSeverity(BLOCKER) .setStatus(STATUS_OPEN) .setNew(true) - .setIsOnReferencedBranch(true) .setIsOnChangedLine(true) .setCopied(true) .setType(RuleType.BUG) @@ -313,6 +321,7 @@ public class PersistIssuesStepTest extends BaseStepTest { @Test public void insert_new_issue() { + periodHolder.setPeriod(new Period(NewCodePeriodType.REFERENCE_BRANCH.name(), "master", null)); RuleDefinitionDto rule = RuleTesting.newRule(RuleKey.of("xoo", "S01")); db.rules().insert(rule); ComponentDto project = db.components().insertPrivateProject(); @@ -332,7 +341,6 @@ public class PersistIssuesStepTest extends BaseStepTest { .setStatus(STATUS_OPEN) .setCreationDate(new Date(NOW)) .setNew(true) - .setIsOnReferencedBranch(true) .setIsOnChangedLine(true) .setType(RuleType.BUG)).close(); @@ -385,6 +393,7 @@ public class PersistIssuesStepTest extends BaseStepTest { @Test public void handle_no_longer_new_issue() { + periodHolder.setPeriod(new Period(NewCodePeriodType.REFERENCE_BRANCH.name(), "master", null)); RuleDefinitionDto rule = RuleTesting.newRule(RuleKey.of("xoo", "S01")); db.rules().insert(rule); ComponentDto project = db.components().insertPrivateProject(); @@ -403,7 +412,6 @@ public class PersistIssuesStepTest extends BaseStepTest { .setSeverity(BLOCKER) .setStatus(STATUS_OPEN) .setNew(true) - .setIsOnReferencedBranch(true) .setIsOnChangedLine(true) .setIsNewCodeReferenceIssue(true) .setIsNoLongerNewCodeReferenceIssue(false) @@ -421,7 +429,6 @@ public class PersistIssuesStepTest extends BaseStepTest { assertThat(result.isNewCodeReferenceIssue()).isTrue(); protoIssueCache.newAppender().append(defaultIssue.setNew(false) - .setIsOnReferencedBranch(true) .setIsOnChangedLine(false) .setIsNewCodeReferenceIssue(false) .setIsNoLongerNewCodeReferenceIssue(true)) @@ -437,6 +444,109 @@ public class PersistIssuesStepTest extends BaseStepTest { assertThat(result.isNewCodeReferenceIssue()).isFalse(); } + @Test + public void handle_existing_new_code_issue_migration() { + periodHolder.setPeriod(new Period(NewCodePeriodType.REFERENCE_BRANCH.name(), "master", null)); + RuleDefinitionDto rule = RuleTesting.newRule(RuleKey.of("xoo", "S01")); + db.rules().insert(rule); + ComponentDto project = db.components().insertPrivateProject(); + ComponentDto file = db.components().insertComponent(newFileDto(project, null)); + when(system2.now()).thenReturn(NOW); + String issueKey = "ISSUE-6"; + + DefaultIssue defaultIssue = new DefaultIssue() + .setKey(issueKey) + .setType(RuleType.CODE_SMELL) + .setRuleKey(rule.getKey()) + .setComponentUuid(file.uuid()) + .setComponentKey(file.getKey()) + .setProjectUuid(project.uuid()) + .setProjectKey(project.getKey()) + .setSeverity(BLOCKER) + .setStatus(STATUS_OPEN) + .setNew(true) + .setCopied(false) + .setType(RuleType.BUG) + .setCreationDate(new Date(NOW)) + .setSelectedAt(NOW); + + IssueDto issueDto = IssueDto.toDtoForComputationInsert(defaultIssue, rule.getUuid(), NOW); + dbClient.issueDao().insert(session, issueDto); + session.commit(); + + IssueDto result = dbClient.issueDao().selectOrFailByKey(session, issueKey); + assertThat(result.isNewCodeReferenceIssue()).isFalse(); + + protoIssueCache.newAppender().append(defaultIssue.setNew(false) + .setIsOnChangedLine(true) + .setIsNewCodeReferenceIssue(false) + .setIsNoLongerNewCodeReferenceIssue(false)) + .close(); + + TestComputationStepContext context = new TestComputationStepContext(); + underTest.execute(context); + + assertThat(context.getStatistics().getAll()).contains( + entry("inserts", "0"), entry("updates", "1"), entry("merged", "0")); + + result = dbClient.issueDao().selectOrFailByKey(session, issueKey); + assertThat(result.isNewCodeReferenceIssue()).isTrue(); + } + + @Test + public void handle_existing_without_need_for_new_code_issue_migration() { + periodHolder.setPeriod(new Period(NewCodePeriodType.REFERENCE_BRANCH.name(), "master", null)); + RuleDefinitionDto rule = RuleTesting.newRule(RuleKey.of("xoo", "S01")); + db.rules().insert(rule); + ComponentDto project = db.components().insertPrivateProject(); + ComponentDto file = db.components().insertComponent(newFileDto(project, null)); + when(system2.now()).thenReturn(NOW); + String issueKey = "ISSUE-7"; + + DefaultIssue defaultIssue = new DefaultIssue() + .setKey(issueKey) + .setType(RuleType.CODE_SMELL) + .setRuleKey(rule.getKey()) + .setComponentUuid(file.uuid()) + .setComponentKey(file.getKey()) + .setProjectUuid(project.uuid()) + .setProjectKey(project.getKey()) + .setSeverity(BLOCKER) + .setStatus(STATUS_OPEN) + .setNew(true) + .setIsOnChangedLine(true) + .setIsNewCodeReferenceIssue(true) + .setIsNoLongerNewCodeReferenceIssue(false) + .setCopied(false) + .setType(RuleType.BUG) + .setCreationDate(new Date(NOW)) + .setSelectedAt(NOW); + + IssueDto issueDto = IssueDto.toDtoForComputationInsert(defaultIssue, rule.getUuid(), NOW); + dbClient.issueDao().insert(session, issueDto); + dbClient.issueDao().insertAsNewCodeOnReferenceBranch(session, newCodeReferenceIssue(issueDto)); + session.commit(); + + IssueDto result = dbClient.issueDao().selectOrFailByKey(session, issueKey); + assertThat(result.isNewCodeReferenceIssue()).isTrue(); + + protoIssueCache.newAppender().append(defaultIssue.setNew(false) + .setIsOnChangedLine(false) + .setIsNewCodeReferenceIssue(true) + .setIsOnChangedLine(true) + .setIsNoLongerNewCodeReferenceIssue(false)) + .close(); + + TestComputationStepContext context = new TestComputationStepContext(); + underTest.execute(context); + + assertThat(context.getStatistics().getAll()).contains( + entry("inserts", "0"), entry("updates", "0"), entry("merged", "0")); + + result = dbClient.issueDao().selectOrFailByKey(session, issueKey); + assertThat(result.isNewCodeReferenceIssue()).isTrue(); + } + @Test public void add_comment() { ComponentDto project = db.components().insertPrivateProject(); @@ -497,6 +607,8 @@ public class PersistIssuesStepTest extends BaseStepTest { .setSelectedAt(NOW) .setNew(false) .setChanged(true) + .setIsOnChangedLine(false) + .setIsNewCodeReferenceIssue(false) .setCurrentChange(new FieldDiffs() .setIssueKey("ISSUE") .setUserUuid("john_uuid") diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/issue/NewCodeReferenceIssueDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/issue/NewCodeReferenceIssueDto.java index 1ca29e296e6..719a12e7986 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/issue/NewCodeReferenceIssueDto.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/issue/NewCodeReferenceIssueDto.java @@ -66,4 +66,11 @@ public final class NewCodeReferenceIssueDto implements Serializable { .setIssueKey(issue.getKey()) .setCreatedAt(now); } + + public static NewCodeReferenceIssueDto fromIssueKey(String issueKey, long now, UuidFactory uuidFactory) { + return new NewCodeReferenceIssueDto() + .setUuid(uuidFactory.create()) + .setIssueKey(issueKey) + .setCreatedAt(now); + } } diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/issue/NewCodeReferenceIssueDtoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/issue/NewCodeReferenceIssueDtoTest.java index 2bcbd5d0189..ffa7d5dae27 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/issue/NewCodeReferenceIssueDtoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/issue/NewCodeReferenceIssueDtoTest.java @@ -45,4 +45,16 @@ public class NewCodeReferenceIssueDtoTest { assertThat(dto.getIssueKey()).isEqualTo(KEY); assertThat(dto.getCreatedAt()).isNotNull(); } + + @Test + public void create_from_issue_key() { + when(UUID_FACTORY.create()).thenReturn(UUID); + long now = System.currentTimeMillis(); + + NewCodeReferenceIssueDto dto = NewCodeReferenceIssueDto.fromIssueKey(KEY, now, UUID_FACTORY); + + assertThat(dto.getUuid()).isEqualTo(UUID); + assertThat(dto.getIssueKey()).isEqualTo(KEY); + assertThat(dto.getCreatedAt()).isNotNull(); + } } diff --git a/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java b/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java index 198bc25d418..b5d3a21c7ba 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java @@ -98,9 +98,6 @@ public class DefaultIssue implements Issue, Trackable, org.sonar.api.ce.measure. // true if the issue did not exist in the previous scan. private boolean isNew = true; - // true if the issue is on a branch using the reference branch new code strategy - private boolean isOnReferencedBranch = false; - // true if the issue is on a changed line on a branch using the reference branch new code strategy private boolean isOnChangedLine = false; @@ -396,10 +393,6 @@ public class DefaultIssue implements Issue, Trackable, org.sonar.api.ce.measure. return isNew; } - public boolean isOnReferencedBranch() { - return isOnReferencedBranch; - } - public boolean isOnChangedLine() { return isOnChangedLine; } @@ -419,11 +412,6 @@ public class DefaultIssue implements Issue, Trackable, org.sonar.api.ce.measure. return this; } - public DefaultIssue setIsOnReferencedBranch(boolean b) { - isOnReferencedBranch = b; - return this; - } - public DefaultIssue setIsOnChangedLine(boolean b) { isOnChangedLine = b; return this; @@ -554,6 +542,12 @@ public class DefaultIssue implements Issue, Trackable, org.sonar.api.ce.measure. return this; } + // true if the issue is new on a reference branch, + // but it's not persisted as such due to being created before the SQ 9.3 migration + public boolean isToBeMigratedAsNewCodeReferenceIssue() { + return isOnChangedLine && !isNewCodeReferenceIssue && !isNoLongerNewCodeReferenceIssue; + } + @CheckForNull public FieldDiffs currentChange() { return currentChange; diff --git a/sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueTest.java b/sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueTest.java index 97797a5a496..53d866457c0 100644 --- a/sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueTest.java +++ b/sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueTest.java @@ -19,7 +19,6 @@ */ package org.sonar.core.issue; -import com.google.common.collect.ImmutableMap; import java.text.SimpleDateFormat; import java.util.List; import org.apache.commons.lang.StringUtils; @@ -29,7 +28,6 @@ import org.sonar.api.rule.RuleKey; import org.sonar.api.utils.Duration; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.entry; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; @@ -56,7 +54,6 @@ public class DefaultIssueTest { .setAuthorLogin("steph") .setChecksum("c7b5db46591806455cf082bb348631e8") .setNew(true) - .setIsOnReferencedBranch(true) .setIsOnChangedLine(true) .setIsNewCodeReferenceIssue(true) .setIsNoLongerNewCodeReferenceIssue(true) @@ -87,10 +84,10 @@ public class DefaultIssueTest { assertThat(issue.authorLogin()).isEqualTo("steph"); assertThat(issue.checksum()).isEqualTo("c7b5db46591806455cf082bb348631e8"); assertThat(issue.isNew()).isTrue(); - assertThat(issue.isOnReferencedBranch()).isTrue(); assertThat(issue.isOnChangedLine()).isTrue(); assertThat(issue.isNewCodeReferenceIssue()).isTrue(); assertThat(issue.isNoLongerNewCodeReferenceIssue()).isTrue(); + assertThat(issue.isToBeMigratedAsNewCodeReferenceIssue()).isFalse(); assertThat(issue.isCopied()).isTrue(); assertThat(issue.isBeingClosed()).isTrue(); assertThat(issue.isOnDisabledRule()).isTrue(); @@ -208,6 +205,58 @@ public class DefaultIssueTest { assertThat(issue.changes()).isEmpty(); } + @Test + public void test_isToBeMigratedAsNewCodeReferenceIssue_is_correctly_calculated() { + issue.setKey("ABCD") + .setIsOnChangedLine(true) + .setIsNewCodeReferenceIssue(false) + .setIsNoLongerNewCodeReferenceIssue(false); + + assertThat(issue.isToBeMigratedAsNewCodeReferenceIssue()).isTrue(); + + issue.setKey("ABCD") + .setIsOnChangedLine(false) + .setIsNewCodeReferenceIssue(false) + .setIsNoLongerNewCodeReferenceIssue(false); + + assertThat(issue.isToBeMigratedAsNewCodeReferenceIssue()).isFalse(); + + issue.setKey("ABCD") + .setIsOnChangedLine(true) + .setIsNewCodeReferenceIssue(true) + .setIsNoLongerNewCodeReferenceIssue(false); + + assertThat(issue.isToBeMigratedAsNewCodeReferenceIssue()).isFalse(); + + issue.setKey("ABCD") + .setIsOnChangedLine(false) + .setIsNewCodeReferenceIssue(false) + .setIsNoLongerNewCodeReferenceIssue(true); + + assertThat(issue.isToBeMigratedAsNewCodeReferenceIssue()).isFalse(); + + issue.setKey("ABCD") + .setIsOnChangedLine(true) + .setIsNewCodeReferenceIssue(true) + .setIsNoLongerNewCodeReferenceIssue(true); + + assertThat(issue.isToBeMigratedAsNewCodeReferenceIssue()).isFalse(); + + issue.setKey("ABCD") + .setIsOnChangedLine(false) + .setIsNewCodeReferenceIssue(true) + .setIsNoLongerNewCodeReferenceIssue(true); + + assertThat(issue.isToBeMigratedAsNewCodeReferenceIssue()).isFalse(); + + issue.setKey("ABCD") + .setIsOnChangedLine(true) + .setIsNewCodeReferenceIssue(false) + .setIsNoLongerNewCodeReferenceIssue(true); + + assertThat(issue.isToBeMigratedAsNewCodeReferenceIssue()).isFalse(); + } + @Test public void isQuickFixAvailable_givenQuickFixAvailable_returnTrue() { DefaultIssue defaultIssue = new DefaultIssue();