]> source.dussan.org Git - sonarqube.git/blob
e4ae60c52f027628658f8821ae754d928f0f1120
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2017 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.server.computation.task.projectanalysis.step;
21
22 import static org.mockito.Mockito.mock;
23 import static org.mockito.Mockito.when;
24
25 import java.util.Date;
26
27 import org.junit.Rule;
28 import org.junit.Test;
29 import org.junit.rules.ExpectedException;
30 import org.sonar.api.utils.DateUtils;
31 import org.sonar.api.utils.MessageException;
32 import org.sonar.api.utils.System2;
33 import org.sonar.db.DbClient;
34 import org.sonar.db.DbTester;
35 import org.sonar.db.component.ComponentDto;
36 import org.sonar.db.component.ComponentTesting;
37 import org.sonar.db.component.SnapshotTesting;
38 import org.sonar.db.organization.OrganizationDto;
39 import org.sonar.scanner.protocol.output.ScannerReport;
40 import org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType;
41 import org.sonar.server.computation.task.projectanalysis.analysis.Analysis;
42 import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
43 import org.sonar.server.computation.task.projectanalysis.analysis.Branch;
44 import org.sonar.server.computation.task.projectanalysis.component.DefaultBranchImpl;
45 import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReaderRule;
46 import org.sonar.server.computation.task.projectanalysis.component.Component;
47 import org.sonar.server.computation.task.projectanalysis.component.ReportComponent;
48 import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
49 import org.sonar.server.computation.task.projectanalysis.validation.ValidateIncremental;
50
51 public class ValidateProjectStepTest {
52
53   static long DEFAULT_ANALYSIS_TIME = 1433131200000L; // 2015-06-01
54   static final String PROJECT_KEY = "PROJECT_KEY";
55   static final String MODULE_KEY = "MODULE_KEY";
56   static final Branch DEFAULT_BRANCH = new DefaultBranchImpl();
57
58   @Rule
59   public DbTester dbTester = DbTester.create(System2.INSTANCE);
60
61   @Rule
62   public ExpectedException thrown = ExpectedException.none();
63
64   @Rule
65   public BatchReportReaderRule reportReader = new BatchReportReaderRule();
66
67   @Rule
68   public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
69
70   @Rule
71   public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule()
72     .setAnalysisDate(new Date(DEFAULT_ANALYSIS_TIME))
73     .setIncrementalAnalysis(false)
74     .setBranch(DEFAULT_BRANCH);
75
76   public ValidateIncremental validateIncremental = mock(ValidateIncremental.class);
77
78   DbClient dbClient = dbTester.getDbClient();
79
80   ValidateProjectStep underTest = new ValidateProjectStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder, validateIncremental);
81
82   @Test
83   public void fail_if_root_component_is_not_a_project_in_db() {
84     reportReader.putComponent(ScannerReport.Component.newBuilder()
85       .setRef(1)
86       .setType(ComponentType.PROJECT)
87       .setKey(PROJECT_KEY)
88       .build());
89     treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").setKey(PROJECT_KEY).build());
90
91     ComponentDto project = ComponentTesting.newView(dbTester.organizations().insert(), "ABCD").setDbKey(PROJECT_KEY);
92     dbClient.componentDao().insert(dbTester.getSession(), project);
93     dbTester.getSession().commit();
94
95     thrown.expect(MessageException.class);
96     thrown.expectMessage("Validation of project failed:\n" +
97       "  o Component (uuid=ABCD, key=PROJECT_KEY) is not a project");
98
99     underTest.execute();
100   }
101
102   @Test
103   public void fail_on_invalid_key() {
104     String invalidProjectKey = "Project\\Key";
105
106     reportReader.putComponent(ScannerReport.Component.newBuilder()
107       .setRef(1)
108       .setType(ComponentType.PROJECT)
109       .setKey(invalidProjectKey)
110       .addChildRef(2)
111       .build());
112     reportReader.putComponent(ScannerReport.Component.newBuilder()
113       .setRef(2)
114       .setType(ComponentType.MODULE)
115       .setKey("Module$Key")
116       .build());
117     treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").setKey(invalidProjectKey).addChildren(
118       ReportComponent.builder(Component.Type.MODULE, 2).setUuid("BCDE").setKey("Module$Key").build())
119       .build());
120
121     thrown.expect(MessageException.class);
122     thrown.expectMessage("Validation of project failed:\n" +
123       "  o \"Project\\Key\" is not a valid project or module key. Allowed characters are alphanumeric, '-', '_', '.' and ':', with at least one non-digit.\n" +
124       "  o \"Module$Key\" is not a valid project or module key. Allowed characters are alphanumeric, '-', '_', '.' and ':', with at least one non-digit");
125
126     underTest.execute();
127   }
128
129   @Test
130   public void fail_if_module_key_is_already_used_as_project_key() {
131     reportReader.putComponent(ScannerReport.Component.newBuilder()
132       .setRef(1)
133       .setType(ComponentType.PROJECT)
134       .setKey(PROJECT_KEY)
135       .addChildRef(2)
136       .build());
137     reportReader.putComponent(ScannerReport.Component.newBuilder()
138       .setRef(2)
139       .setType(ComponentType.MODULE)
140       .setKey(MODULE_KEY)
141       .build());
142
143     ComponentDto project = ComponentTesting.newPrivateProjectDto(dbTester.organizations().insert(), "ABCD").setDbKey(MODULE_KEY);
144     dbClient.componentDao().insert(dbTester.getSession(), project);
145     dbTester.getSession().commit();
146
147     treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").setKey(PROJECT_KEY).addChildren(
148       ReportComponent.builder(Component.Type.MODULE, 2).setUuid("BCDE").setKey(MODULE_KEY).build())
149       .build());
150
151     thrown.expect(MessageException.class);
152     thrown.expectMessage("Validation of project failed:\n" +
153       "  o The project \"" + MODULE_KEY + "\" is already defined in SonarQube but not as a module of project \"" + PROJECT_KEY + "\". " +
154       "If you really want to stop directly analysing project \"" + MODULE_KEY + "\", please first delete it from SonarQube and then relaunch the analysis of project \""
155       + PROJECT_KEY + "\".");
156
157     underTest.execute();
158   }
159
160   @Test
161   public void fail_if_module_key_already_exists_in_another_project() {
162     String anotherProjectKey = "ANOTHER_PROJECT_KEY";
163     reportReader.putComponent(ScannerReport.Component.newBuilder()
164       .setRef(1)
165       .setType(ComponentType.PROJECT)
166       .setKey(PROJECT_KEY)
167       .addChildRef(2)
168       .build());
169     reportReader.putComponent(ScannerReport.Component.newBuilder()
170       .setRef(2)
171       .setType(ComponentType.MODULE)
172       .setKey(MODULE_KEY)
173       .build());
174
175     OrganizationDto organizationDto = dbTester.organizations().insert();
176     ComponentDto project = ComponentTesting.newPrivateProjectDto(organizationDto, "ABCD").setDbKey(PROJECT_KEY);
177     ComponentDto anotherProject = ComponentTesting.newPrivateProjectDto(organizationDto).setDbKey(anotherProjectKey);
178     dbClient.componentDao().insert(dbTester.getSession(), project, anotherProject);
179     ComponentDto module = ComponentTesting.newModuleDto("BCDE", anotherProject).setDbKey(MODULE_KEY);
180     dbClient.componentDao().insert(dbTester.getSession(), module);
181     dbTester.getSession().commit();
182
183     treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").setKey(PROJECT_KEY).addChildren(
184       ReportComponent.builder(Component.Type.MODULE, 2).setUuid("BCDE").setKey(MODULE_KEY).build())
185       .build());
186
187     thrown.expect(MessageException.class);
188     thrown.expectMessage("Validation of project failed:\n" +
189       "  o Module \"" + MODULE_KEY + "\" is already part of project \"" + anotherProjectKey + "\"");
190
191     underTest.execute();
192   }
193
194   @Test
195   public void fail_if_project_key_already_exists_as_module() {
196     String anotherProjectKey = "ANOTHER_PROJECT_KEY";
197
198     reportReader.putComponent(ScannerReport.Component.newBuilder()
199       .setRef(1)
200       .setType(ComponentType.PROJECT)
201       .setKey(PROJECT_KEY)
202       .addChildRef(2)
203       .build());
204     reportReader.putComponent(ScannerReport.Component.newBuilder()
205       .setRef(2)
206       .setType(ComponentType.MODULE)
207       .setKey(MODULE_KEY)
208       .build());
209
210     ComponentDto anotherProject = ComponentTesting.newPrivateProjectDto(dbTester.organizations().insert()).setDbKey(anotherProjectKey);
211     dbClient.componentDao().insert(dbTester.getSession(), anotherProject);
212     ComponentDto module = ComponentTesting.newModuleDto("ABCD", anotherProject).setDbKey(PROJECT_KEY);
213     dbClient.componentDao().insert(dbTester.getSession(), module);
214     dbTester.getSession().commit();
215
216     treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").setKey(PROJECT_KEY).addChildren(
217       ReportComponent.builder(Component.Type.MODULE, 2).setUuid("BCDE").setKey(MODULE_KEY).build())
218       .build());
219
220     thrown.expect(MessageException.class);
221     thrown.expectMessage("Validation of project failed:\n" +
222       "  o Component (uuid=ABCD, key=PROJECT_KEY) is not a project\n" +
223       "  o The project \"" + PROJECT_KEY + "\" is already defined in SonarQube but as a module of project \"" + anotherProjectKey + "\". " +
224       "If you really want to stop directly analysing project \"" + anotherProjectKey + "\", please first delete it from SonarQube and then relaunch the analysis of project \""
225       + PROJECT_KEY + "\".");
226
227     underTest.execute();
228   }
229
230   @Test
231   public void not_fail_if_analysis_date_is_after_last_analysis() {
232     reportReader.putComponent(ScannerReport.Component.newBuilder()
233       .setRef(1)
234       .setType(ComponentType.PROJECT)
235       .setKey(PROJECT_KEY)
236       .addChildRef(2)
237       .build());
238
239     ComponentDto project = ComponentTesting.newPrivateProjectDto(dbTester.organizations().insert(), "ABCD").setDbKey(PROJECT_KEY);
240     dbClient.componentDao().insert(dbTester.getSession(), project);
241     dbClient.snapshotDao().insert(dbTester.getSession(), SnapshotTesting.newAnalysis(project).setCreatedAt(1420088400000L)); // 2015-01-01
242     dbTester.getSession().commit();
243
244     treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").setKey(PROJECT_KEY).build());
245
246     underTest.execute();
247   }
248
249   @Test
250   public void fail_if_analysis_date_is_before_last_analysis() {
251     analysisMetadataHolder.setAnalysisDate(DateUtils.parseDate("2015-01-01"));
252
253     reportReader.putComponent(ScannerReport.Component.newBuilder()
254       .setRef(1)
255       .setType(ComponentType.PROJECT)
256       .setKey(PROJECT_KEY)
257       .addChildRef(2)
258       .build());
259
260     ComponentDto project = ComponentTesting.newPrivateProjectDto(dbTester.organizations().insert(), "ABCD").setDbKey(PROJECT_KEY);
261     dbClient.componentDao().insert(dbTester.getSession(), project);
262     dbClient.snapshotDao().insert(dbTester.getSession(), SnapshotTesting.newAnalysis(project).setCreatedAt(1433131200000L)); // 2015-06-01
263     dbTester.getSession().commit();
264
265     treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").setKey(PROJECT_KEY).build());
266
267     thrown.expect(MessageException.class);
268     thrown.expectMessage("Validation of project failed:");
269     thrown.expectMessage("Date of analysis cannot be older than the date of the last known analysis on this project. Value: ");
270     thrown.expectMessage("Latest analysis: ");
271
272     underTest.execute();
273   }
274
275   @Test
276   public void fail_if_incremental_plugin_not_found() {
277     ValidateProjectStep underTest = new ValidateProjectStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder, null);
278
279     when(validateIncremental.execute()).thenReturn(false);
280     analysisMetadataHolder.setBaseAnalysis(new Analysis.Builder().setId(1).setUuid("base").setCreatedAt(DEFAULT_ANALYSIS_TIME).build());
281     analysisMetadataHolder.setIncrementalAnalysis(true);
282
283     reportReader.putComponent(ScannerReport.Component.newBuilder()
284       .setRef(1)
285       .setType(ComponentType.PROJECT)
286       .setKey(PROJECT_KEY)
287       .addChildRef(2)
288       .build());
289
290     treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").setKey(PROJECT_KEY).build());
291
292     thrown.expect(MessageException.class);
293     thrown.expectMessage("Validation of project failed:");
294     thrown.expectMessage("Can't process an incremental analysis of the project \"PROJECT_KEY\" because the incremental plugin is not loaded");
295
296     underTest.execute();
297   }
298
299   @Test
300   public void fail_if_incremental_validation_fails() {
301     when(validateIncremental.execute()).thenReturn(false);
302     analysisMetadataHolder.setBaseAnalysis(new Analysis.Builder().setId(1).setUuid("base").setCreatedAt(DEFAULT_ANALYSIS_TIME).build());
303     analysisMetadataHolder.setIncrementalAnalysis(true);
304
305     reportReader.putComponent(ScannerReport.Component.newBuilder()
306       .setRef(1)
307       .setType(ComponentType.PROJECT)
308       .setKey(PROJECT_KEY)
309       .addChildRef(2)
310       .build());
311
312     treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").setKey(PROJECT_KEY).build());
313
314     thrown.expect(MessageException.class);
315     thrown.expectMessage("Validation of project failed:");
316     thrown.expectMessage("The installation of the incremental plugin is invalid");
317
318     underTest.execute();
319   }
320
321   @Test
322   public void fail_if_incremental_and_first_analysis() {
323     when(validateIncremental.execute()).thenReturn(true);
324     analysisMetadataHolder.setBaseAnalysis(null);
325     analysisMetadataHolder.setIncrementalAnalysis(true);
326
327     reportReader.putComponent(ScannerReport.Component.newBuilder()
328       .setRef(1)
329       .setType(ComponentType.PROJECT)
330       .setKey(PROJECT_KEY)
331       .addChildRef(2)
332       .build());
333
334     treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").setKey(PROJECT_KEY).build());
335
336     thrown.expect(MessageException.class);
337     thrown.expectMessage("Validation of project failed:");
338     thrown.expectMessage("hasn't been analysed before and the first analysis can't be incremental. Please launch a full analysis of the project.");
339
340     underTest.execute();
341   }
342 }