From: Ngx <108925779+nicolas-gouteux-sonarsource@users.noreply.github.com> Date: Thu, 11 Apr 2024 13:19:51 +0000 (+0200) Subject: SONAR-22030 make sure field anticipatedTransitions is never null (#10949) X-Git-Tag: 10.5.0.89998~9 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=ba07204fd4e62749f7de8e6106036aee7acc113b;p=sonarqube.git SONAR-22030 make sure field anticipatedTransitions is never null (#10949) --- diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/TransitionIssuesToAnticipatedStatesVisitor.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/TransitionIssuesToAnticipatedStatesVisitor.java index 9a9ddf0b999..ea5c35927c4 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/TransitionIssuesToAnticipatedStatesVisitor.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/TransitionIssuesToAnticipatedStatesVisitor.java @@ -21,6 +21,7 @@ package org.sonar.ce.task.projectanalysis.issue; import java.time.Instant; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; import org.apache.logging.log4j.util.Strings; @@ -53,7 +54,8 @@ public class TransitionIssuesToAnticipatedStatesVisitor extends IssueVisitor { private final AnticipatedTransitionRepository anticipatedTransitionRepository; - public TransitionIssuesToAnticipatedStatesVisitor(AnticipatedTransitionRepository anticipatedTransitionRepository, IssueLifecycle issueLifecycle, CeTaskMessages ceTaskMessages) { + public TransitionIssuesToAnticipatedStatesVisitor(AnticipatedTransitionRepository anticipatedTransitionRepository, + IssueLifecycle issueLifecycle, CeTaskMessages ceTaskMessages) { this.anticipatedTransitionRepository = anticipatedTransitionRepository; this.issueLifecycle = issueLifecycle; this.ceTaskMessages = ceTaskMessages; @@ -63,6 +65,8 @@ public class TransitionIssuesToAnticipatedStatesVisitor extends IssueVisitor { public void beforeComponent(Component component) { if (FILE.equals(component.getType())) { anticipatedTransitions = anticipatedTransitionRepository.getAnticipatedTransitionByComponent(component); + } else { + anticipatedTransitions = Collections.emptyList(); } } @@ -104,5 +108,4 @@ public class TransitionIssuesToAnticipatedStatesVisitor extends IssueVisitor { String componentKey = componentKeyLength > MAX_LENGTH ? ("..." + issue.componentKey().substring(componentKeyLength - MAX_LENGTH, componentKeyLength)) : issue.componentKey(); return String.format(TRANSITION_ERROR_TEMPLATE.replace("{}", "%s"), issue.getLine(), componentKey, e.getMessage()); } - } diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/TransitionIssuesToAnticipatedStatesVisitorTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/TransitionIssuesToAnticipatedStatesVisitorTest.java index 8c8c6e36e06..94a74d9dbd1 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/TransitionIssuesToAnticipatedStatesVisitorTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/TransitionIssuesToAnticipatedStatesVisitorTest.java @@ -50,6 +50,7 @@ import static org.sonar.api.issue.Issue.STATUS_RESOLVED; import static org.sonar.ce.task.projectanalysis.component.Component.Type.PROJECT; public class TransitionIssuesToAnticipatedStatesVisitorTest { + @Rule public LogTester logTester = new LogTester(); private final IssueLifecycle issueLifecycle = mock(IssueLifecycle.class); @@ -58,12 +59,14 @@ public class TransitionIssuesToAnticipatedStatesVisitorTest { private final CeTaskMessages ceTaskMessages = mock(CeTaskMessages.class); - private final TransitionIssuesToAnticipatedStatesVisitor underTest = new TransitionIssuesToAnticipatedStatesVisitor(anticipatedTransitionRepository, issueLifecycle, ceTaskMessages); + private final TransitionIssuesToAnticipatedStatesVisitor underTest = + new TransitionIssuesToAnticipatedStatesVisitor(anticipatedTransitionRepository, issueLifecycle, ceTaskMessages); @Test public void givenMatchingAnticipatedTransitions_transitionsShouldBeAppliedToIssues() { Component component = getComponent(Component.Type.FILE); - when(anticipatedTransitionRepository.getAnticipatedTransitionByComponent(component)).thenReturn(getAnticipatedTransitions("projectKey", "fileName")); + when(anticipatedTransitionRepository.getAnticipatedTransitionByComponent(component)) + .thenReturn(getAnticipatedTransitions("projectKey", "fileName")); DefaultIssue issue = getDefaultIssue(1, "abcdefghi", "issue message"); @@ -81,7 +84,8 @@ public class TransitionIssuesToAnticipatedStatesVisitorTest { Component component = getComponent(Component.Type.FILE); String exceptionMessage = "Cannot apply transition"; - when(anticipatedTransitionRepository.getAnticipatedTransitionByComponent(component)).thenReturn(getAnticipatedTransitions("projectKey", "fileName")); + when(anticipatedTransitionRepository.getAnticipatedTransitionByComponent(component)) + .thenReturn(getAnticipatedTransitions("projectKey", "fileName")); doThrow(new IllegalStateException(exceptionMessage)).when(issueLifecycle).doManualTransition(any(), any(), any()); DefaultIssue issue = getDefaultIssue(1, "abcdefghi", "issue message"); issue.setComponentKey(component.getKey()); @@ -101,7 +105,8 @@ public class TransitionIssuesToAnticipatedStatesVisitorTest { @Test public void givenMatchingAnticipatedTransitionsOnResolvedIssue_transitionsShouldNotBeAppliedToIssues() { Component component = getComponent(Component.Type.FILE); - when(anticipatedTransitionRepository.getAnticipatedTransitionByComponent(component)).thenReturn(getAnticipatedTransitions("projectKey", "fileName")); + when(anticipatedTransitionRepository.getAnticipatedTransitionByComponent(component)) + .thenReturn(getAnticipatedTransitions("projectKey", "fileName")); DefaultIssue issue = getDefaultIssue(1, "abcdefghi", "issue message"); issue.setStatus(STATUS_RESOLVED); @@ -117,7 +122,8 @@ public class TransitionIssuesToAnticipatedStatesVisitorTest { @Test public void givenMatchingAnticipatedTransitions_whenIssueIsNotNew_transitionsShouldNotBeAppliedToIssues() { Component component = getComponent(Component.Type.FILE); - when(anticipatedTransitionRepository.getAnticipatedTransitionByComponent(component)).thenReturn(getAnticipatedTransitions("projectKey", "fileName")); + when(anticipatedTransitionRepository.getAnticipatedTransitionByComponent(component)) + .thenReturn(getAnticipatedTransitions("projectKey", "fileName")); DefaultIssue issue = getDefaultIssue(1, "abcdefghi", "issue message"); issue.setNew(false); @@ -133,7 +139,8 @@ public class TransitionIssuesToAnticipatedStatesVisitorTest { @Test public void givenNonMatchingAnticipatedTransitions_transitionsAreNotAppliedToIssues() { Component component = getComponent(Component.Type.FILE); - when(anticipatedTransitionRepository.getAnticipatedTransitionByComponent(component)).thenReturn(getAnticipatedTransitions("projectKey", "fileName")); + when(anticipatedTransitionRepository.getAnticipatedTransitionByComponent(component)) + .thenReturn(getAnticipatedTransitions("projectKey", "fileName")); DefaultIssue issue = getDefaultIssue(2, "abcdefghf", "another issue message"); @@ -148,7 +155,8 @@ public class TransitionIssuesToAnticipatedStatesVisitorTest { @Test public void givenMatchingAnticipatedTransitionsWithEmptyComment_transitionsShouldBeAppliedToIssuesAndDefaultCommentApplied() { Component component = getComponent(Component.Type.FILE); - when(anticipatedTransitionRepository.getAnticipatedTransitionByComponent(component)).thenReturn(getAnticipatedTransitionsWithEmptyComment("projectKey", "fileName")); + when(anticipatedTransitionRepository.getAnticipatedTransitionByComponent(component)) + .thenReturn(getAnticipatedTransitionsWithEmptyComment("projectKey", "fileName")); DefaultIssue issue = getDefaultIssue(1, "abcdefghi", "issue message"); @@ -181,12 +189,25 @@ public class TransitionIssuesToAnticipatedStatesVisitorTest { verifyNoInteractions(anticipatedTransitionRepository); } + @Test + public void givenAProjecComponent_the_issue_is_not_affected() { + Component component = getComponent(PROJECT); + DefaultIssue issue = getDefaultIssue(1, "abcdefghi", "issue message"); + + underTest.beforeComponent(component); + underTest.onIssue(component, issue); + assertThat(issue.getAnticipatedTransitionUuid()).isEmpty(); + assertThat(issue.isBeingClosed()).isFalse(); + } + private Collection getAnticipatedTransitions(String projecKey, String fileName) { - return Stream.of(new AnticipatedTransition("atuuid", projecKey, "admin", RuleKey.parse("repo:id"), "issue message", fileName, 1, "abcdefghi", DefaultTransitions.ACCEPT, "doing the transition in an anticipated way")).toList(); + return Stream.of(new AnticipatedTransition("atuuid", projecKey, "admin", RuleKey.parse("repo:id"), "issue message", fileName, 1, + "abcdefghi", DefaultTransitions.ACCEPT, "doing the transition in an anticipated way")).toList(); } private Collection getAnticipatedTransitionsWithEmptyComment(String projecKey, String fileName) { - return Stream.of(new AnticipatedTransition("atuuid", projecKey, "admin", RuleKey.parse("repo:id"), "issue message", fileName, 1, "abcdefghi", DefaultTransitions.ACCEPT, null)).toList(); + return Stream.of(new AnticipatedTransition("atuuid", projecKey, "admin", RuleKey.parse("repo:id"), "issue message", fileName, 1, + "abcdefghi", DefaultTransitions.ACCEPT, null)).toList(); } private Component getComponent(Component.Type type) {