3 * Copyright (C) 2009-2019 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 com.google.common.base.Optional;
23 import java.util.Date;
24 import org.junit.Before;
25 import org.junit.Test;
26 import org.junit.rules.ExpectedException;
27 import org.mockito.ArgumentCaptor;
28 import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
29 import org.sonar.ce.task.projectanalysis.component.Component;
30 import org.sonar.ce.task.projectanalysis.component.ReportComponent;
31 import org.sonar.ce.task.projectanalysis.filemove.MovedFilesRepository;
32 import org.sonar.core.issue.DefaultIssue;
33 import org.sonar.core.issue.IssueChangeContext;
34 import org.sonar.server.issue.IssueFieldsSetter;
36 import static org.assertj.core.api.Assertions.assertThat;
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.verifyNoMoreInteractions;
42 import static org.mockito.Mockito.verifyZeroInteractions;
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 ExpectedException expectedException = ExpectedException.none();
57 public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
59 private MovedFilesRepository movedFilesRepository = mock(MovedFilesRepository.class);
60 private MovedIssueVisitor underTest = new MovedIssueVisitor(analysisMetadataHolder, movedFilesRepository, new IssueFieldsSetter());
63 public void setUp() throws Exception {
64 analysisMetadataHolder.setAnalysisDate(ANALYSIS_DATE);
65 when(movedFilesRepository.getOriginalFile(any(Component.class)))
66 .thenReturn(Optional.absent());
70 public void onIssue_does_not_alter_issue_if_component_is_not_a_file() {
71 DefaultIssue issue = mock(DefaultIssue.class);
72 underTest.onIssue(ReportComponent.builder(Component.Type.DIRECTORY, 1).build(), issue);
74 verifyZeroInteractions(issue);
78 public void onIssue_does_not_alter_issue_if_component_file_but_issue_has_the_same_component_uuid() {
79 DefaultIssue issue = mockIssue(FILE_UUID);
80 underTest.onIssue(FILE, issue);
82 verify(issue).componentUuid();
83 verifyNoMoreInteractions(issue);
87 public void onIssue_throws_ISE_if_issue_has_different_component_uuid_but_component_has_no_original_file() {
88 DefaultIssue issue = mockIssue("other component uuid");
89 when(issue.toString()).thenReturn("[bad issue, bad!]");
91 expectedException.expect(IllegalStateException.class);
92 expectedException.expectMessage("Issue [bad issue, bad!] for component ReportComponent{ref=1, key='key_1', type=FILE} " +
93 "has a different component key but no original file exist in MovedFilesRepository");
95 underTest.onIssue(FILE, issue);
99 public void onIssue_throws_ISE_if_issue_has_different_component_uuid_from_component_but_it_is_not_the_one_of_original_file() {
100 DefaultIssue issue = mockIssue("other component uuid");
101 when(issue.toString()).thenReturn("[bad issue, bad!]");
102 when(movedFilesRepository.getOriginalFile(FILE))
103 .thenReturn(Optional.of(new MovedFilesRepository.OriginalFile(6451, "original uuid", "original key")));
105 expectedException.expect(IllegalStateException.class);
106 expectedException.expectMessage("Issue [bad issue, bad!] doesn't belong to file original uuid registered as original " +
107 "file of current file ReportComponent{ref=1, key='key_1', type=FILE}");
109 underTest.onIssue(FILE, issue);
113 public void onIssue_update_component_and_module_fields_to_component_and_flag_issue_has_changed() {
114 MovedFilesRepository.OriginalFile originalFile = new MovedFilesRepository.OriginalFile(6451, "original uuid", "original key");
115 DefaultIssue issue = mockIssue(originalFile.getUuid());
116 when(movedFilesRepository.getOriginalFile(FILE))
117 .thenReturn(Optional.of(originalFile));
119 underTest.onIssue(FILE, issue);
121 verify(issue).setComponentUuid(FILE.getUuid());
122 verify(issue).setComponentKey(FILE.getKey());
123 verify(issue).setModuleUuid(null);
124 verify(issue).setModuleUuidPath(null);
125 verify(issue).setChanged(true);
126 ArgumentCaptor<IssueChangeContext> issueChangeContextCaptor = ArgumentCaptor.forClass(IssueChangeContext.class);
127 verify(issue).setFieldChange(issueChangeContextCaptor.capture(), eq("file"), eq(originalFile.getUuid()), eq(FILE.getUuid()));
128 assertThat(issueChangeContextCaptor.getValue().date()).isEqualTo(new Date(ANALYSIS_DATE));
129 assertThat(issueChangeContextCaptor.getValue().userUuid()).isNull();
130 assertThat(issueChangeContextCaptor.getValue().scan()).isFalse();
133 private DefaultIssue mockIssue(String fileUuid) {
134 DefaultIssue issue = mock(DefaultIssue.class);
135 when(issue.componentUuid()).thenReturn(fileUuid);