]> source.dussan.org Git - sonarqube.git/blob
df5120f8d6869ab60a83dee57dc12ac3b16821f5
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2024 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.source;
21
22 import com.tngtech.java.junit.dataprovider.DataProvider;
23 import com.tngtech.java.junit.dataprovider.DataProviderRunner;
24 import com.tngtech.java.junit.dataprovider.UseDataProvider;
25 import java.util.Arrays;
26 import java.util.Random;
27 import java.util.stream.Collectors;
28 import java.util.stream.IntStream;
29 import org.junit.Test;
30 import org.junit.runner.RunWith;
31 import org.sonar.api.utils.System2;
32 import org.sonar.ce.task.log.CeTaskMessages;
33 import org.sonar.ce.task.projectanalysis.component.Component;
34 import org.sonar.ce.task.projectanalysis.component.ReportComponent;
35 import org.sonar.ce.task.projectanalysis.source.linereader.LineReader;
36
37 import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
38 import static org.assertj.core.api.Assertions.assertThatThrownBy;
39 import static org.mockito.Mockito.mock;
40 import static org.mockito.Mockito.times;
41 import static org.mockito.Mockito.verify;
42 import static org.mockito.Mockito.verifyNoInteractions;
43 import static org.mockito.Mockito.when;
44 import static org.sonar.ce.task.projectanalysis.source.linereader.LineReader.Data.HIGHLIGHTING;
45 import static org.sonar.ce.task.projectanalysis.source.linereader.LineReader.Data.SYMBOLS;
46
47 @RunWith(DataProviderRunner.class)
48 public class FileSourceDataWarningsTest {
49
50   private CeTaskMessages taskMessages = mock(CeTaskMessages.class);
51   private System2 system2 = mock(System2.class);
52   private Random random = new Random();
53   private int line = 1 + new Random().nextInt(200);
54   private long timeStamp = 9_887L + new Random().nextInt(300);
55   private String path = randomAlphabetic(50);
56
57   private FileSourceDataWarnings underTest = new FileSourceDataWarnings(taskMessages, system2);
58
59   @Test
60   public void addWarning_fails_with_NPE_if_file_is_null() {
61     LineReader.ReadError readError = new LineReader.ReadError(HIGHLIGHTING, 2);
62
63     assertThatThrownBy(() -> underTest.addWarning(null, readError))
64       .isInstanceOf(NullPointerException.class)
65       .hasMessage("file can't be null");
66   }
67
68   @Test
69   public void addWarning_fails_with_NPE_if_readError_is_null() {
70     Component component = mock(Component.class);
71
72     assertThatThrownBy(() -> underTest.addWarning(component, null))
73       .isInstanceOf(NullPointerException.class)
74       .hasMessage("readError can't be null");
75   }
76
77   @Test
78   public void addWarnings_fails_with_ISE_if_called_after_commitWarnings() {
79     underTest.commitWarnings();
80
81     assertThatThrownBy(() -> underTest.addWarning(null /*doesn't matter*/, null /*doesn't matter*/))
82       .isInstanceOf(IllegalStateException.class)
83       .hasMessage("warnings already commit");
84   }
85
86   @Test
87   public void commitWarnings_fails_with_ISE_if_called_after_commitWarnings() {
88     underTest.commitWarnings();
89
90     assertThatThrownBy(() -> underTest.commitWarnings())
91       .isInstanceOf(IllegalStateException.class)
92       .hasMessage("warnings already commit");
93   }
94
95   @Test
96   public void create_highlighting_warning_when_one_file_HIGHLIGHT_read_error() {
97     ReportComponent file = ReportComponent.builder(Component.Type.FILE, 1)
98       .setUuid("uuid")
99       .setName(path)
100       .build();
101     LineReader.ReadError readError = new LineReader.ReadError(HIGHLIGHTING, line);
102     when(system2.now()).thenReturn(timeStamp);
103
104     underTest.addWarning(file, readError);
105
106     verifyNoInteractions(taskMessages);
107
108     underTest.commitWarnings();
109
110     verify(taskMessages, times(1))
111       .add(new CeTaskMessages.Message("Inconsistent highlighting data detected on file '" + path + "'. " +
112         "File source may have been modified while analysis was running.", timeStamp));
113   }
114
115   @Test
116   public void create_highlighting_warning_when_any_number_of_read_error_for_one_file() {
117     ReportComponent file = ReportComponent.builder(Component.Type.FILE, 1)
118       .setUuid("uuid")
119       .setName(path)
120       .build();
121     LineReader.ReadError[] readErrors = IntStream.range(0, 1 + random.nextInt(10))
122       .mapToObj(i -> new LineReader.ReadError(HIGHLIGHTING, line + i))
123       .toArray(LineReader.ReadError[]::new);
124     when(system2.now()).thenReturn(timeStamp);
125
126     Arrays.stream(readErrors).forEach(readError -> underTest.addWarning(file, readError));
127
128     verifyNoInteractions(taskMessages);
129
130     underTest.commitWarnings();
131
132     verify(taskMessages, times(1))
133       .add(new CeTaskMessages.Message("Inconsistent highlighting data detected on file '" + path + "'. " +
134         "File source may have been modified while analysis was running.", timeStamp));
135   }
136
137   @Test
138   public void create_highlighting_warning_when_any_number_of_read_error_for_less_than_5_files() {
139     int fileCount = 2 + random.nextInt(3);
140     Component[] files = IntStream.range(0, fileCount)
141       .mapToObj(i -> ReportComponent.builder(Component.Type.FILE, i)
142         .setUuid("uuid_" + i)
143         .setName(path + "_" + i)
144         .build())
145       .toArray(Component[]::new);
146     when(system2.now()).thenReturn(timeStamp);
147
148     Arrays.stream(files).forEach(file -> IntStream.range(0, 1 + random.nextInt(10))
149       .forEach(i -> underTest.addWarning(file, new LineReader.ReadError(HIGHLIGHTING, line + i))));
150
151     verifyNoInteractions(taskMessages);
152
153     underTest.commitWarnings();
154
155     String expectedMessage = "Inconsistent highlighting data detected on some files (" + fileCount + " in total). " +
156       "File source may have been modified while analysis was running." +
157       Arrays.stream(files).map(Component::getName).collect(Collectors.joining("\n   ° ", "\n   ° ", ""));
158     verify(taskMessages, times(1))
159       .add(new CeTaskMessages.Message(expectedMessage, timeStamp));
160   }
161
162   @Test
163   public void create_highlighting_warning_when_any_number_of_read_error_for_more_than_5_files_only_the_5_first_by_ref() {
164     int fileCount = 6 + random.nextInt(4);
165     Component[] files = IntStream.range(0, fileCount)
166       .mapToObj(i -> ReportComponent.builder(Component.Type.FILE, i)
167         .setUuid("uuid_" + i)
168         .setName(path + "_" + i)
169         .build())
170       .toArray(Component[]::new);
171     when(system2.now()).thenReturn(timeStamp);
172
173     Arrays.stream(files).forEach(file -> IntStream.range(0, 1 + random.nextInt(10))
174       .forEach(i -> underTest.addWarning(file, new LineReader.ReadError(HIGHLIGHTING, line + i))));
175
176     verifyNoInteractions(taskMessages);
177
178     underTest.commitWarnings();
179
180     String expectedMessage = "Inconsistent highlighting data detected on some files (" + fileCount + " in total). " +
181       "File source may have been modified while analysis was running." +
182       Arrays.stream(files).limit(5).map(Component::getName).collect(Collectors.joining("\n   ° ", "\n   ° ", ""));
183     verify(taskMessages, times(1))
184       .add(new CeTaskMessages.Message(expectedMessage, timeStamp));
185   }
186
187   @Test
188   public void create_symbol_warning_when_one_file_HIGHLIGHT_read_error() {
189     ReportComponent file = ReportComponent.builder(Component.Type.FILE, 1)
190       .setUuid("uuid")
191       .setName(path)
192       .build();
193     LineReader.ReadError readError = new LineReader.ReadError(SYMBOLS, line);
194     when(system2.now()).thenReturn(timeStamp);
195
196     underTest.addWarning(file, readError);
197
198     verifyNoInteractions(taskMessages);
199
200     underTest.commitWarnings();
201
202     verify(taskMessages, times(1))
203       .add(new CeTaskMessages.Message("Inconsistent symbol data detected on file '" + path + "'. " +
204         "File source may have been modified while analysis was running.", timeStamp));
205   }
206
207   @Test
208   public void create_symbol_warning_when_any_number_of_read_error_for_one_file() {
209     ReportComponent file = ReportComponent.builder(Component.Type.FILE, 1)
210       .setUuid("uuid")
211       .setName(path)
212       .build();
213     LineReader.ReadError[] readErrors = IntStream.range(0, 1 + random.nextInt(10))
214       .mapToObj(i -> new LineReader.ReadError(SYMBOLS, line + i))
215       .toArray(LineReader.ReadError[]::new);
216     when(system2.now()).thenReturn(timeStamp);
217
218     Arrays.stream(readErrors).forEach(readError -> underTest.addWarning(file, readError));
219
220     verifyNoInteractions(taskMessages);
221
222     underTest.commitWarnings();
223
224     verify(taskMessages, times(1))
225       .add(new CeTaskMessages.Message("Inconsistent symbol data detected on file '" + path + "'. " +
226         "File source may have been modified while analysis was running.", timeStamp));
227   }
228
229   @Test
230   public void create_symbol_warning_when_any_number_of_read_error_for_less_than_5_files() {
231     int fileCount = 2 + random.nextInt(3);
232     Component[] files = IntStream.range(0, fileCount)
233       .mapToObj(i -> ReportComponent.builder(Component.Type.FILE, i)
234         .setUuid("uuid_" + i)
235         .setName(path + "_" + i)
236         .build())
237       .toArray(Component[]::new);
238     when(system2.now()).thenReturn(timeStamp);
239
240     Arrays.stream(files).forEach(file -> IntStream.range(0, 1 + random.nextInt(10))
241       .forEach(i -> underTest.addWarning(file, new LineReader.ReadError(SYMBOLS, line + i))));
242
243     verifyNoInteractions(taskMessages);
244
245     underTest.commitWarnings();
246
247     String expectedMessage = "Inconsistent symbol data detected on some files (" + fileCount + " in total). " +
248       "File source may have been modified while analysis was running." +
249       Arrays.stream(files).map(Component::getName).collect(Collectors.joining("\n   ° ", "\n   ° ", ""));
250     verify(taskMessages, times(1))
251       .add(new CeTaskMessages.Message(expectedMessage, timeStamp));
252   }
253
254   @Test
255   public void create_symbol_warning_when_any_number_of_read_error_for_more_than_5_files_only_the_5_first_by_ref() {
256     int fileCount = 6 + random.nextInt(4);
257     Component[] files = IntStream.range(0, fileCount)
258       .mapToObj(i -> ReportComponent.builder(Component.Type.FILE, i)
259         .setUuid("uuid_" + i)
260         .setName(path + "_" + i)
261         .build())
262       .toArray(Component[]::new);
263     when(system2.now()).thenReturn(timeStamp);
264
265     Arrays.stream(files).forEach(file -> IntStream.range(0, 1 + random.nextInt(10))
266       .forEach(i -> underTest.addWarning(file, new LineReader.ReadError(SYMBOLS, line + i))));
267
268     verifyNoInteractions(taskMessages);
269
270     underTest.commitWarnings();
271
272     String expectedMessage = "Inconsistent symbol data detected on some files (" + fileCount + " in total). " +
273       "File source may have been modified while analysis was running." +
274       Arrays.stream(files).limit(5).map(Component::getName).collect(Collectors.joining("\n   ° ", "\n   ° ", ""));
275     verify(taskMessages, times(1))
276       .add(new CeTaskMessages.Message(expectedMessage, timeStamp));
277   }
278
279   @Test
280   @UseDataProvider("anyDataButHighlightAndSymbols")
281   public void creates_no_warning_when_read_error_for_anything_but_highlighting_and_symbols(LineReader.Data data) {
282     ReportComponent file = ReportComponent.builder(Component.Type.FILE, 1)
283       .setUuid("uuid")
284       .setName(path)
285       .build();
286     LineReader.ReadError readError = new LineReader.ReadError(data, line);
287     when(system2.now()).thenReturn(timeStamp);
288
289     underTest.addWarning(file, readError);
290
291     verifyNoInteractions(taskMessages);
292
293     underTest.commitWarnings();
294
295     verifyNoInteractions(taskMessages);
296   }
297
298   @DataProvider
299   public static Object[][] anyDataButHighlightAndSymbols() {
300     return Arrays.stream(LineReader.Data.values())
301       .filter(t -> t != HIGHLIGHTING && t != SYMBOLS)
302       .map(t -> new Object[] {t})
303       .toArray(Object[][]::new);
304   }
305 }