]> source.dussan.org Git - sonarqube.git/blob
11ad345a60890f50ef2f952200208985d376d6f2
[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 java.util.Optional;
28 import javax.annotation.Nullable;
29 import org.junit.Rule;
30 import org.junit.Test;
31 import org.junit.runner.RunWith;
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.SnapshotDto;
37 import org.sonar.db.organization.OrganizationDto;
38 import org.sonar.scanner.protocol.output.ScannerReport;
39 import org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType;
40 import org.sonar.scanner.protocol.output.ScannerReport.Component.FileStatus;
41 import org.sonar.server.computation.task.projectanalysis.analysis.Branch;
42 import org.sonar.server.computation.task.projectanalysis.analysis.MutableAnalysisMetadataHolderRule;
43 import org.sonar.server.computation.task.projectanalysis.analysis.Project;
44 import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReaderRule;
45 import org.sonar.server.computation.task.projectanalysis.component.Component;
46 import org.sonar.server.computation.task.projectanalysis.component.DefaultBranchImpl;
47 import org.sonar.server.computation.task.projectanalysis.component.MutableTreeRootHolderRule;
48
49 import static com.google.common.base.Predicates.in;
50 import static com.google.common.base.Predicates.not;
51 import static com.google.common.collect.FluentIterable.from;
52 import static java.util.Arrays.asList;
53 import static org.assertj.core.api.Assertions.assertThat;
54 import static org.mockito.Matchers.any;
55 import static org.mockito.Mockito.mock;
56 import static org.mockito.Mockito.when;
57 import static org.sonar.db.component.ComponentTesting.newDirectory;
58 import static org.sonar.db.component.ComponentTesting.newFileDto;
59 import static org.sonar.db.component.ComponentTesting.newModuleDto;
60 import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto;
61 import static org.sonar.db.component.SnapshotTesting.newAnalysis;
62 import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.DIRECTORY;
63 import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.FILE;
64 import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.MODULE;
65 import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.PROJECT;
66 import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.UNRECOGNIZED;
67 import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.UNSET;
68
69 @RunWith(DataProviderRunner.class)
70 public class BuildComponentTreeStepTest {
71
72   static final int ROOT_REF = 1;
73   static final int MODULE_REF = 2;
74   static final int DIR_REF_1 = 3;
75   static final int FILE_1_REF = 4;
76   static final int FILE_2_REF = 5;
77   static final int DIR_REF_2 = 6;
78   static final int FILE_3_REF = 7;
79
80   static final String REPORT_PROJECT_KEY = "REPORT_PROJECT_KEY";
81   static final String REPORT_MODULE_KEY = "MODULE_KEY";
82   static final String REPORT_DIR_KEY_1 = "src/main/java/dir1";
83   static final String REPORT_FILE_KEY_1 = "src/main/java/dir1/File1.java";
84   static final String REPORT_DIR_KEY_2 = "src/main/java/dir2";
85   static final String REPORT_FILE_KEY_2 = "src/main/java/dir2/File2.java";
86
87   static final long ANALYSIS_DATE = 123456789L;
88
89   @Rule
90   public DbTester dbTester = DbTester.create(System2.INSTANCE);
91   @Rule
92   public BatchReportReaderRule reportReader = new BatchReportReaderRule()
93     .setMetadata(ScannerReport.Metadata.newBuilder()
94       .setProjectKey(REPORT_PROJECT_KEY)
95       .setRootComponentRef(ROOT_REF)
96       .build());
97   @Rule
98   public MutableTreeRootHolderRule treeRootHolder = new MutableTreeRootHolderRule();
99   @Rule
100   public MutableAnalysisMetadataHolderRule analysisMetadataHolder = new MutableAnalysisMetadataHolderRule();
101
102   private DbClient dbClient = dbTester.getDbClient();
103   private BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder);
104
105   @Test(expected = NullPointerException.class)
106   public void fails_if_root_component_does_not_exist_in_reportReader() {
107     setAnalysisMetadataHolder();
108
109     underTest.execute();
110   }
111
112   @DataProvider
113   public static Object[][] allComponentTypes() {
114     Object[][] res = new Object[ComponentType.values().length - 2][1];
115     int i = 0;
116     for (ComponentType componentType : from(asList(ComponentType.values())).filter(not(in(asList(UNSET, UNRECOGNIZED))))) {
117       res[i][0] = componentType;
118       i++;
119     }
120     return res;
121   }
122
123   @Test
124   @UseDataProvider("allComponentTypes")
125   public void verify_ref_and_type(ComponentType componentType) {
126     setAnalysisMetadataHolder();
127     int componentRef = 1;
128     reportReader.putComponent(component(componentRef, componentType));
129
130     underTest.execute();
131
132     Component root = treeRootHolder.getRoot();
133     assertThat(root).isNotNull();
134     assertThat(root.getType()).isEqualTo(Component.Type.valueOf(componentType.name()));
135     assertThat(root.getReportAttributes().getRef()).isEqualTo(ROOT_REF);
136     assertThat(root.getChildren()).isEmpty();
137   }
138
139   @Test
140   public void verify_tree_is_correctly_built() {
141     setAnalysisMetadataHolder();
142     reportReader.putComponent(component(ROOT_REF, PROJECT, MODULE_REF));
143     reportReader.putComponent(component(MODULE_REF, MODULE, DIR_REF_1, DIR_REF_2));
144     reportReader.putComponent(component(DIR_REF_1, DIRECTORY, FILE_1_REF, FILE_2_REF));
145     reportReader.putComponent(component(FILE_1_REF, FILE));
146     reportReader.putComponent(component(FILE_2_REF, FILE));
147     reportReader.putComponent(component(DIR_REF_2, DIRECTORY, FILE_3_REF));
148     reportReader.putComponent(component(FILE_3_REF, FILE));
149
150     underTest.execute();
151
152     Component root = treeRootHolder.getRoot();
153     assertThat(root).isNotNull();
154     verifyComponent(root, Component.Type.PROJECT, ROOT_REF, 1);
155     Component module = root.getChildren().iterator().next();
156     verifyComponent(module, Component.Type.MODULE, MODULE_REF, 2);
157     Component dir1 = module.getChildren().get(0);
158     verifyComponent(dir1, Component.Type.DIRECTORY, DIR_REF_1, 2);
159     verifyComponent(dir1.getChildren().get(0), Component.Type.FILE, FILE_1_REF, 0);
160     verifyComponent(dir1.getChildren().get(1), Component.Type.FILE, FILE_2_REF, 0);
161     Component dir2 = module.getChildren().get(1);
162     verifyComponent(dir2, Component.Type.DIRECTORY, DIR_REF_2, 1);
163     verifyComponent(dir2.getChildren().iterator().next(), Component.Type.FILE, FILE_3_REF, 0);
164   }
165
166   @Test
167   public void compute_keys_and_uuids() {
168     setAnalysisMetadataHolder();
169     reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF));
170     reportReader.putComponent(componentWithKey(MODULE_REF, MODULE, REPORT_MODULE_KEY, DIR_REF_1));
171     reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, REPORT_DIR_KEY_1, FILE_1_REF));
172     reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_KEY_1));
173
174     underTest.execute();
175
176     verifyComponent(ROOT_REF, REPORT_PROJECT_KEY);
177     verifyComponent(MODULE_REF, REPORT_MODULE_KEY);
178     verifyComponent(DIR_REF_1, REPORT_MODULE_KEY + ":" + REPORT_DIR_KEY_1);
179     verifyComponent(FILE_1_REF, REPORT_MODULE_KEY + ":" + REPORT_FILE_KEY_1);
180   }
181
182   @Test
183   public void return_existing_uuids() {
184     setAnalysisMetadataHolder();
185     OrganizationDto organizationDto = dbTester.organizations().insert();
186     ComponentDto project = insertComponent(newPrivateProjectDto(organizationDto, "ABCD").setDbKey(REPORT_PROJECT_KEY));
187     ComponentDto module = insertComponent(newModuleDto("BCDE", project).setDbKey(REPORT_MODULE_KEY));
188     ComponentDto directory = newDirectory(module, "CDEF", REPORT_DIR_KEY_1);
189     insertComponent(directory.setDbKey(REPORT_MODULE_KEY + ":" + REPORT_DIR_KEY_1));
190     insertComponent(newFileDto(module, directory, "DEFG").setDbKey(REPORT_MODULE_KEY + ":" + REPORT_FILE_KEY_1));
191
192     reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF));
193     reportReader.putComponent(componentWithKey(MODULE_REF, MODULE, REPORT_MODULE_KEY, DIR_REF_1));
194     reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, REPORT_DIR_KEY_1, FILE_1_REF));
195     reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_KEY_1));
196
197     underTest.execute();
198
199     verifyComponent(ROOT_REF, REPORT_PROJECT_KEY, "ABCD");
200     verifyComponent(MODULE_REF, REPORT_MODULE_KEY, "BCDE");
201     verifyComponent(DIR_REF_1, REPORT_MODULE_KEY + ":" + REPORT_DIR_KEY_1, "CDEF");
202     verifyComponent(FILE_1_REF, REPORT_MODULE_KEY + ":" + REPORT_FILE_KEY_1, "DEFG");
203   }
204
205   @Test
206   public void generate_keys_when_using_branch() {
207     Branch branch = mock(Branch.class);
208     when(branch.getName()).thenReturn("origin/feature");
209     when(branch.isMain()).thenReturn(false);
210     when(branch.isLegacyFeature()).thenReturn(false);
211     when(branch.generateKey(any(ScannerReport.Component.class), any(ScannerReport.Component.class))).thenReturn("generated");
212     analysisMetadataHolder.setRootComponentRef(ROOT_REF)
213       .setAnalysisDate(ANALYSIS_DATE)
214       .setProject(new Project("U1", REPORT_PROJECT_KEY, REPORT_PROJECT_KEY))
215       .setBranch(branch);
216     BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder);
217     reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF));
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
222     underTest.execute();
223
224     verifyComponent(ROOT_REF, "generated", REPORT_PROJECT_KEY, null);
225     verifyComponent(MODULE_REF, "generated", REPORT_MODULE_KEY, null);
226     verifyComponent(DIR_REF_1, "generated", REPORT_MODULE_KEY + ":" + REPORT_DIR_KEY_1, null);
227     verifyComponent(FILE_1_REF, "generated", REPORT_MODULE_KEY + ":" + REPORT_FILE_KEY_1, null);
228   }
229
230   @Test
231   public void generate_keys_when_using_main_branch() {
232     Branch branch = mock(Branch.class);
233     when(branch.getName()).thenReturn("origin/master");
234     when(branch.isMain()).thenReturn(true);
235     when(branch.isLegacyFeature()).thenReturn(false);
236     when(branch.generateKey(any(ScannerReport.Component.class), any(ScannerReport.Component.class))).thenReturn("generated");
237     analysisMetadataHolder.setRootComponentRef(ROOT_REF)
238       .setAnalysisDate(ANALYSIS_DATE)
239       .setProject(new Project("U1", REPORT_PROJECT_KEY, REPORT_PROJECT_KEY))
240       .setBranch(branch);
241     BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder);
242     reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF));
243     reportReader.putComponent(componentWithKey(MODULE_REF, MODULE, REPORT_MODULE_KEY, DIR_REF_1));
244     reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, REPORT_DIR_KEY_1, FILE_1_REF));
245     reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_KEY_1));
246
247     underTest.execute();
248
249     verifyComponent(ROOT_REF, "generated", REPORT_PROJECT_KEY, null);
250     verifyComponent(MODULE_REF, "generated", REPORT_MODULE_KEY, null);
251     verifyComponent(DIR_REF_1, "generated", REPORT_MODULE_KEY + ":" + REPORT_DIR_KEY_1, null);
252     verifyComponent(FILE_1_REF, "generated", REPORT_MODULE_KEY + ":" + REPORT_FILE_KEY_1, null);
253   }
254
255   @Test
256   public void generate_keys_when_using_legacy_branch() {
257     analysisMetadataHolder.setRootComponentRef(ROOT_REF)
258       .setAnalysisDate(ANALYSIS_DATE)
259       .setProject(new Project("U1", REPORT_PROJECT_KEY, REPORT_PROJECT_KEY))
260       .setBranch(new DefaultBranchImpl("origin/feature"));
261     BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder);
262     reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF));
263     reportReader.putComponent(componentWithKey(MODULE_REF, MODULE, REPORT_MODULE_KEY, DIR_REF_1));
264     reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, REPORT_DIR_KEY_1, FILE_1_REF));
265     reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_KEY_1));
266
267     underTest.execute();
268
269     verifyComponent(ROOT_REF, REPORT_PROJECT_KEY + ":origin/feature", null);
270     verifyComponent(MODULE_REF, REPORT_MODULE_KEY + ":origin/feature", null);
271     verifyComponent(DIR_REF_1, REPORT_MODULE_KEY + ":origin/feature:" + REPORT_DIR_KEY_1, null);
272     verifyComponent(FILE_1_REF, REPORT_MODULE_KEY + ":origin/feature:" + REPORT_FILE_KEY_1, null);
273   }
274
275   @Test
276   public void compute_keys_when_no_branch() {
277     analysisMetadataHolder.setRootComponentRef(ROOT_REF)
278       .setAnalysisDate(ANALYSIS_DATE)
279       .setProject(new Project("U1", REPORT_PROJECT_KEY, REPORT_PROJECT_KEY))
280       .setBranch(null);
281     BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder);
282     reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF));
283     reportReader.putComponent(componentWithKey(MODULE_REF, MODULE, REPORT_MODULE_KEY, DIR_REF_1));
284     reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, REPORT_DIR_KEY_1, FILE_1_REF));
285     reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_KEY_1));
286
287     underTest.execute();
288
289     verifyComponent(ROOT_REF, REPORT_PROJECT_KEY);
290     verifyComponent(MODULE_REF, REPORT_MODULE_KEY);
291     verifyComponent(DIR_REF_1, REPORT_MODULE_KEY + ":" + REPORT_DIR_KEY_1);
292     verifyComponent(FILE_1_REF, REPORT_MODULE_KEY + ":" + REPORT_FILE_KEY_1);
293   }
294
295   @Test
296   public void compute_keys_and_uuids_on_project_having_module_and_directory() {
297     setAnalysisMetadataHolder();
298     reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF, DIR_REF_2));
299     reportReader.putComponent(componentWithKey(MODULE_REF, MODULE, REPORT_MODULE_KEY, DIR_REF_1));
300     reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, REPORT_DIR_KEY_1, FILE_1_REF));
301     reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_KEY_1));
302     reportReader.putComponent(componentWithPath(DIR_REF_2, DIRECTORY, REPORT_DIR_KEY_2, FILE_2_REF));
303     reportReader.putComponent(componentWithPath(FILE_2_REF, FILE, REPORT_FILE_KEY_2));
304
305     underTest.execute();
306
307     verifyComponent(ROOT_REF, REPORT_PROJECT_KEY);
308     verifyComponent(MODULE_REF, REPORT_MODULE_KEY);
309     verifyComponent(DIR_REF_1, REPORT_MODULE_KEY + ":" + REPORT_DIR_KEY_1);
310     verifyComponent(FILE_1_REF, REPORT_MODULE_KEY + ":" + REPORT_FILE_KEY_1);
311     verifyComponent(DIR_REF_2, REPORT_PROJECT_KEY + ":" + REPORT_DIR_KEY_2);
312     verifyComponent(FILE_2_REF, REPORT_PROJECT_KEY + ":" + REPORT_FILE_KEY_2);
313   }
314
315   @Test
316   public void compute_keys_and_uuids_on_multi_modules() {
317     setAnalysisMetadataHolder();
318     reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF));
319     reportReader.putComponent(componentWithKey(MODULE_REF, MODULE, REPORT_MODULE_KEY, 100));
320     reportReader.putComponent(componentWithKey(100, MODULE, "SUB_MODULE_KEY", DIR_REF_1));
321     reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, REPORT_DIR_KEY_1, FILE_1_REF));
322     reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_KEY_1));
323
324     underTest.execute();
325
326     verifyComponent(ROOT_REF, REPORT_PROJECT_KEY);
327     verifyComponent(MODULE_REF, REPORT_MODULE_KEY);
328     verifyComponent(100, "SUB_MODULE_KEY");
329     verifyComponent(DIR_REF_1, "SUB_MODULE_KEY" + ":" + REPORT_DIR_KEY_1);
330     verifyComponent(FILE_1_REF, "SUB_MODULE_KEY" + ":" + REPORT_FILE_KEY_1);
331   }
332
333   @Test
334   public void return_existing_uuids_when_components_were_removed() {
335     setAnalysisMetadataHolder();
336     OrganizationDto organizationDto = dbTester.organizations().insert();
337     ComponentDto project = insertComponent(newPrivateProjectDto(organizationDto, "ABCD").setDbKey(REPORT_PROJECT_KEY));
338     ComponentDto removedModule = insertComponent(newModuleDto("BCDE", project).setDbKey(REPORT_MODULE_KEY).setEnabled(false));
339     ComponentDto removedDirectory = insertComponent(newDirectory(removedModule, "CDEF", REPORT_DIR_KEY_1).setDbKey(REPORT_MODULE_KEY + ":" + REPORT_DIR_KEY_1).setEnabled(false));
340     insertComponent(newFileDto(removedModule, removedDirectory, "DEFG").setDbKey(REPORT_MODULE_KEY + ":" + REPORT_FILE_KEY_1).setEnabled(false));
341
342     reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF));
343     reportReader.putComponent(componentWithKey(MODULE_REF, MODULE, REPORT_MODULE_KEY, DIR_REF_1));
344     reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, REPORT_DIR_KEY_1, FILE_1_REF));
345     reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_KEY_1));
346
347     underTest.execute();
348
349     verifyComponent(ROOT_REF, REPORT_PROJECT_KEY, "ABCD");
350
351     // No new UUID is generated on removed components
352     verifyComponent(MODULE_REF, REPORT_MODULE_KEY, "BCDE");
353     verifyComponent(DIR_REF_1, REPORT_MODULE_KEY + ":" + REPORT_DIR_KEY_1, "CDEF");
354     verifyComponent(FILE_1_REF, REPORT_MODULE_KEY + ":" + REPORT_FILE_KEY_1, "DEFG");
355   }
356
357   @Test
358   public void set_no_base_project_snapshot_when_no_snapshot() throws Exception {
359     setAnalysisMetadataHolder();
360     reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY));
361     underTest.execute();
362
363     assertThat(analysisMetadataHolder.isFirstAnalysis()).isTrue();
364   }
365
366   @Test
367   public void set_no_base_project_snapshot_when_no_last_snapshot() throws Exception {
368     setAnalysisMetadataHolder();
369     OrganizationDto organizationDto = dbTester.organizations().insert();
370     ComponentDto project = insertComponent(newPrivateProjectDto(organizationDto, "ABCD").setDbKey(REPORT_PROJECT_KEY));
371     insertSnapshot(newAnalysis(project).setLast(false));
372
373     reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY));
374     underTest.execute();
375
376     assertThat(analysisMetadataHolder.isFirstAnalysis()).isTrue();
377   }
378
379   @Test
380   public void set_base_project_snapshot_when_last_snapshot_exist() throws Exception {
381     setAnalysisMetadataHolder();
382     OrganizationDto organizationDto = dbTester.organizations().insert();
383     ComponentDto project = insertComponent(newPrivateProjectDto(organizationDto, "ABCD").setDbKey(REPORT_PROJECT_KEY));
384     insertSnapshot(newAnalysis(project).setLast(true));
385
386     reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY));
387     underTest.execute();
388
389     assertThat(analysisMetadataHolder.isFirstAnalysis()).isFalse();
390   }
391
392   private void verifyComponent(Component component, Component.Type type, int componentRef, int size) {
393     assertThat(component.getType()).isEqualTo(type);
394     assertThat(component.getReportAttributes().getRef()).isEqualTo(componentRef);
395     assertThat(component.getChildren()).hasSize(size);
396   }
397
398   private void verifyComponent(int ref, String key) {
399     verifyComponent(ref, key, key, null);
400   }
401
402   private void verifyComponent(int ref, String key, @Nullable String uuid) {
403     verifyComponent(ref, key, key, uuid);
404   }
405
406   private void verifyComponent(int ref, String key, String publicKey, @Nullable String uuid) {
407     Map<Integer, Component> componentsByRef = indexAllComponentsInTreeByRef(treeRootHolder.getRoot());
408     Component component = componentsByRef.get(ref);
409     assertThat(component.getKey()).isEqualTo(key);
410     assertThat(component.getPublicKey()).isEqualTo(publicKey);
411     if (uuid != null) {
412       assertThat(component.getUuid()).isEqualTo(uuid);
413     } else {
414       assertThat(component.getUuid()).isNotNull();
415     }
416   }
417
418   private static ScannerReport.Component component(int componentRef, ComponentType componentType, int... children) {
419     return component(componentRef, componentType, null, null, children);
420   }
421
422   private static ScannerReport.Component componentWithKey(int componentRef, ComponentType componentType, String key, int... children) {
423     return component(componentRef, componentType, key, null, children);
424   }
425
426   private static ScannerReport.Component componentWithPath(int componentRef, ComponentType componentType, String path, int... children) {
427     return component(componentRef, componentType, null, path, children);
428   }
429
430   private static ScannerReport.Component component(int componentRef, ComponentType componentType, @Nullable String key, @Nullable String path, int... children) {
431     ScannerReport.Component.Builder builder = ScannerReport.Component.newBuilder()
432       .setType(componentType)
433       .setRef(componentRef)
434       .setStatus(FileStatus.UNAVAILABLE)
435       .setLines(1);
436     if (key != null) {
437       builder.setKey(key);
438     }
439     if (path != null) {
440       builder.setPath(path);
441     }
442     for (int child : children) {
443       builder.addChildRef(child);
444     }
445     return builder.build();
446   }
447
448   private static Map<Integer, Component> indexAllComponentsInTreeByRef(Component root) {
449     Map<Integer, Component> componentsByRef = new HashMap<>();
450     feedComponentByRef(root, componentsByRef);
451     return componentsByRef;
452   }
453
454   private static void feedComponentByRef(Component component, Map<Integer, Component> map) {
455     map.put(component.getReportAttributes().getRef(), component);
456     for (Component child : component.getChildren()) {
457       feedComponentByRef(child, map);
458     }
459   }
460
461   private ComponentDto insertComponent(ComponentDto component) {
462     dbClient.componentDao().insert(dbTester.getSession(), component);
463     dbTester.getSession().commit();
464     return component;
465   }
466
467   private SnapshotDto insertSnapshot(SnapshotDto snapshot) {
468     dbClient.snapshotDao().insert(dbTester.getSession(), snapshot);
469     dbTester.getSession().commit();
470     return snapshot;
471   }
472
473   private void setAnalysisMetadataHolder() {
474     analysisMetadataHolder.setRootComponentRef(ROOT_REF)
475       .setAnalysisDate(ANALYSIS_DATE)
476       .setBranch(new DefaultBranchImpl(null))
477       .setProject(new Project("U1", REPORT_PROJECT_KEY, REPORT_PROJECT_KEY));
478   }
479
480 }