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.

LoadReportAnalysisMetadataHolderStepTest.java 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2021 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.DataProviderRunner;
  22. import java.util.Collection;
  23. import java.util.HashMap;
  24. import java.util.Map;
  25. import java.util.Optional;
  26. import org.assertj.core.api.Assertions;
  27. import org.junit.Before;
  28. import org.junit.Rule;
  29. import org.junit.Test;
  30. import org.junit.runner.RunWith;
  31. import org.sonar.api.Plugin;
  32. import org.sonar.api.utils.MessageException;
  33. import org.sonar.api.utils.System2;
  34. import org.sonar.ce.task.CeTask;
  35. import org.sonar.ce.task.projectanalysis.analysis.MutableAnalysisMetadataHolderRule;
  36. import org.sonar.ce.task.projectanalysis.analysis.ScannerPlugin;
  37. import org.sonar.ce.task.projectanalysis.batch.BatchReportReaderRule;
  38. import org.sonar.ce.task.projectanalysis.component.BranchLoader;
  39. import org.sonar.ce.task.step.ComputationStep;
  40. import org.sonar.ce.task.step.TestComputationStepContext;
  41. import org.sonar.core.platform.PluginInfo;
  42. import org.sonar.core.platform.PluginRepository;
  43. import org.sonar.db.DbClient;
  44. import org.sonar.db.DbTester;
  45. import org.sonar.db.component.ComponentDto;
  46. import org.sonar.scanner.protocol.output.ScannerReport;
  47. import org.sonar.server.project.Project;
  48. import static java.util.Arrays.stream;
  49. import static org.assertj.core.api.Assertions.assertThat;
  50. import static org.assertj.core.api.Assertions.assertThatThrownBy;
  51. import static org.assertj.core.api.Assertions.tuple;
  52. import static org.mockito.Mockito.mock;
  53. import static org.mockito.Mockito.when;
  54. @RunWith(DataProviderRunner.class)
  55. public class LoadReportAnalysisMetadataHolderStepTest {
  56. private static final String PROJECT_KEY = "project_key";
  57. private static final long ANALYSIS_DATE = 123456789L;
  58. @Rule
  59. public DbTester db = DbTester.create(System2.INSTANCE);
  60. @Rule
  61. public BatchReportReaderRule reportReader = new BatchReportReaderRule();
  62. @Rule
  63. public MutableAnalysisMetadataHolderRule analysisMetadataHolder = new MutableAnalysisMetadataHolderRule();
  64. private final DbClient dbClient = db.getDbClient();
  65. private final TestPluginRepository pluginRepository = new TestPluginRepository();
  66. private ComponentDto project;
  67. private ComputationStep underTest;
  68. @Before
  69. public void setUp() {
  70. CeTask defaultOrgCeTask = createCeTask(PROJECT_KEY);
  71. underTest = createStep(defaultOrgCeTask);
  72. project = db.components().insertPublicProject(p -> p.setDbKey(PROJECT_KEY));
  73. }
  74. @Test
  75. public void set_root_component_ref() {
  76. reportReader.setMetadata(
  77. newBatchReportBuilder()
  78. .setRootComponentRef(1)
  79. .build());
  80. underTest.execute(new TestComputationStepContext());
  81. assertThat(analysisMetadataHolder.getRootComponentRef()).isOne();
  82. }
  83. @Test
  84. public void set_analysis_date() {
  85. reportReader.setMetadata(
  86. newBatchReportBuilder()
  87. .setAnalysisDate(ANALYSIS_DATE)
  88. .build());
  89. underTest.execute(new TestComputationStepContext());
  90. assertThat(analysisMetadataHolder.getAnalysisDate()).isEqualTo(ANALYSIS_DATE);
  91. }
  92. @Test
  93. public void set_fork_date() {
  94. reportReader.setMetadata(
  95. newBatchReportBuilder()
  96. .setForkDate(ANALYSIS_DATE)
  97. .build());
  98. underTest.execute(new TestComputationStepContext());
  99. assertThat(analysisMetadataHolder.getForkDate()).isEqualTo(ANALYSIS_DATE);
  100. }
  101. @Test
  102. public void set_project_from_dto() {
  103. reportReader.setMetadata(
  104. newBatchReportBuilder()
  105. .setRootComponentRef(1)
  106. .build());
  107. underTest.execute(new TestComputationStepContext());
  108. Project project = analysisMetadataHolder.getProject();
  109. assertThat(project.getUuid()).isEqualTo(this.project.uuid());
  110. assertThat(project.getKey()).isEqualTo(this.project.getDbKey());
  111. assertThat(project.getName()).isEqualTo(this.project.name());
  112. assertThat(project.getDescription()).isEqualTo(this.project.description());
  113. }
  114. @Test
  115. public void set_cross_project_duplication_to_true() {
  116. reportReader.setMetadata(
  117. newBatchReportBuilder()
  118. .setCrossProjectDuplicationActivated(true)
  119. .build());
  120. underTest.execute(new TestComputationStepContext());
  121. assertThat(analysisMetadataHolder.isCrossProjectDuplicationEnabled()).isTrue();
  122. }
  123. @Test
  124. public void set_cross_project_duplication_to_false() {
  125. reportReader.setMetadata(
  126. newBatchReportBuilder()
  127. .setCrossProjectDuplicationActivated(false)
  128. .build());
  129. underTest.execute(new TestComputationStepContext());
  130. assertThat(analysisMetadataHolder.isCrossProjectDuplicationEnabled()).isFalse();
  131. }
  132. @Test
  133. public void set_cross_project_duplication_to_false_when_nothing_in_the_report() {
  134. reportReader.setMetadata(
  135. newBatchReportBuilder()
  136. .build());
  137. underTest.execute(new TestComputationStepContext());
  138. assertThat(analysisMetadataHolder.isCrossProjectDuplicationEnabled()).isFalse();
  139. }
  140. @Test
  141. public void execute_fails_with_ISE_if_component_is_null_in_CE_task() {
  142. CeTask res = mock(CeTask.class);
  143. when(res.getComponent()).thenReturn(Optional.empty());
  144. reportReader.setMetadata(ScannerReport.Metadata.newBuilder().build());
  145. ComputationStep underTest = createStep(res);
  146. assertThatThrownBy(() -> underTest.execute(new TestComputationStepContext()))
  147. .isInstanceOf(IllegalStateException.class)
  148. .hasMessage("component missing on ce task");
  149. }
  150. @Test
  151. public void execute_fails_with_MessageException_if_main_projectKey_is_null_in_CE_task() {
  152. CeTask res = mock(CeTask.class);
  153. Optional<CeTask.Component> component = Optional.of(new CeTask.Component("main_prj_uuid", null, null));
  154. when(res.getComponent()).thenReturn(component);
  155. when(res.getMainComponent()).thenReturn(component);
  156. reportReader.setMetadata(ScannerReport.Metadata.newBuilder().build());
  157. ComputationStep underTest = createStep(res);
  158. assertThatThrownBy(() -> underTest.execute(new TestComputationStepContext()))
  159. .isInstanceOf(MessageException.class)
  160. .hasMessage("Compute Engine task main component key is null. Project with UUID main_prj_uuid must have been deleted since report was uploaded. Can not proceed.");
  161. }
  162. @Test
  163. public void execute_fails_with_MessageException_if_projectKey_is_null_in_CE_task() {
  164. CeTask res = mock(CeTask.class);
  165. Optional<CeTask.Component> component = Optional.of(new CeTask.Component("prj_uuid", null, null));
  166. when(res.getComponent()).thenReturn(component);
  167. when(res.getMainComponent()).thenReturn(Optional.of(new CeTask.Component("main_prj_uuid", "main_prj_key", null)));
  168. reportReader.setMetadata(ScannerReport.Metadata.newBuilder().build());
  169. ComputationStep underTest = createStep(res);
  170. assertThatThrownBy(() -> underTest.execute(new TestComputationStepContext()))
  171. .isInstanceOf(MessageException.class)
  172. .hasMessage("Compute Engine task component key is null. Project with UUID prj_uuid must have been deleted since report was uploaded. Can not proceed.");
  173. }
  174. @Test
  175. public void execute_fails_with_MessageException_when_projectKey_in_report_is_different_from_componentKey_in_CE_task() {
  176. ComponentDto otherProject = db.components().insertPublicProject();
  177. reportReader.setMetadata(
  178. ScannerReport.Metadata.newBuilder()
  179. .setProjectKey(otherProject.getDbKey())
  180. .build());
  181. assertThatThrownBy(() -> underTest.execute(new TestComputationStepContext()))
  182. .isInstanceOf(MessageException.class)
  183. .hasMessage("ProjectKey in report (" + otherProject.getDbKey() + ") is not consistent with projectKey under which the report has been submitted (" + PROJECT_KEY + ")");
  184. }
  185. @Test
  186. public void execute_sets_branch_even_if_MessageException_is_thrown_because_projectKey_in_report_is_different_from_componentKey_in_CE_task() {
  187. ComponentDto otherProject = db.components().insertPublicProject();
  188. reportReader.setMetadata(
  189. ScannerReport.Metadata.newBuilder()
  190. .setProjectKey(otherProject.getDbKey())
  191. .build());
  192. try {
  193. underTest.execute(new TestComputationStepContext());
  194. } catch (MessageException e) {
  195. assertThat(analysisMetadataHolder.getBranch()).isNotNull();
  196. }
  197. }
  198. @Test
  199. public void execute_sets_analysis_date_even_if_MessageException_is_thrown_because_projectKey_is_different_from_componentKey_in_CE_task() {
  200. ComponentDto otherProject = db.components().insertPublicProject();
  201. reportReader.setMetadata(
  202. ScannerReport.Metadata.newBuilder()
  203. .setProjectKey(otherProject.getDbKey())
  204. .setAnalysisDate(ANALYSIS_DATE)
  205. .build());
  206. try {
  207. underTest.execute(new TestComputationStepContext());
  208. } catch (MessageException e) {
  209. assertThat(analysisMetadataHolder.getAnalysisDate()).isEqualTo(ANALYSIS_DATE);
  210. }
  211. }
  212. @Test
  213. public void execute_does_not_fail_when_report_has_a_quality_profile_that_does_not_exist_anymore() {
  214. ComponentDto project = db.components().insertPublicProject();
  215. ScannerReport.Metadata.Builder metadataBuilder = newBatchReportBuilder();
  216. metadataBuilder
  217. .setProjectKey(project.getDbKey());
  218. metadataBuilder.putQprofilesPerLanguage("js", ScannerReport.Metadata.QProfile.newBuilder().setKey("p1").setName("Sonar way").setLanguage("js").build());
  219. reportReader.setMetadata(metadataBuilder.build());
  220. ComputationStep underTest = createStep(createCeTask(project.getDbKey()));
  221. underTest.execute(new TestComputationStepContext());
  222. }
  223. @Test
  224. public void execute_read_plugins_from_report() {
  225. // the installed plugins
  226. pluginRepository.add(
  227. new PluginInfo("java"),
  228. new PluginInfo("customjava").setBasePlugin("java"),
  229. new PluginInfo("php"));
  230. // the plugins sent by scanner
  231. ScannerReport.Metadata.Builder metadataBuilder = newBatchReportBuilder();
  232. metadataBuilder.putPluginsByKey("java", ScannerReport.Metadata.Plugin.newBuilder().setKey("java").setUpdatedAt(10L).build());
  233. metadataBuilder.putPluginsByKey("php", ScannerReport.Metadata.Plugin.newBuilder().setKey("php").setUpdatedAt(20L).build());
  234. metadataBuilder.putPluginsByKey("customjava", ScannerReport.Metadata.Plugin.newBuilder().setKey("customjava").setUpdatedAt(30L).build());
  235. metadataBuilder.putPluginsByKey("uninstalled", ScannerReport.Metadata.Plugin.newBuilder().setKey("uninstalled").setUpdatedAt(40L).build());
  236. reportReader.setMetadata(metadataBuilder.build());
  237. underTest.execute(new TestComputationStepContext());
  238. Assertions.assertThat(analysisMetadataHolder.getScannerPluginsByKey().values()).extracting(ScannerPlugin::getKey, ScannerPlugin::getBasePluginKey, ScannerPlugin::getUpdatedAt)
  239. .containsExactlyInAnyOrder(
  240. tuple("java", null, 10L),
  241. tuple("php", null, 20L),
  242. tuple("customjava", "java", 30L),
  243. tuple("uninstalled", null, 40L));
  244. }
  245. private LoadReportAnalysisMetadataHolderStep createStep(CeTask ceTask) {
  246. return new LoadReportAnalysisMetadataHolderStep(ceTask, reportReader, analysisMetadataHolder,
  247. dbClient, new BranchLoader(analysisMetadataHolder), pluginRepository);
  248. }
  249. private static ScannerReport.Metadata.Builder newBatchReportBuilder() {
  250. return ScannerReport.Metadata.newBuilder()
  251. .setProjectKey(PROJECT_KEY);
  252. }
  253. private CeTask createCeTask(String projectKey) {
  254. CeTask res = mock(CeTask.class);
  255. Optional<CeTask.Component> component = Optional.of(new CeTask.Component(projectKey + "_uuid", projectKey, projectKey + "_name"));
  256. when(res.getComponent()).thenReturn(component);
  257. when(res.getMainComponent()).thenReturn(component);
  258. return res;
  259. }
  260. private static class TestPluginRepository implements PluginRepository {
  261. private final Map<String, PluginInfo> pluginsMap = new HashMap<>();
  262. void add(PluginInfo... plugins) {
  263. stream(plugins).forEach(p -> pluginsMap.put(p.getKey(), p));
  264. }
  265. @Override
  266. public Collection<PluginInfo> getPluginInfos() {
  267. return pluginsMap.values();
  268. }
  269. @Override
  270. public PluginInfo getPluginInfo(String key) {
  271. if (!pluginsMap.containsKey(key)) {
  272. throw new IllegalArgumentException();
  273. }
  274. return pluginsMap.get(key);
  275. }
  276. @Override
  277. public Plugin getPluginInstance(String key) {
  278. throw new UnsupportedOperationException();
  279. }
  280. @Override
  281. public Collection<Plugin> getPluginInstances() {
  282. throw new UnsupportedOperationException();
  283. }
  284. @Override
  285. public boolean hasPlugin(String key) {
  286. return pluginsMap.containsKey(key);
  287. }
  288. }
  289. }