3 * Copyright (C) 2009-2022 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.ce.task.projectanalysis.issue;
22 import java.util.Date;
23 import java.util.Optional;
24 import org.junit.Before;
25 import org.junit.Test;
26 import org.mockito.ArgumentCaptor;
27 import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
28 import org.sonar.ce.task.projectanalysis.component.Component;
29 import org.sonar.ce.task.projectanalysis.component.ReportComponent;
30 import org.sonar.ce.task.projectanalysis.filemove.MovedFilesRepository;
31 import org.sonar.core.issue.DefaultIssue;
32 import org.sonar.core.issue.IssueChangeContext;
33 import org.sonar.server.issue.IssueFieldsSetter;
35 import static org.assertj.core.api.Assertions.assertThat;
36 import static org.assertj.core.api.Assertions.assertThatThrownBy;
37 import static org.mockito.ArgumentMatchers.any;
38 import static org.mockito.ArgumentMatchers.eq;
39 import static org.mockito.Mockito.mock;
40 import static org.mockito.Mockito.verify;
41 import static org.mockito.Mockito.verifyNoInteractions;
42 import static org.mockito.Mockito.verifyNoMoreInteractions;
43 import static org.mockito.Mockito.when;
45 public class MovedIssueVisitorTest {
46 private static final long ANALYSIS_DATE = 894521;
47 private static final String FILE_UUID = "file uuid";
48 private static final Component FILE = ReportComponent.builder(Component.Type.FILE, 1)
50 .setPublicKey("public_key_1")
55 public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
57 private MovedFilesRepository movedFilesRepository = mock(MovedFilesRepository.class);
58 private MovedIssueVisitor underTest = new MovedIssueVisitor(analysisMetadataHolder, movedFilesRepository, new IssueFieldsSetter());
62 analysisMetadataHolder.setAnalysisDate(ANALYSIS_DATE);
63 when(movedFilesRepository.getOriginalFile(any(Component.class)))
64 .thenReturn(Optional.empty());
68 public void onIssue_does_not_alter_issue_if_component_is_not_a_file() {
69 DefaultIssue issue = mock(DefaultIssue.class);
70 underTest.onIssue(ReportComponent.builder(Component.Type.DIRECTORY, 1).build(), issue);
72 verifyNoInteractions(issue);
76 public void onIssue_does_not_alter_issue_if_component_file_but_issue_has_the_same_component_uuid() {
77 DefaultIssue issue = mockIssue(FILE_UUID);
78 underTest.onIssue(FILE, issue);
80 verify(issue).componentUuid();
81 verifyNoMoreInteractions(issue);
85 public void onIssue_throws_ISE_if_issue_has_different_component_uuid_but_component_has_no_original_file() {
86 DefaultIssue issue = mockIssue("other component uuid");
87 when(issue.toString()).thenReturn("[bad issue, bad!]");
89 assertThatThrownBy(() -> underTest.onIssue(FILE, issue))
90 .isInstanceOf(IllegalStateException.class)
91 .hasMessage("Issue [bad issue, bad!] for component ReportComponent{ref=1, key='key_1', type=FILE} " +
92 "has a different component key but no original file exist in MovedFilesRepository");
96 public void onIssue_throws_ISE_if_issue_has_different_component_uuid_from_component_but_it_is_not_the_one_of_original_file() {
97 DefaultIssue issue = mockIssue("other component uuid");
98 when(issue.toString()).thenReturn("[bad issue, bad!]");
99 when(movedFilesRepository.getOriginalFile(FILE))
100 .thenReturn(Optional.of(new MovedFilesRepository.OriginalFile("original uuid", "original key")));
102 assertThatThrownBy(() -> underTest.onIssue(FILE, issue))
103 .isInstanceOf(IllegalStateException.class)
104 .hasMessage("Issue [bad issue, bad!] doesn't belong to file original uuid registered as original " +
105 "file of current file ReportComponent{ref=1, key='key_1', type=FILE}");
109 public void onIssue_update_component_and_module_fields_to_component_and_flag_issue_has_changed() {
110 MovedFilesRepository.OriginalFile originalFile = new MovedFilesRepository.OriginalFile("original uuid", "original key");
111 DefaultIssue issue = mockIssue(originalFile.getUuid());
112 when(movedFilesRepository.getOriginalFile(FILE))
113 .thenReturn(Optional.of(originalFile));
115 underTest.onIssue(FILE, issue);
117 verify(issue).setComponentUuid(FILE.getUuid());
118 verify(issue).setComponentKey(FILE.getKey());
119 verify(issue).setModuleUuidPath(null);
120 verify(issue).setChanged(true);
121 ArgumentCaptor<IssueChangeContext> issueChangeContextCaptor = ArgumentCaptor.forClass(IssueChangeContext.class);
122 verify(issue).setFieldChange(issueChangeContextCaptor.capture(), eq("file"), eq(originalFile.getUuid()), eq(FILE.getUuid()));
123 assertThat(issueChangeContextCaptor.getValue().date()).isEqualTo(new Date(ANALYSIS_DATE));
124 assertThat(issueChangeContextCaptor.getValue().userUuid()).isNull();
125 assertThat(issueChangeContextCaptor.getValue().scan()).isFalse();
128 private DefaultIssue mockIssue(String fileUuid) {
129 DefaultIssue issue = mock(DefaultIssue.class);
130 when(issue.componentUuid()).thenReturn(fileUuid);