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