3 * Copyright (C) 2009-2016 SonarSource SA
4 * mailto:contact 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.server.computation.task.projectanalysis.step;
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;
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;
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;
62 @RunWith(DataProviderRunner.class)
63 public class BuildComponentTreeStepTest {
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;
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";
80 static final long ANALYSIS_DATE = 123456789L;
83 public DbTester dbTester = DbTester.create(System2.INSTANCE);
86 public BatchReportReaderRule reportReader = new BatchReportReaderRule();
89 public MutableTreeRootHolderRule treeRootHolder = new MutableTreeRootHolderRule();
92 public MutableAnalysisMetadataHolderRule analysisMetadataHolder = new MutableAnalysisMetadataHolderRule()
93 .setRootComponentRef(ROOT_REF)
94 .setAnalysisDate(ANALYSIS_DATE)
97 DbClient dbClient = dbTester.getDbClient();
99 BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder);
101 @Test(expected = NullPointerException.class)
102 public void fails_if_root_component_does_not_exist_in_reportReader() {
107 public static Object[][] allComponentTypes() {
108 Object[][] res = new Object[ComponentType.values().length - 2][1];
110 for (ComponentType componentType : from(asList(ComponentType.values())).filter(not(in(asList(UNSET, UNRECOGNIZED))))) {
111 res[i][0] = componentType;
118 @UseDataProvider("allComponentTypes")
119 public void verify_ref_and_type(ComponentType componentType) {
120 int componentRef = 1;
121 reportReader.putComponent(component(componentRef, componentType));
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();
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));
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);
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));
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);
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));
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));
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");
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");
201 BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder);
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));
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);
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));
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);
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));
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);
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));
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));
266 verifyComponent(ROOT_REF, REPORT_PROJECT_KEY, "ABCD");
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");
275 public void set_no_base_project_snapshot_when_no_snapshot() throws Exception {
276 reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY));
279 assertThat(analysisMetadataHolder.isFirstAnalysis()).isTrue();
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));
287 reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY));
290 assertThat(analysisMetadataHolder.isFirstAnalysis()).isTrue();
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));
298 reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY));
301 assertThat(analysisMetadataHolder.isFirstAnalysis()).isFalse();
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);
310 private void verifyComponent(int ref, String key) {
311 verifyComponent(ref, key, null);
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);
319 assertThat(component.getUuid()).isEqualTo(uuid);
321 assertThat(component.getUuid()).isNotNull();
325 private static ScannerReport.Component component(int componentRef, ComponentType componentType, int... children) {
326 return component(componentRef, componentType, null, null, children);
329 private static ScannerReport.Component componentWithKey(int componentRef, ComponentType componentType, String key, int... children) {
330 return component(componentRef, componentType, key, null, children);
333 private static ScannerReport.Component componentWithPath(int componentRef, ComponentType componentType, String path, int... children) {
334 return component(componentRef, componentType, null, path, children);
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);
345 builder.setPath(path);
347 for (int child : children) {
348 builder.addChildRef(child);
350 return builder.build();
353 private static Map<Integer, Component> indexAllComponentsInTreeByRef(Component root) {
354 Map<Integer, Component> componentsByRef = new HashMap<>();
355 feedComponentByRef(root, componentsByRef);
356 return componentsByRef;
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);
366 private ComponentDto insertComponent(ComponentDto component) {
367 dbClient.componentDao().insert(dbTester.getSession(), component);
368 dbTester.getSession().commit();
372 private SnapshotDto insertSnapshot(SnapshotDto snapshot) {
373 dbClient.snapshotDao().insert(dbTester.getSession(), snapshot);
374 dbTester.getSession().commit();