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.

MetadataPublisherTest.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  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.scanner.report;
  21. import com.google.common.collect.ImmutableMap;
  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.io.File;
  26. import java.io.IOException;
  27. import java.nio.file.Files;
  28. import java.nio.file.Path;
  29. import java.nio.file.Paths;
  30. import java.time.Instant;
  31. import java.util.Collections;
  32. import java.util.Date;
  33. import java.util.Optional;
  34. import javax.annotation.Nullable;
  35. import org.junit.Before;
  36. import org.junit.Rule;
  37. import org.junit.Test;
  38. import org.junit.rules.TemporaryFolder;
  39. import org.junit.runner.RunWith;
  40. import org.sonar.api.batch.bootstrap.ProjectDefinition;
  41. import org.sonar.api.batch.fs.internal.DefaultInputModule;
  42. import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
  43. import org.sonar.api.batch.scm.ScmProvider;
  44. import org.sonar.scanner.ProjectInfo;
  45. import org.sonar.scanner.bootstrap.ScannerPlugin;
  46. import org.sonar.scanner.bootstrap.ScannerPluginRepository;
  47. import org.sonar.scanner.cpd.CpdSettings;
  48. import org.sonar.scanner.fs.InputModuleHierarchy;
  49. import org.sonar.scanner.protocol.output.ScannerReport;
  50. import org.sonar.scanner.protocol.output.ScannerReportReader;
  51. import org.sonar.scanner.protocol.output.ScannerReportWriter;
  52. import org.sonar.scanner.repository.ForkDateSupplier;
  53. import org.sonar.scanner.rule.QProfile;
  54. import org.sonar.scanner.rule.QualityProfiles;
  55. import org.sonar.scanner.scan.branch.BranchConfiguration;
  56. import org.sonar.scanner.scan.branch.BranchType;
  57. import org.sonar.scanner.scan.filesystem.InputComponentStore;
  58. import org.sonar.scanner.scm.ScmConfiguration;
  59. import org.sonar.scanner.scm.ScmRevision;
  60. import static java.util.Collections.emptyMap;
  61. import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
  62. import static org.assertj.core.api.Assertions.assertThat;
  63. import static org.assertj.core.api.Assertions.entry;
  64. import static org.mockito.ArgumentMatchers.any;
  65. import static org.mockito.Mockito.mock;
  66. import static org.mockito.Mockito.when;
  67. @RunWith(DataProviderRunner.class)
  68. public class MetadataPublisherTest {
  69. @Rule
  70. public TemporaryFolder temp = new TemporaryFolder();
  71. private MetadataPublisher underTest;
  72. private final QualityProfiles qProfiles = mock(QualityProfiles.class);
  73. private final ProjectInfo projectInfo = mock(ProjectInfo.class);
  74. private final CpdSettings cpdSettings = mock(CpdSettings.class);
  75. private final ForkDateSupplier forkDateSupplier = mock(ForkDateSupplier.class);
  76. private final ScannerPluginRepository pluginRepository = mock(ScannerPluginRepository.class);
  77. private BranchConfiguration branches;
  78. private ScmConfiguration scmConfiguration;
  79. private final ScmProvider scmProvider = mock(ScmProvider.class);
  80. private final ScmRevision scmRevision = mock(ScmRevision.class);
  81. private final InputComponentStore componentStore = mock(InputComponentStore.class);
  82. @Before
  83. public void prepare() throws IOException {
  84. when(projectInfo.getAnalysisDate()).thenReturn(new Date(1234567L));
  85. when(scmProvider.relativePathFromScmRoot(any(Path.class))).thenReturn(Paths.get("dummy/path"));
  86. when(scmProvider.revisionId(any(Path.class))).thenReturn("dummy-sha1");
  87. createPublisher(ProjectDefinition.create());
  88. when(pluginRepository.getPluginsByKey()).thenReturn(emptyMap());
  89. }
  90. private void createPublisher(ProjectDefinition def) throws IOException {
  91. Path rootBaseDir = temp.newFolder().toPath();
  92. Path moduleBaseDir = rootBaseDir.resolve("moduleDir");
  93. Files.createDirectory(moduleBaseDir);
  94. DefaultInputModule rootModule = new DefaultInputModule(def
  95. .setBaseDir(rootBaseDir.toFile())
  96. .setKey("root")
  97. .setWorkDir(temp.newFolder()), TestInputFileBuilder.nextBatchId());
  98. InputModuleHierarchy inputModuleHierarchy = mock(InputModuleHierarchy.class);
  99. when(inputModuleHierarchy.root()).thenReturn(rootModule);
  100. DefaultInputModule child = new DefaultInputModule(ProjectDefinition.create()
  101. .setKey("module")
  102. .setBaseDir(moduleBaseDir.toFile())
  103. .setWorkDir(temp.newFolder()), TestInputFileBuilder.nextBatchId());
  104. when(inputModuleHierarchy.children(rootModule)).thenReturn(Collections.singletonList(child));
  105. when(inputModuleHierarchy.relativePathToRoot(child)).thenReturn("modulePath");
  106. when(inputModuleHierarchy.relativePathToRoot(rootModule)).thenReturn("");
  107. branches = mock(BranchConfiguration.class);
  108. scmConfiguration = mock(ScmConfiguration.class);
  109. when(scmConfiguration.provider()).thenReturn(scmProvider);
  110. underTest = new MetadataPublisher(projectInfo, inputModuleHierarchy, qProfiles, cpdSettings,
  111. pluginRepository, branches, scmRevision, forkDateSupplier, componentStore, scmConfiguration);
  112. }
  113. @Test
  114. public void write_metadata() throws Exception {
  115. Date date = new Date();
  116. when(forkDateSupplier.get()).thenReturn(Instant.ofEpochMilli(123456789L));
  117. when(qProfiles.findAll()).thenReturn(Collections.singletonList(new QProfile("q1", "Q1", "java", date)));
  118. when(pluginRepository.getPluginsByKey()).thenReturn(ImmutableMap.of(
  119. "java", new ScannerPlugin("java", 12345L, null),
  120. "php", new ScannerPlugin("php", 45678L, null)));
  121. File outputDir = temp.newFolder();
  122. ScannerReportWriter writer = new ScannerReportWriter(outputDir);
  123. underTest.publish(writer);
  124. ScannerReportReader reader = new ScannerReportReader(outputDir);
  125. ScannerReport.Metadata metadata = reader.readMetadata();
  126. assertThat(metadata.getForkDate()).isEqualTo(123456789L);
  127. assertThat(metadata.getAnalysisDate()).isEqualTo(1234567L);
  128. assertThat(metadata.getProjectKey()).isEqualTo("root");
  129. assertThat(metadata.getModulesProjectRelativePathByKeyMap()).containsOnly(entry("module", "modulePath"), entry("root", ""));
  130. assertThat(metadata.getProjectVersion()).isEmpty();
  131. assertThat(metadata.getNotAnalyzedFilesByLanguageCount()).isZero();
  132. assertThat(metadata.getQprofilesPerLanguageMap()).containsOnly(entry("java", org.sonar.scanner.protocol.output.ScannerReport.Metadata.QProfile.newBuilder()
  133. .setKey("q1")
  134. .setName("Q1")
  135. .setLanguage("java")
  136. .setRulesUpdatedAt(date.getTime())
  137. .build()));
  138. assertThat(metadata.getPluginsByKey()).containsOnly(entry("java", org.sonar.scanner.protocol.output.ScannerReport.Metadata.Plugin.newBuilder()
  139. .setKey("java")
  140. .setUpdatedAt(12345)
  141. .build()),
  142. entry("php", org.sonar.scanner.protocol.output.ScannerReport.Metadata.Plugin.newBuilder()
  143. .setKey("php")
  144. .setUpdatedAt(45678)
  145. .build()));
  146. }
  147. @Test
  148. public void write_not_analysed_file_counts() throws Exception {
  149. when(componentStore.getNotAnalysedFilesByLanguage()).thenReturn(ImmutableMap.of("c", 10, "cpp", 20));
  150. File outputDir = temp.newFolder();
  151. ScannerReportWriter writer = new ScannerReportWriter(outputDir);
  152. underTest.publish(writer);
  153. ScannerReportReader reader = new ScannerReportReader(outputDir);
  154. ScannerReport.Metadata metadata = reader.readMetadata();
  155. assertThat(metadata.getNotAnalyzedFilesByLanguageMap()).contains(entry("c", 10), entry("cpp", 20));
  156. }
  157. @Test
  158. @UseDataProvider("projectVersions")
  159. public void write_project_version(@Nullable String projectVersion, String expected) throws Exception {
  160. when(projectInfo.getProjectVersion()).thenReturn(Optional.ofNullable(projectVersion));
  161. File outputDir = temp.newFolder();
  162. ScannerReportWriter writer = new ScannerReportWriter(outputDir);
  163. underTest.publish(writer);
  164. ScannerReportReader reader = new ScannerReportReader(outputDir);
  165. ScannerReport.Metadata metadata = reader.readMetadata();
  166. assertThat(metadata.getProjectVersion()).isEqualTo(expected);
  167. }
  168. @DataProvider
  169. public static Object[][] projectVersions() {
  170. String version = randomAlphabetic(15);
  171. return new Object[][] {
  172. {null, ""},
  173. {"", ""},
  174. {"5.6.3", "5.6.3"},
  175. {version, version}
  176. };
  177. }
  178. @Test
  179. @UseDataProvider("buildStrings")
  180. public void write_buildString(@Nullable String buildString, String expected) throws Exception {
  181. when(projectInfo.getBuildString()).thenReturn(Optional.ofNullable(buildString));
  182. File outputDir = temp.newFolder();
  183. ScannerReportWriter writer = new ScannerReportWriter(outputDir);
  184. underTest.publish(writer);
  185. ScannerReportReader reader = new ScannerReportReader(outputDir);
  186. ScannerReport.Metadata metadata = reader.readMetadata();
  187. assertThat(metadata.getBuildString()).isEqualTo(expected);
  188. }
  189. @DataProvider
  190. public static Object[][] buildStrings() {
  191. String randomBuildString = randomAlphabetic(15);
  192. return new Object[][] {
  193. {null, ""},
  194. {"", ""},
  195. {"5.6.3", "5.6.3"},
  196. {randomBuildString, randomBuildString}
  197. };
  198. }
  199. @Test
  200. public void write_branch_info() throws Exception {
  201. String branchName = "name";
  202. String targetName = "target";
  203. when(branches.branchName()).thenReturn(branchName);
  204. when(branches.branchType()).thenReturn(BranchType.BRANCH);
  205. when(branches.targetBranchName()).thenReturn(targetName);
  206. File outputDir = temp.newFolder();
  207. underTest.publish(new ScannerReportWriter(outputDir));
  208. ScannerReportReader reader = new ScannerReportReader(outputDir);
  209. ScannerReport.Metadata metadata = reader.readMetadata();
  210. assertThat(metadata.getBranchName()).isEqualTo(branchName);
  211. assertThat(metadata.getBranchType()).isEqualTo(ScannerReport.Metadata.BranchType.BRANCH);
  212. assertThat(metadata.getReferenceBranchName()).isEmpty();
  213. assertThat(metadata.getTargetBranchName()).isEqualTo(targetName);
  214. }
  215. @Test
  216. public void write_project_basedir() throws Exception {
  217. String path = "some/dir";
  218. Path relativePathFromScmRoot = Paths.get(path);
  219. when(scmProvider.relativePathFromScmRoot(any(Path.class))).thenReturn(relativePathFromScmRoot);
  220. File outputDir = temp.newFolder();
  221. underTest.publish(new ScannerReportWriter(outputDir));
  222. ScannerReportReader reader = new ScannerReportReader(outputDir);
  223. ScannerReport.Metadata metadata = reader.readMetadata();
  224. assertThat(metadata.getRelativePathFromScmRoot()).isEqualTo(path);
  225. }
  226. @Test
  227. public void write_revision_id() throws Exception {
  228. String revisionId = "some-sha1";
  229. when(scmRevision.get()).thenReturn(Optional.of(revisionId));
  230. File outputDir = temp.newFolder();
  231. underTest.publish(new ScannerReportWriter(outputDir));
  232. ScannerReportReader reader = new ScannerReportReader(outputDir);
  233. ScannerReport.Metadata metadata = reader.readMetadata();
  234. assertThat(metadata.getScmRevisionId()).isEqualTo(revisionId);
  235. }
  236. @Test
  237. public void should_not_crash_when_scm_provider_does_not_support_relativePathFromScmRoot() throws IOException {
  238. ScmProvider fakeScmProvider = new ScmProvider() {
  239. @Override
  240. public String key() {
  241. return "foo";
  242. }
  243. };
  244. when(scmConfiguration.provider()).thenReturn(fakeScmProvider);
  245. File outputDir = temp.newFolder();
  246. underTest.publish(new ScannerReportWriter(outputDir));
  247. ScannerReportReader reader = new ScannerReportReader(outputDir);
  248. ScannerReport.Metadata metadata = reader.readMetadata();
  249. assertThat(metadata.getRelativePathFromScmRoot()).isEmpty();
  250. }
  251. }