You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BuildComponentTreeStepIT.java 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2024 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.ce.task.projectanalysis.step;
  21. import com.tngtech.java.junit.dataprovider.DataProvider;
  22. import com.tngtech.java.junit.dataprovider.DataProviderRunner;
  23. import com.tngtech.java.junit.dataprovider.UseDataProvider;
  24. import java.util.HashMap;
  25. import java.util.Map;
  26. import java.util.Optional;
  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.ce.task.projectanalysis.analysis.Branch;
  33. import org.sonar.ce.task.projectanalysis.analysis.MutableAnalysisMetadataHolderRule;
  34. import org.sonar.ce.task.projectanalysis.batch.BatchReportReaderRule;
  35. import org.sonar.ce.task.projectanalysis.component.Component;
  36. import org.sonar.ce.task.projectanalysis.component.DefaultBranchImpl;
  37. import org.sonar.ce.task.projectanalysis.component.MutableTreeRootHolderRule;
  38. import org.sonar.ce.task.step.TestComputationStepContext;
  39. import org.sonar.db.DbClient;
  40. import org.sonar.db.DbTester;
  41. import org.sonar.db.component.BranchType;
  42. import org.sonar.db.component.ComponentDto;
  43. import org.sonar.db.component.SnapshotDto;
  44. import org.sonar.scanner.protocol.output.ScannerReport;
  45. import org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType;
  46. import org.sonar.scanner.protocol.output.ScannerReport.Component.FileStatus;
  47. import org.sonar.server.project.Project;
  48. import static java.util.Optional.ofNullable;
  49. import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
  50. import static org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric;
  51. import static org.assertj.core.api.Assertions.assertThat;
  52. import static org.assertj.core.api.Assertions.assertThatThrownBy;
  53. import static org.mockito.ArgumentMatchers.any;
  54. import static org.mockito.Mockito.mock;
  55. import static org.mockito.Mockito.when;
  56. import static org.sonar.db.component.BranchDto.DEFAULT_MAIN_BRANCH_NAME;
  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.newPrivateProjectDto;
  60. import static org.sonar.db.component.SnapshotTesting.newAnalysis;
  61. import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.FILE;
  62. import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.PROJECT;
  63. @RunWith(DataProviderRunner.class)
  64. public class BuildComponentTreeStepIT {
  65. private static final String NO_SCANNER_PROJECT_VERSION = null;
  66. private static final String NO_SCANNER_BUILD_STRING = null;
  67. private static final int ROOT_REF = 1;
  68. private static final int FILE_1_REF = 4;
  69. private static final int FILE_2_REF = 5;
  70. private static final int FILE_3_REF = 7;
  71. private static final int UNCHANGED_FILE_REF = 10;
  72. private static final String REPORT_PROJECT_KEY = "REPORT_PROJECT_KEY";
  73. private static final String REPORT_DIR_PATH_1 = "src/main/java/dir1";
  74. private static final String REPORT_FILE_PATH_1 = "src/main/java/dir1/File1.java";
  75. private static final String REPORT_FILE_NAME_1 = "File1.java";
  76. private static final String REPORT_DIR_PATH_2 = "src/main/java/dir2";
  77. private static final String REPORT_FILE_PATH_2 = "src/main/java/dir2/File2.java";
  78. private static final String REPORT_FILE_PATH_3 = "src/main/java/dir2/File3.java";
  79. private static final String REPORT_UNCHANGED_FILE_PATH = "src/main/File3.java";
  80. private static final long ANALYSIS_DATE = 123456789L;
  81. @Rule
  82. public DbTester dbTester = DbTester.create(System2.INSTANCE);
  83. @Rule
  84. public BatchReportReaderRule reportReader = new BatchReportReaderRule().setMetadata(createReportMetadata(NO_SCANNER_PROJECT_VERSION, NO_SCANNER_BUILD_STRING));
  85. @Rule
  86. public MutableTreeRootHolderRule treeRootHolder = new MutableTreeRootHolderRule();
  87. @Rule
  88. public MutableAnalysisMetadataHolderRule analysisMetadataHolder = new MutableAnalysisMetadataHolderRule();
  89. private DbClient dbClient = dbTester.getDbClient();
  90. private BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder);
  91. @Test
  92. public void fails_if_root_component_does_not_exist_in_reportReader() {
  93. setAnalysisMetadataHolder();
  94. assertThatThrownBy(() -> underTest.execute(new TestComputationStepContext()))
  95. .isInstanceOf(NullPointerException.class);
  96. }
  97. @Test
  98. public void verify_tree_is_correctly_built() {
  99. setAnalysisMetadataHolder();
  100. reportReader.putComponent(component(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, FILE_1_REF, FILE_2_REF, FILE_3_REF));
  101. reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_PATH_1));
  102. reportReader.putComponent(componentWithPath(FILE_2_REF, FILE, REPORT_FILE_PATH_2));
  103. reportReader.putComponent(componentWithPath(FILE_3_REF, FILE, REPORT_FILE_PATH_3));
  104. TestComputationStepContext context = new TestComputationStepContext();
  105. underTest.execute(context);
  106. Component root = treeRootHolder.getRoot();
  107. assertThat(root).isNotNull();
  108. verifyComponent(root, Component.Type.PROJECT, ROOT_REF, 1);
  109. Component dir = root.getChildren().iterator().next();
  110. verifyComponent(dir, Component.Type.DIRECTORY, null, 2);
  111. Component dir1 = dir.getChildren().get(0);
  112. verifyComponent(dir1, Component.Type.DIRECTORY, null, 1);
  113. verifyComponent(dir1.getChildren().get(0), Component.Type.FILE, FILE_1_REF, 0);
  114. Component dir2 = dir.getChildren().get(1);
  115. verifyComponent(dir2, Component.Type.DIRECTORY, null, 2);
  116. verifyComponent(dir2.getChildren().get(0), Component.Type.FILE, FILE_2_REF, 0);
  117. verifyComponent(dir2.getChildren().get(1), Component.Type.FILE, FILE_3_REF, 0);
  118. context.getStatistics().assertValue("components", 7);
  119. }
  120. @Test
  121. public void verify_tree_is_correctly_built_in_prs() {
  122. setAnalysisMetadataHolder(true);
  123. reportReader.putComponent(component(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, FILE_1_REF, FILE_2_REF, FILE_3_REF, UNCHANGED_FILE_REF));
  124. reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_PATH_1));
  125. reportReader.putComponent(componentWithPath(FILE_2_REF, FILE, REPORT_FILE_PATH_2));
  126. reportReader.putComponent(componentWithPath(FILE_3_REF, FILE, REPORT_FILE_PATH_3));
  127. reportReader.putComponent(unchangedComponentWithPath(UNCHANGED_FILE_REF, FILE, REPORT_UNCHANGED_FILE_PATH));
  128. TestComputationStepContext context = new TestComputationStepContext();
  129. underTest.execute(context);
  130. // modified root
  131. Component mRoot = treeRootHolder.getRoot();
  132. verifyComponent(mRoot, Component.Type.PROJECT, ROOT_REF, 1);
  133. Component mDir = mRoot.getChildren().get(0);
  134. assertThat(mDir.getName()).isEqualTo("src/main/java");
  135. verifyComponent(mDir, Component.Type.DIRECTORY, null, 2);
  136. Component mDir1 = mDir.getChildren().get(0);
  137. assertThat(mDir1.getName()).isEqualTo("src/main/java/dir1");
  138. verifyComponent(mDir1, Component.Type.DIRECTORY, null, 1);
  139. verifyComponent(mDir1.getChildren().get(0), Component.Type.FILE, FILE_1_REF, 0);
  140. Component mDir2 = mDir.getChildren().get(1);
  141. assertThat(mDir2.getName()).isEqualTo("src/main/java/dir2");
  142. verifyComponent(mDir2, Component.Type.DIRECTORY, null, 2);
  143. verifyComponent(mDir2.getChildren().get(0), Component.Type.FILE, FILE_2_REF, 0);
  144. verifyComponent(mDir2.getChildren().get(1), Component.Type.FILE, FILE_3_REF, 0);
  145. // root
  146. Component root = treeRootHolder.getReportTreeRoot();
  147. verifyComponent(root, Component.Type.PROJECT, ROOT_REF, 1);
  148. Component dir = root.getChildren().get(0);
  149. assertThat(dir.getName()).isEqualTo("src/main");
  150. verifyComponent(dir, Component.Type.DIRECTORY, null, 2);
  151. Component dir1 = dir.getChildren().get(0);
  152. assertThat(dir1.getName()).isEqualTo("src/main/java");
  153. verifyComponent(dir1, Component.Type.DIRECTORY, null, 2);
  154. verifyComponent(dir1.getChildren().get(0), Component.Type.DIRECTORY, null, 1);
  155. verifyComponent(dir1.getChildren().get(1), Component.Type.DIRECTORY, null, 2);
  156. Component dir2 = dir1.getChildren().get(0);
  157. assertThat(dir2.getName()).isEqualTo("src/main/java/dir1");
  158. verifyComponent(dir2, Component.Type.DIRECTORY, null, 1);
  159. verifyComponent(dir2.getChildren().get(0), Component.Type.FILE, FILE_1_REF, 0);
  160. Component dir3 = dir1.getChildren().get(1);
  161. assertThat(dir3.getName()).isEqualTo("src/main/java/dir2");
  162. verifyComponent(dir3, Component.Type.DIRECTORY, null, 2);
  163. verifyComponent(dir3.getChildren().get(0), Component.Type.FILE, FILE_2_REF, 0);
  164. verifyComponent(dir3.getChildren().get(1), Component.Type.FILE, FILE_3_REF, 0);
  165. context.getStatistics().assertValue("components", 7);
  166. }
  167. /**
  168. * SONAR-13262
  169. */
  170. @Test
  171. public void verify_tree_is_correctly_built_in_prs_with_repeated_names() {
  172. setAnalysisMetadataHolder(true);
  173. reportReader.putComponent(component(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, FILE_1_REF));
  174. reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_PROJECT_KEY + "/file.js"));
  175. TestComputationStepContext context = new TestComputationStepContext();
  176. underTest.execute(context);
  177. // modified root
  178. Component mRoot = treeRootHolder.getRoot();
  179. verifyComponent(mRoot, Component.Type.PROJECT, ROOT_REF, 1);
  180. Component dir = mRoot.getChildren().get(0);
  181. assertThat(dir.getName()).isEqualTo(REPORT_PROJECT_KEY);
  182. assertThat(dir.getShortName()).isEqualTo(REPORT_PROJECT_KEY);
  183. verifyComponent(dir, Component.Type.DIRECTORY, null, 1);
  184. }
  185. @Test
  186. public void compute_keys_and_uuids() {
  187. setAnalysisMetadataHolder();
  188. reportReader.putComponent(component(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, FILE_1_REF));
  189. reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_PATH_1));
  190. underTest.execute(new TestComputationStepContext());
  191. verifyComponentByRef(ROOT_REF, REPORT_PROJECT_KEY, analysisMetadataHolder.getProject().getName());
  192. verifyComponentByKey(REPORT_PROJECT_KEY + ":" + REPORT_DIR_PATH_1, REPORT_DIR_PATH_1);
  193. verifyComponentByRef(FILE_1_REF, REPORT_PROJECT_KEY + ":" + REPORT_FILE_PATH_1, REPORT_FILE_NAME_1);
  194. }
  195. @Test
  196. public void return_existing_uuids() {
  197. setAnalysisMetadataHolder();
  198. ComponentDto mainBranch = dbTester.components().insertPrivateProject("ABCD", p -> p.setKey(REPORT_PROJECT_KEY)).getMainBranchComponent();
  199. ComponentDto directory = newDirectory(mainBranch, "CDEF", REPORT_DIR_PATH_1);
  200. insertComponent(directory.setKey(REPORT_PROJECT_KEY + ":" + REPORT_DIR_PATH_1));
  201. insertComponent(newFileDto(mainBranch, directory, "DEFG")
  202. .setKey(REPORT_PROJECT_KEY + ":" + REPORT_FILE_PATH_1)
  203. .setPath(REPORT_FILE_PATH_1));
  204. // new structure, without modules
  205. reportReader.putComponent(component(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, FILE_1_REF));
  206. reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_PATH_1));
  207. underTest.execute(new TestComputationStepContext());
  208. verifyComponentByRef(ROOT_REF, REPORT_PROJECT_KEY, analysisMetadataHolder.getProject().getName(), mainBranch.uuid());
  209. verifyComponentByKey(REPORT_PROJECT_KEY + ":" + REPORT_DIR_PATH_1, REPORT_DIR_PATH_1, "CDEF");
  210. verifyComponentByRef(FILE_1_REF, REPORT_PROJECT_KEY + ":" + REPORT_FILE_PATH_1, REPORT_FILE_NAME_1, "DEFG");
  211. }
  212. @Test
  213. public void generate_keys_when_using_new_branch() {
  214. Branch branch = mock(Branch.class);
  215. when(branch.getName()).thenReturn("origin/feature");
  216. when(branch.isMain()).thenReturn(false);
  217. when(branch.generateKey(any(), any())).thenReturn("generated");
  218. analysisMetadataHolder.setRootComponentRef(ROOT_REF)
  219. .setAnalysisDate(ANALYSIS_DATE)
  220. .setProject(Project.from(newPrivateProjectDto().setKey(REPORT_PROJECT_KEY)))
  221. .setBranch(branch);
  222. BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder);
  223. reportReader.putComponent(component(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, FILE_1_REF));
  224. reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_PATH_1));
  225. underTest.execute(new TestComputationStepContext());
  226. verifyComponentByRef(ROOT_REF, "generated", analysisMetadataHolder.getProject().getName(), null);
  227. verifyComponentByRef(FILE_1_REF, "generated", REPORT_FILE_NAME_1, null);
  228. }
  229. @Test
  230. public void generate_keys_when_using_existing_branch() {
  231. ComponentDto projectDto = dbTester.components().insertPublicProject().getMainBranchComponent();
  232. String branchName = randomAlphanumeric(248);
  233. ComponentDto componentDto = dbTester.components().insertProjectBranch(projectDto, b -> b.setKey(branchName));
  234. Branch branch = mock(Branch.class);
  235. when(branch.getName()).thenReturn(branchName);
  236. when(branch.isMain()).thenReturn(false);
  237. when(branch.generateKey(any(), any())).thenReturn(componentDto.getKey());
  238. analysisMetadataHolder.setRootComponentRef(ROOT_REF)
  239. .setAnalysisDate(ANALYSIS_DATE)
  240. .setProject(Project.from(projectDto))
  241. .setBranch(branch);
  242. BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder);
  243. reportReader.putComponent(component(ROOT_REF, PROJECT, componentDto.getKey()));
  244. underTest.execute(new TestComputationStepContext());
  245. verifyComponentByRef(ROOT_REF, componentDto.getKey(), analysisMetadataHolder.getProject().getName(), componentDto.uuid());
  246. }
  247. @Test
  248. public void generate_keys_when_using_main_branch() {
  249. setAnalysisMetadataHolder();
  250. BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder);
  251. reportReader.putComponent(component(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, FILE_1_REF));
  252. reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_PATH_1));
  253. underTest.execute(new TestComputationStepContext());
  254. verifyComponentByRef(ROOT_REF, REPORT_PROJECT_KEY, analysisMetadataHolder.getProject().getName(), null);
  255. verifyComponentByKey(REPORT_PROJECT_KEY + ":" + REPORT_DIR_PATH_1, REPORT_DIR_PATH_1);
  256. verifyComponentByRef(FILE_1_REF, REPORT_PROJECT_KEY + ":" + REPORT_FILE_PATH_1, REPORT_FILE_NAME_1, null);
  257. }
  258. @Test
  259. public void compute_keys_and_uuids_on_project_having_module_and_directory() {
  260. setAnalysisMetadataHolder();
  261. reportReader.putComponent(component(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, FILE_1_REF, FILE_2_REF));
  262. reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_PATH_1));
  263. reportReader.putComponent(componentWithPath(FILE_2_REF, FILE, REPORT_FILE_PATH_2));
  264. underTest.execute(new TestComputationStepContext());
  265. verifyComponentByRef(ROOT_REF, REPORT_PROJECT_KEY, analysisMetadataHolder.getProject().getName());
  266. verifyComponentByKey(REPORT_PROJECT_KEY + ":" + REPORT_DIR_PATH_1, "dir1");
  267. verifyComponentByRef(FILE_1_REF, REPORT_PROJECT_KEY + ":" + REPORT_FILE_PATH_1, REPORT_FILE_NAME_1);
  268. verifyComponentByKey(REPORT_PROJECT_KEY + ":" + REPORT_DIR_PATH_2, "dir2");
  269. verifyComponentByRef(FILE_2_REF, REPORT_PROJECT_KEY + ":" + REPORT_FILE_PATH_2, "File2.java");
  270. }
  271. @Test
  272. public void compute_keys_and_uuids_on_multi_modules() {
  273. setAnalysisMetadataHolder();
  274. reportReader.putComponent(component(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, FILE_1_REF));
  275. reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_PATH_1));
  276. underTest.execute(new TestComputationStepContext());
  277. verifyComponentByRef(ROOT_REF, REPORT_PROJECT_KEY, analysisMetadataHolder.getProject().getName());
  278. verifyComponentByKey(REPORT_PROJECT_KEY + ":" + REPORT_DIR_PATH_1, REPORT_DIR_PATH_1);
  279. verifyComponentByRef(FILE_1_REF, REPORT_PROJECT_KEY + ":" + REPORT_FILE_PATH_1, REPORT_FILE_NAME_1);
  280. }
  281. @Test
  282. public void set_no_base_project_snapshot_when_no_snapshot() {
  283. setAnalysisMetadataHolder();
  284. reportReader.putComponent(component(ROOT_REF, PROJECT, REPORT_PROJECT_KEY));
  285. underTest.execute(new TestComputationStepContext());
  286. assertThat(analysisMetadataHolder.isFirstAnalysis()).isTrue();
  287. }
  288. @Test
  289. public void set_no_base_project_snapshot_when_no_last_snapshot() {
  290. setAnalysisMetadataHolder();
  291. ComponentDto project = insertComponent(newPrivateProjectDto("ABCD").setKey(REPORT_PROJECT_KEY));
  292. insertSnapshot(newAnalysis(project).setLast(false));
  293. reportReader.putComponent(component(ROOT_REF, PROJECT, REPORT_PROJECT_KEY));
  294. underTest.execute(new TestComputationStepContext());
  295. assertThat(analysisMetadataHolder.isFirstAnalysis()).isTrue();
  296. }
  297. @Test
  298. public void set_base_project_snapshot_when_last_snapshot_exist() {
  299. setAnalysisMetadataHolder();
  300. ComponentDto project = dbTester.components().insertPrivateProject("ABCD", p -> p.setKey(REPORT_PROJECT_KEY)).getMainBranchComponent();
  301. insertSnapshot(newAnalysis(project).setLast(true));
  302. reportReader.putComponent(component(ROOT_REF, PROJECT, REPORT_PROJECT_KEY));
  303. underTest.execute(new TestComputationStepContext());
  304. assertThat(analysisMetadataHolder.isFirstAnalysis()).isFalse();
  305. }
  306. @Test
  307. public void set_projectVersion_to_not_provided_when_not_set_on_first_analysis() {
  308. setAnalysisMetadataHolder();
  309. reportReader.putComponent(component(ROOT_REF, PROJECT, REPORT_PROJECT_KEY));
  310. underTest.execute(new TestComputationStepContext());
  311. assertThat(treeRootHolder.getReportTreeRoot().getProjectAttributes().getProjectVersion()).isEqualTo("not provided");
  312. }
  313. @Test
  314. @UseDataProvider("oneParameterNullNonNullCombinations")
  315. public void set_projectVersion_to_previous_analysis_when_not_set(@Nullable String previousAnalysisProjectVersion) {
  316. setAnalysisMetadataHolder();
  317. ComponentDto project = dbTester.components().insertPrivateProject("ABCD", p -> p.setKey(REPORT_PROJECT_KEY)).getMainBranchComponent();
  318. insertSnapshot(newAnalysis(project).setProjectVersion(previousAnalysisProjectVersion).setLast(true));
  319. reportReader.putComponent(component(ROOT_REF, PROJECT, REPORT_PROJECT_KEY));
  320. underTest.execute(new TestComputationStepContext());
  321. String projectVersion = treeRootHolder.getReportTreeRoot().getProjectAttributes().getProjectVersion();
  322. if (previousAnalysisProjectVersion == null) {
  323. assertThat(projectVersion).isEqualTo("not provided");
  324. } else {
  325. assertThat(projectVersion).isEqualTo(previousAnalysisProjectVersion);
  326. }
  327. }
  328. @Test
  329. public void set_projectVersion_when_it_is_set_on_first_analysis() {
  330. String scannerProjectVersion = randomAlphabetic(12);
  331. setAnalysisMetadataHolder();
  332. reportReader.setMetadata(createReportMetadata(scannerProjectVersion, NO_SCANNER_BUILD_STRING));
  333. reportReader.putComponent(component(ROOT_REF, PROJECT, REPORT_PROJECT_KEY));
  334. underTest.execute(new TestComputationStepContext());
  335. assertThat(treeRootHolder.getReportTreeRoot().getProjectAttributes().getProjectVersion())
  336. .isEqualTo(scannerProjectVersion);
  337. }
  338. @Test
  339. @UseDataProvider("oneParameterNullNonNullCombinations")
  340. public void set_projectVersion_when_it_is_set_on_later_analysis(@Nullable String previousAnalysisProjectVersion) {
  341. String scannerProjectVersion = randomAlphabetic(12);
  342. setAnalysisMetadataHolder();
  343. reportReader.setMetadata(createReportMetadata(scannerProjectVersion, NO_SCANNER_BUILD_STRING));
  344. ComponentDto project = insertComponent(newPrivateProjectDto("ABCD").setKey(REPORT_PROJECT_KEY));
  345. insertSnapshot(newAnalysis(project).setProjectVersion(previousAnalysisProjectVersion).setLast(true));
  346. reportReader.putComponent(component(ROOT_REF, PROJECT, REPORT_PROJECT_KEY));
  347. underTest.execute(new TestComputationStepContext());
  348. assertThat(treeRootHolder.getReportTreeRoot().getProjectAttributes().getProjectVersion())
  349. .isEqualTo(scannerProjectVersion);
  350. }
  351. @Test
  352. @UseDataProvider("oneParameterNullNonNullCombinations")
  353. public void set_buildString(@Nullable String buildString) {
  354. String projectVersion = randomAlphabetic(7);
  355. setAnalysisMetadataHolder();
  356. reportReader.setMetadata(createReportMetadata(projectVersion, buildString));
  357. reportReader.putComponent(component(ROOT_REF, PROJECT, REPORT_PROJECT_KEY));
  358. underTest.execute(new TestComputationStepContext());
  359. assertThat(treeRootHolder.getReportTreeRoot().getProjectAttributes().getBuildString()).isEqualTo(Optional.ofNullable(buildString));
  360. }
  361. @DataProvider
  362. public static Object[][] oneParameterNullNonNullCombinations() {
  363. return new Object[][] {
  364. {null},
  365. {randomAlphabetic(7)}
  366. };
  367. }
  368. private void verifyComponent(Component component, Component.Type type, @Nullable Integer componentRef, int size) {
  369. assertThat(component.getType()).isEqualTo(type);
  370. assertThat(component.getReportAttributes().getRef()).isEqualTo(componentRef);
  371. assertThat(component.getChildren()).hasSize(size);
  372. }
  373. private void verifyComponentByRef(int ref, String key, String shortName) {
  374. verifyComponentByRef(ref, key, shortName, null);
  375. }
  376. private void verifyComponentByKey(String key, String shortName) {
  377. verifyComponentByKey(key, shortName, null);
  378. }
  379. private void verifyComponentByKey(String key, String shortName, @Nullable String uuid) {
  380. Map<String, Component> componentsByKey = indexAllComponentsInTreeByKey(treeRootHolder.getRoot());
  381. Component component = componentsByKey.get(key);
  382. assertThat(component.getKey()).isEqualTo(key);
  383. assertThat(component.getReportAttributes().getRef()).isNull();
  384. assertThat(component.getShortName()).isEqualTo(shortName);
  385. if (uuid != null) {
  386. assertThat(component.getUuid()).isEqualTo(uuid);
  387. } else {
  388. assertThat(component.getUuid()).isNotNull();
  389. }
  390. }
  391. private void verifyComponentByRef(int ref, String key, String shortName, @Nullable String uuid) {
  392. Map<Integer, Component> componentsByRef = indexAllComponentsInTreeByRef(treeRootHolder.getRoot());
  393. Component component = componentsByRef.get(ref);
  394. assertThat(component.getKey()).isEqualTo(key);
  395. assertThat(component.getShortName()).isEqualTo(shortName);
  396. if (uuid != null) {
  397. assertThat(component.getUuid()).isEqualTo(uuid);
  398. } else {
  399. assertThat(component.getUuid()).isNotNull();
  400. }
  401. }
  402. private static ScannerReport.Component component(int componentRef, ComponentType componentType, String key, int... children) {
  403. return component(componentRef, componentType, key, FileStatus.CHANGED, null, children);
  404. }
  405. private static ScannerReport.Component unchangedComponentWithPath(int componentRef, ComponentType componentType, String path, int... children) {
  406. return component(componentRef, componentType, REPORT_PROJECT_KEY + ":" + path, FileStatus.SAME, path, children);
  407. }
  408. private static ScannerReport.Component componentWithPath(int componentRef, ComponentType componentType, String path, int... children) {
  409. return component(componentRef, componentType, REPORT_PROJECT_KEY + ":" + path, FileStatus.CHANGED, path, children);
  410. }
  411. private static ScannerReport.Component component(int componentRef, ComponentType componentType, String key, FileStatus status, @Nullable String path, int... children) {
  412. ScannerReport.Component.Builder builder = ScannerReport.Component.newBuilder()
  413. .setType(componentType)
  414. .setRef(componentRef)
  415. .setName(key)
  416. .setStatus(status)
  417. .setLines(1)
  418. .setKey(key);
  419. if (path != null) {
  420. builder.setProjectRelativePath(path);
  421. }
  422. for (int child : children) {
  423. builder.addChildRef(child);
  424. }
  425. return builder.build();
  426. }
  427. private static Map<Integer, Component> indexAllComponentsInTreeByRef(Component root) {
  428. Map<Integer, Component> componentsByRef = new HashMap<>();
  429. feedComponentByRef(root, componentsByRef);
  430. return componentsByRef;
  431. }
  432. private static Map<String, Component> indexAllComponentsInTreeByKey(Component root) {
  433. Map<String, Component> componentsByKey = new HashMap<>();
  434. feedComponentByKey(root, componentsByKey);
  435. return componentsByKey;
  436. }
  437. private static void feedComponentByKey(Component component, Map<String, Component> map) {
  438. map.put(component.getKey(), component);
  439. for (Component child : component.getChildren()) {
  440. feedComponentByKey(child, map);
  441. }
  442. }
  443. private static void feedComponentByRef(Component component, Map<Integer, Component> map) {
  444. if (component.getReportAttributes().getRef() != null) {
  445. map.put(component.getReportAttributes().getRef(), component);
  446. }
  447. for (Component child : component.getChildren()) {
  448. feedComponentByRef(child, map);
  449. }
  450. }
  451. private ComponentDto insertComponent(ComponentDto component) {
  452. return dbTester.components().insertComponent(component);
  453. }
  454. private SnapshotDto insertSnapshot(SnapshotDto snapshot) {
  455. dbClient.snapshotDao().insert(dbTester.getSession(), snapshot);
  456. dbTester.getSession().commit();
  457. return snapshot;
  458. }
  459. private void setAnalysisMetadataHolder() {
  460. setAnalysisMetadataHolder(false);
  461. }
  462. private void setAnalysisMetadataHolder(boolean isPr) {
  463. Branch branch = isPr ? new PrBranch(DEFAULT_MAIN_BRANCH_NAME) : new DefaultBranchImpl(DEFAULT_MAIN_BRANCH_NAME);
  464. analysisMetadataHolder.setRootComponentRef(ROOT_REF)
  465. .setAnalysisDate(ANALYSIS_DATE)
  466. .setBranch(branch)
  467. .setProject(Project.from(newPrivateProjectDto().setKey(REPORT_PROJECT_KEY).setName(REPORT_PROJECT_KEY)));
  468. }
  469. public static ScannerReport.Metadata createReportMetadata(@Nullable String projectVersion, @Nullable String buildString) {
  470. ScannerReport.Metadata.Builder builder = ScannerReport.Metadata.newBuilder()
  471. .setProjectKey(REPORT_PROJECT_KEY)
  472. .setRootComponentRef(ROOT_REF);
  473. ofNullable(projectVersion).ifPresent(builder::setProjectVersion);
  474. ofNullable(buildString).ifPresent(builder::setBuildString);
  475. return builder.build();
  476. }
  477. private static class PrBranch extends DefaultBranchImpl {
  478. public PrBranch(String branch) {
  479. super(branch);
  480. }
  481. @Override
  482. public BranchType getType() {
  483. return BranchType.PULL_REQUEST;
  484. }
  485. }
  486. }