]> source.dussan.org Git - sonarqube.git/blob
9f681bc0a10faa80517970c3006f2397000f562d
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2016 SonarSource SA
4  * mailto:contact 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 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.HashMap;
26 import java.util.Map;
27 import javax.annotation.Nullable;
28 import org.junit.Rule;
29 import org.junit.Test;
30 import org.junit.runner.RunWith;
31 import org.sonar.api.utils.System2;
32 import org.sonar.db.DbClient;
33 import org.sonar.db.DbTester;
34 import org.sonar.db.component.ComponentDto;
35 import org.sonar.db.component.SnapshotDto;
36 import org.sonar.scanner.protocol.output.ScannerReport;
37 import org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType;
38 import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderImpl;
39 import org.sonar.server.computation.task.projectanalysis.analysis.MutableAnalysisMetadataHolder;
40 import org.sonar.server.computation.task.projectanalysis.analysis.MutableAnalysisMetadataHolderRule;
41 import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReaderRule;
42 import org.sonar.server.computation.task.projectanalysis.component.Component;
43 import org.sonar.server.computation.task.projectanalysis.component.MutableTreeRootHolderRule;
44
45 import static com.google.common.base.Predicates.in;
46 import static com.google.common.base.Predicates.not;
47 import static com.google.common.collect.FluentIterable.from;
48 import static java.util.Arrays.asList;
49 import static org.assertj.core.api.Assertions.assertThat;
50 import static org.sonar.db.component.ComponentTesting.newDirectory;
51 import static org.sonar.db.component.ComponentTesting.newFileDto;
52 import static org.sonar.db.component.ComponentTesting.newModuleDto;
53 import static org.sonar.db.component.ComponentTesting.newProjectDto;
54 import static org.sonar.db.component.SnapshotTesting.newAnalysis;
55 import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.DIRECTORY;
56 import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.FILE;
57 import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.MODULE;
58 import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.PROJECT;
59 import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.UNRECOGNIZED;
60 import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.UNSET;
61
62 @RunWith(DataProviderRunner.class)
63 public class BuildComponentTreeStepTest {
64
65   static final int ROOT_REF = 1;
66   static final int MODULE_REF = 2;
67   static final int DIR_REF_1 = 3;
68   static final int FILE_1_REF = 4;
69   static final int FILE_2_REF = 5;
70   static final int DIR_REF_2 = 6;
71   static final int FILE_3_REF = 7;
72
73   static final String REPORT_PROJECT_KEY = "REPORT_PROJECT_KEY";
74   static final String REPORT_MODULE_KEY = "MODULE_KEY";
75   static final String REPORT_DIR_KEY_1 = "src/main/java/dir1";
76   static final String REPORT_FILE_KEY_1 = "src/main/java/dir1/File1.java";
77   static final String REPORT_DIR_KEY_2 = "src/main/java/dir2";
78   static final String REPORT_FILE_KEY_2 = "src/main/java/dir2/File2.java";
79
80   static final long ANALYSIS_DATE = 123456789L;
81
82   @Rule
83   public DbTester dbTester = DbTester.create(System2.INSTANCE);
84
85   @Rule
86   public BatchReportReaderRule reportReader = new BatchReportReaderRule();
87
88   @Rule
89   public MutableTreeRootHolderRule treeRootHolder = new MutableTreeRootHolderRule();
90
91   @Rule
92   public MutableAnalysisMetadataHolderRule analysisMetadataHolder = new MutableAnalysisMetadataHolderRule()
93     .setRootComponentRef(ROOT_REF)
94     .setAnalysisDate(ANALYSIS_DATE)
95     .setBranch(null);
96
97   DbClient dbClient = dbTester.getDbClient();
98
99   BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder);
100
101   @Test(expected = NullPointerException.class)
102   public void fails_if_root_component_does_not_exist_in_reportReader() {
103     underTest.execute();
104   }
105
106   @DataProvider
107   public static Object[][] allComponentTypes() {
108     Object[][] res = new Object[ComponentType.values().length - 2][1];
109     int i = 0;
110     for (ComponentType componentType : from(asList(ComponentType.values())).filter(not(in(asList(UNSET, UNRECOGNIZED))))) {
111       res[i][0] = componentType;
112       i++;
113     }
114     return res;
115   }
116
117   @Test
118   @UseDataProvider("allComponentTypes")
119   public void verify_ref_and_type(ComponentType componentType) {
120     int componentRef = 1;
121     reportReader.putComponent(component(componentRef, componentType));
122
123     underTest.execute();
124
125     Component root = treeRootHolder.getRoot();
126     assertThat(root).isNotNull();
127     assertThat(root.getType()).isEqualTo(Component.Type.valueOf(componentType.name()));
128     assertThat(root.getReportAttributes().getRef()).isEqualTo(ROOT_REF);
129     assertThat(root.getChildren()).isEmpty();
130   }
131
132   @Test
133   public void verify_tree_is_correctly_built() {
134     reportReader.putComponent(component(ROOT_REF, PROJECT, MODULE_REF));
135     reportReader.putComponent(component(MODULE_REF, MODULE, DIR_REF_1, DIR_REF_2));
136     reportReader.putComponent(component(DIR_REF_1, DIRECTORY, FILE_1_REF, FILE_2_REF));
137     reportReader.putComponent(component(FILE_1_REF, FILE));
138     reportReader.putComponent(component(FILE_2_REF, FILE));
139     reportReader.putComponent(component(DIR_REF_2, DIRECTORY, FILE_3_REF));
140     reportReader.putComponent(component(FILE_3_REF, FILE));
141
142     underTest.execute();
143
144     Component root = treeRootHolder.getRoot();
145     assertThat(root).isNotNull();
146     verifyComponent(root, Component.Type.PROJECT, ROOT_REF, 1);
147     Component module = root.getChildren().iterator().next();
148     verifyComponent(module, Component.Type.MODULE, MODULE_REF, 2);
149     Component dir1 = module.getChildren().get(0);
150     verifyComponent(dir1, Component.Type.DIRECTORY, DIR_REF_1, 2);
151     verifyComponent(dir1.getChildren().get(0), Component.Type.FILE, FILE_1_REF, 0);
152     verifyComponent(dir1.getChildren().get(1), Component.Type.FILE, FILE_2_REF, 0);
153     Component dir2 = module.getChildren().get(1);
154     verifyComponent(dir2, Component.Type.DIRECTORY, DIR_REF_2, 1);
155     verifyComponent(dir2.getChildren().iterator().next(), Component.Type.FILE, FILE_3_REF, 0);
156   }
157
158   @Test
159   public void compute_keys_and_uuids() {
160     reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF));
161     reportReader.putComponent(componentWithKey(MODULE_REF, MODULE, REPORT_MODULE_KEY, DIR_REF_1));
162     reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, REPORT_DIR_KEY_1, FILE_1_REF));
163     reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_KEY_1));
164
165     underTest.execute();
166
167     verifyComponent(ROOT_REF, REPORT_PROJECT_KEY);
168     verifyComponent(MODULE_REF, REPORT_MODULE_KEY);
169     verifyComponent(DIR_REF_1, REPORT_MODULE_KEY + ":" + REPORT_DIR_KEY_1);
170     verifyComponent(FILE_1_REF, REPORT_MODULE_KEY + ":" + REPORT_FILE_KEY_1);
171   }
172
173   @Test
174   public void return_existing_uuids() {
175     ComponentDto project = insertComponent(newProjectDto("ABCD").setKey(REPORT_PROJECT_KEY));
176     ComponentDto module = insertComponent(newModuleDto("BCDE", project).setKey(REPORT_MODULE_KEY));
177     ComponentDto directory = newDirectory(module, "CDEF", REPORT_DIR_KEY_1);
178     insertComponent(directory.setKey(REPORT_MODULE_KEY + ":" + REPORT_DIR_KEY_1));
179     insertComponent(newFileDto(module, directory, "DEFG").setKey(REPORT_MODULE_KEY + ":" + REPORT_FILE_KEY_1));
180
181     reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF));
182     reportReader.putComponent(componentWithKey(MODULE_REF, MODULE, REPORT_MODULE_KEY, DIR_REF_1));
183     reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, REPORT_DIR_KEY_1, FILE_1_REF));
184     reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_KEY_1));
185
186     underTest.execute();
187
188     verifyComponent(ROOT_REF, REPORT_PROJECT_KEY, "ABCD");
189     verifyComponent(MODULE_REF, REPORT_MODULE_KEY, "BCDE");
190     verifyComponent(DIR_REF_1, REPORT_MODULE_KEY + ":" + REPORT_DIR_KEY_1, "CDEF");
191     verifyComponent(FILE_1_REF, REPORT_MODULE_KEY + ":" + REPORT_FILE_KEY_1, "DEFG");
192   }
193
194   @Test
195   public void use_branch_to_generate_keys() {
196     MutableAnalysisMetadataHolder analysisMetadataHolder = new AnalysisMetadataHolderImpl()
197       .setRootComponentRef(ROOT_REF)
198       .setAnalysisDate(ANALYSIS_DATE)
199       .setBranch("origin/master");
200
201     BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder);
202
203     reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF));
204     reportReader.putComponent(componentWithKey(MODULE_REF, MODULE, REPORT_MODULE_KEY, DIR_REF_1));
205     reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, REPORT_DIR_KEY_1, FILE_1_REF));
206     reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_KEY_1));
207
208     underTest.execute();
209
210     verifyComponent(ROOT_REF, REPORT_PROJECT_KEY + ":origin/master");
211     verifyComponent(MODULE_REF, REPORT_MODULE_KEY + ":origin/master");
212     verifyComponent(DIR_REF_1, REPORT_MODULE_KEY + ":origin/master:" + REPORT_DIR_KEY_1);
213     verifyComponent(FILE_1_REF, REPORT_MODULE_KEY + ":origin/master:" + REPORT_FILE_KEY_1);
214   }
215
216   @Test
217   public void compute_keys_and_uuids_on_project_having_module_and_directory() {
218     reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF, DIR_REF_2));
219     reportReader.putComponent(componentWithKey(MODULE_REF, MODULE, REPORT_MODULE_KEY, DIR_REF_1));
220     reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, REPORT_DIR_KEY_1, FILE_1_REF));
221     reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_KEY_1));
222     reportReader.putComponent(componentWithPath(DIR_REF_2, DIRECTORY, REPORT_DIR_KEY_2, FILE_2_REF));
223     reportReader.putComponent(componentWithPath(FILE_2_REF, FILE, REPORT_FILE_KEY_2));
224
225     underTest.execute();
226
227     verifyComponent(ROOT_REF, REPORT_PROJECT_KEY);
228     verifyComponent(MODULE_REF, REPORT_MODULE_KEY);
229     verifyComponent(DIR_REF_1, REPORT_MODULE_KEY + ":" + REPORT_DIR_KEY_1);
230     verifyComponent(FILE_1_REF, REPORT_MODULE_KEY + ":" + REPORT_FILE_KEY_1);
231     verifyComponent(DIR_REF_2, REPORT_PROJECT_KEY + ":" + REPORT_DIR_KEY_2);
232     verifyComponent(FILE_2_REF, REPORT_PROJECT_KEY + ":" + REPORT_FILE_KEY_2);
233   }
234
235   @Test
236   public void compute_keys_and_uuids_on_multi_modules() {
237     reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF));
238     reportReader.putComponent(componentWithKey(MODULE_REF, MODULE, REPORT_MODULE_KEY, 100));
239     reportReader.putComponent(componentWithKey(100, MODULE, "SUB_MODULE_KEY", DIR_REF_1));
240     reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, REPORT_DIR_KEY_1, FILE_1_REF));
241     reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_KEY_1));
242
243     underTest.execute();
244
245     verifyComponent(ROOT_REF, REPORT_PROJECT_KEY);
246     verifyComponent(MODULE_REF, REPORT_MODULE_KEY);
247     verifyComponent(100, "SUB_MODULE_KEY");
248     verifyComponent(DIR_REF_1, "SUB_MODULE_KEY" + ":" + REPORT_DIR_KEY_1);
249     verifyComponent(FILE_1_REF, "SUB_MODULE_KEY" + ":" + REPORT_FILE_KEY_1);
250   }
251
252   @Test
253   public void return_existing_uuids_when_components_were_removed() {
254     ComponentDto project = insertComponent(newProjectDto("ABCD").setKey(REPORT_PROJECT_KEY));
255     ComponentDto removedModule = insertComponent(newModuleDto("BCDE", project).setKey(REPORT_MODULE_KEY).setEnabled(false));
256     ComponentDto removedDirectory = insertComponent(newDirectory(removedModule, "CDEF", REPORT_DIR_KEY_1).setKey(REPORT_MODULE_KEY + ":" + REPORT_DIR_KEY_1).setEnabled(false));
257     insertComponent(newFileDto(removedModule, removedDirectory, "DEFG").setKey(REPORT_MODULE_KEY + ":" + REPORT_FILE_KEY_1).setEnabled(false));
258
259     reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF));
260     reportReader.putComponent(componentWithKey(MODULE_REF, MODULE, REPORT_MODULE_KEY, DIR_REF_1));
261     reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, REPORT_DIR_KEY_1, FILE_1_REF));
262     reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_KEY_1));
263
264     underTest.execute();
265
266     verifyComponent(ROOT_REF, REPORT_PROJECT_KEY, "ABCD");
267
268     // No new UUID is generated on removed components
269     verifyComponent(MODULE_REF, REPORT_MODULE_KEY, "BCDE");
270     verifyComponent(DIR_REF_1, REPORT_MODULE_KEY + ":" + REPORT_DIR_KEY_1, "CDEF");
271     verifyComponent(FILE_1_REF, REPORT_MODULE_KEY + ":" + REPORT_FILE_KEY_1, "DEFG");
272   }
273
274   @Test
275   public void set_no_base_project_snapshot_when_no_snapshot() throws Exception {
276     reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY));
277     underTest.execute();
278
279     assertThat(analysisMetadataHolder.isFirstAnalysis()).isTrue();
280   }
281
282   @Test
283   public void set_no_base_project_snapshot_when_no_last_snapshot() throws Exception {
284     ComponentDto project = insertComponent(newProjectDto("ABCD").setKey(REPORT_PROJECT_KEY));
285     insertSnapshot(newAnalysis(project).setLast(false));
286
287     reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY));
288     underTest.execute();
289
290     assertThat(analysisMetadataHolder.isFirstAnalysis()).isTrue();
291   }
292
293   @Test
294   public void set_base_project_snapshot_when_last_snapshot_exist() throws Exception {
295     ComponentDto project = insertComponent(newProjectDto("ABCD").setKey(REPORT_PROJECT_KEY));
296     insertSnapshot(newAnalysis(project).setLast(true));
297
298     reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY));
299     underTest.execute();
300
301     assertThat(analysisMetadataHolder.isFirstAnalysis()).isFalse();
302   }
303
304   private void verifyComponent(Component component, Component.Type type, int componentRef, int size) {
305     assertThat(component.getType()).isEqualTo(type);
306     assertThat(component.getReportAttributes().getRef()).isEqualTo(componentRef);
307     assertThat(component.getChildren()).hasSize(size);
308   }
309
310   private void verifyComponent(int ref, String key) {
311     verifyComponent(ref, key, null);
312   }
313
314   private void verifyComponent(int ref, String key, @Nullable String uuid) {
315     Map<Integer, Component> componentsByRef = indexAllComponentsInTreeByRef(treeRootHolder.getRoot());
316     Component component = componentsByRef.get(ref);
317     assertThat(component.getKey()).isEqualTo(key);
318     if (uuid != null) {
319       assertThat(component.getUuid()).isEqualTo(uuid);
320     } else {
321       assertThat(component.getUuid()).isNotNull();
322     }
323   }
324
325   private static ScannerReport.Component component(int componentRef, ComponentType componentType, int... children) {
326     return component(componentRef, componentType, null, null, children);
327   }
328
329   private static ScannerReport.Component componentWithKey(int componentRef, ComponentType componentType, String key, int... children) {
330     return component(componentRef, componentType, key, null, children);
331   }
332
333   private static ScannerReport.Component componentWithPath(int componentRef, ComponentType componentType, String path, int... children) {
334     return component(componentRef, componentType, null, path, children);
335   }
336
337   private static ScannerReport.Component component(int componentRef, ComponentType componentType, @Nullable String key, @Nullable String path, int... children) {
338     ScannerReport.Component.Builder builder = ScannerReport.Component.newBuilder()
339       .setType(componentType)
340       .setRef(componentRef);
341     if (key != null) {
342       builder.setKey(key);
343     }
344     if (path != null) {
345       builder.setPath(path);
346     }
347     for (int child : children) {
348       builder.addChildRef(child);
349     }
350     return builder.build();
351   }
352
353   private static Map<Integer, Component> indexAllComponentsInTreeByRef(Component root) {
354     Map<Integer, Component> componentsByRef = new HashMap<>();
355     feedComponentByRef(root, componentsByRef);
356     return componentsByRef;
357   }
358
359   private static void feedComponentByRef(Component component, Map<Integer, Component> map) {
360     map.put(component.getReportAttributes().getRef(), component);
361     for (Component child : component.getChildren()) {
362       feedComponentByRef(child, map);
363     }
364   }
365
366   private ComponentDto insertComponent(ComponentDto component) {
367     dbClient.componentDao().insert(dbTester.getSession(), component);
368     dbTester.getSession().commit();
369     return component;
370   }
371
372   private SnapshotDto insertSnapshot(SnapshotDto snapshot) {
373     dbClient.snapshotDao().insert(dbTester.getSession(), snapshot);
374     dbTester.getSession().commit();
375     return snapshot;
376   }
377
378 }