Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

ScannerMediumTester.java 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2020 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.mediumtest;
  21. import java.io.File;
  22. import java.io.FileInputStream;
  23. import java.io.IOException;
  24. import java.io.InputStreamReader;
  25. import java.io.Reader;
  26. import java.nio.charset.StandardCharsets;
  27. import java.nio.file.Path;
  28. import java.util.ArrayList;
  29. import java.util.Collections;
  30. import java.util.Date;
  31. import java.util.HashMap;
  32. import java.util.LinkedList;
  33. import java.util.List;
  34. import java.util.Map;
  35. import java.util.Properties;
  36. import javax.annotation.CheckForNull;
  37. import javax.annotation.Nullable;
  38. import org.apache.commons.io.FileUtils;
  39. import org.junit.rules.ExternalResource;
  40. import org.sonar.api.Plugin;
  41. import org.sonar.api.SonarEdition;
  42. import org.sonar.api.SonarProduct;
  43. import org.sonar.api.SonarQubeSide;
  44. import org.sonar.api.SonarRuntime;
  45. import org.sonar.api.batch.rule.LoadedActiveRule;
  46. import org.sonar.api.impl.server.RulesDefinitionContext;
  47. import org.sonar.api.measures.CoreMetrics;
  48. import org.sonar.api.measures.Metric;
  49. import org.sonar.api.rule.RuleKey;
  50. import org.sonar.api.server.rule.RulesDefinition;
  51. import org.sonar.api.server.rule.RulesDefinition.Repository;
  52. import org.sonar.api.utils.DateUtils;
  53. import org.sonar.api.utils.Version;
  54. import org.sonar.batch.bootstrapper.Batch;
  55. import org.sonar.batch.bootstrapper.EnvironmentInformation;
  56. import org.sonar.batch.bootstrapper.LogOutput;
  57. import org.sonar.scanner.bootstrap.GlobalAnalysisMode;
  58. import org.sonar.scanner.report.CeTaskReportDataHolder;
  59. import org.sonar.scanner.repository.FileData;
  60. import org.sonar.scanner.repository.MetricsRepository;
  61. import org.sonar.scanner.repository.MetricsRepositoryLoader;
  62. import org.sonar.scanner.repository.ProjectRepositories;
  63. import org.sonar.scanner.repository.ProjectRepositoriesLoader;
  64. import org.sonar.scanner.repository.QualityProfileLoader;
  65. import org.sonar.scanner.repository.SingleProjectRepository;
  66. import org.sonar.scanner.repository.settings.GlobalSettingsLoader;
  67. import org.sonar.scanner.repository.settings.ProjectSettingsLoader;
  68. import org.sonar.scanner.rule.ActiveRulesLoader;
  69. import org.sonar.scanner.rule.RulesLoader;
  70. import org.sonar.scanner.scan.ScanProperties;
  71. import org.sonar.scanner.scan.branch.BranchConfiguration;
  72. import org.sonar.scanner.scan.branch.BranchConfigurationLoader;
  73. import org.sonar.scanner.scan.branch.BranchType;
  74. import org.sonar.scanner.scan.branch.ProjectBranches;
  75. import org.sonar.scanner.scan.branch.ProjectPullRequests;
  76. import org.sonarqube.ws.Qualityprofiles.SearchWsResponse.QualityProfile;
  77. import org.sonarqube.ws.Rules.ListResponse.Rule;
  78. /**
  79. * Main utility class for writing scanner medium tests.
  80. */
  81. public class ScannerMediumTester extends ExternalResource {
  82. private static Path userHome = null;
  83. private Map<String, String> globalProperties = new HashMap<>();
  84. private final FakeMetricsRepositoryLoader globalRefProvider = new FakeMetricsRepositoryLoader();
  85. private final FakeBranchConfigurationLoader branchConfigurationLoader = new FakeBranchConfigurationLoader();
  86. private final FakeBranchConfiguration branchConfiguration = new FakeBranchConfiguration();
  87. private final FakeProjectRepositoriesLoader projectRefProvider = new FakeProjectRepositoriesLoader();
  88. private final FakePluginInstaller pluginInstaller = new FakePluginInstaller();
  89. private final FakeGlobalSettingsLoader globalSettingsLoader = new FakeGlobalSettingsLoader();
  90. private final FakeProjectSettingsLoader projectSettingsLoader = new FakeProjectSettingsLoader();
  91. private final FakeRulesLoader rulesLoader = new FakeRulesLoader();
  92. private final FakeQualityProfileLoader qualityProfiles = new FakeQualityProfileLoader();
  93. private final FakeActiveRulesLoader activeRules = new FakeActiveRulesLoader();
  94. private final FakeSonarRuntime sonarRuntime = new FakeSonarRuntime();
  95. private final CeTaskReportDataHolder reportMetadataHolder = new CeTaskReportDataHolder();
  96. private LogOutput logOutput = null;
  97. private static void createWorkingDirs() throws IOException {
  98. destroyWorkingDirs();
  99. userHome = java.nio.file.Files.createTempDirectory("mediumtest-userHome");
  100. }
  101. private static void destroyWorkingDirs() throws IOException {
  102. if (userHome != null) {
  103. FileUtils.deleteDirectory(userHome.toFile());
  104. userHome = null;
  105. }
  106. }
  107. public ScannerMediumTester setLogOutput(LogOutput logOutput) {
  108. this.logOutput = logOutput;
  109. return this;
  110. }
  111. public ScannerMediumTester registerPlugin(String pluginKey, File location) {
  112. return registerPlugin(pluginKey, location, 1L);
  113. }
  114. public ScannerMediumTester registerPlugin(String pluginKey, File location, long lastUpdatedAt) {
  115. pluginInstaller.add(pluginKey, location, lastUpdatedAt);
  116. return this;
  117. }
  118. public ScannerMediumTester registerPlugin(String pluginKey, Plugin instance) {
  119. return registerPlugin(pluginKey, instance, 1L);
  120. }
  121. public ScannerMediumTester registerPlugin(String pluginKey, Plugin instance, long lastUpdatedAt) {
  122. pluginInstaller.add(pluginKey, instance, lastUpdatedAt);
  123. return this;
  124. }
  125. public ScannerMediumTester registerCoreMetrics() {
  126. for (Metric<?> m : CoreMetrics.getMetrics()) {
  127. registerMetric(m);
  128. }
  129. return this;
  130. }
  131. public ScannerMediumTester registerMetric(Metric<?> metric) {
  132. globalRefProvider.add(metric);
  133. return this;
  134. }
  135. public ScannerMediumTester addQProfile(String language, String name) {
  136. qualityProfiles.add(language, name);
  137. return this;
  138. }
  139. public ScannerMediumTester addRule(Rule rule) {
  140. rulesLoader.addRule(rule);
  141. return this;
  142. }
  143. public ScannerMediumTester addRule(String key, String repoKey, String internalKey, String name) {
  144. Rule.Builder builder = Rule.newBuilder();
  145. builder.setKey(key);
  146. builder.setRepository(repoKey);
  147. if (internalKey != null) {
  148. builder.setInternalKey(internalKey);
  149. }
  150. builder.setName(name);
  151. rulesLoader.addRule(builder.build());
  152. return this;
  153. }
  154. public ScannerMediumTester addRules(RulesDefinition rulesDefinition) {
  155. RulesDefinition.Context context = new RulesDefinitionContext();
  156. rulesDefinition.define(context);
  157. List<Repository> repositories = context.repositories();
  158. for (Repository repo : repositories) {
  159. for (RulesDefinition.Rule rule : repo.rules()) {
  160. this.addRule(rule.key(), rule.repository().key(), rule.internalKey(), rule.name());
  161. }
  162. }
  163. return this;
  164. }
  165. public ScannerMediumTester addDefaultQProfile(String language, String name) {
  166. addQProfile(language, name);
  167. return this;
  168. }
  169. public ScannerMediumTester bootstrapProperties(Map<String, String> props) {
  170. globalProperties.putAll(props);
  171. return this;
  172. }
  173. public ScannerMediumTester activateRule(LoadedActiveRule activeRule) {
  174. activeRules.addActiveRule(activeRule);
  175. return this;
  176. }
  177. public ScannerMediumTester addActiveRule(String repositoryKey, String ruleKey, @Nullable String templateRuleKey, String name, @Nullable String severity,
  178. @Nullable String internalKey, @Nullable String language) {
  179. LoadedActiveRule r = new LoadedActiveRule();
  180. r.setInternalKey(internalKey);
  181. r.setRuleKey(RuleKey.of(repositoryKey, ruleKey));
  182. r.setName(name);
  183. r.setTemplateRuleKey(templateRuleKey);
  184. r.setLanguage(language);
  185. r.setSeverity(severity);
  186. activeRules.addActiveRule(r);
  187. return this;
  188. }
  189. public ScannerMediumTester addFileData(String path, FileData fileData) {
  190. projectRefProvider.addFileData(path, fileData);
  191. return this;
  192. }
  193. public ScannerMediumTester addGlobalServerSettings(String key, String value) {
  194. globalSettingsLoader.getGlobalSettings().put(key, value);
  195. return this;
  196. }
  197. public ScannerMediumTester addProjectServerSettings(String key, String value) {
  198. projectSettingsLoader.getProjectSettings().put(key, value);
  199. return this;
  200. }
  201. @Override
  202. protected void before() {
  203. try {
  204. createWorkingDirs();
  205. } catch (IOException e) {
  206. throw new IllegalStateException(e);
  207. }
  208. registerCoreMetrics();
  209. globalProperties.put(GlobalAnalysisMode.MEDIUM_TEST_ENABLED, "true");
  210. globalProperties.put(ScanProperties.KEEP_REPORT_PROP_KEY, "true");
  211. globalProperties.put("sonar.userHome", userHome.toString());
  212. }
  213. @Override
  214. protected void after() {
  215. try {
  216. destroyWorkingDirs();
  217. } catch (IOException e) {
  218. throw new IllegalStateException(e);
  219. }
  220. }
  221. public AnalysisBuilder newAnalysis() {
  222. return new AnalysisBuilder(this);
  223. }
  224. public AnalysisBuilder newAnalysis(File sonarProps) {
  225. Properties prop = new Properties();
  226. try (Reader reader = new InputStreamReader(new FileInputStream(sonarProps), StandardCharsets.UTF_8)) {
  227. prop.load(reader);
  228. } catch (Exception e) {
  229. throw new IllegalStateException("Unable to read configuration file", e);
  230. }
  231. AnalysisBuilder builder = new AnalysisBuilder(this);
  232. builder.property("sonar.projectBaseDir", sonarProps.getParentFile().getAbsolutePath());
  233. for (Map.Entry<Object, Object> entry : prop.entrySet()) {
  234. builder.property(entry.getKey().toString(), entry.getValue().toString());
  235. }
  236. return builder;
  237. }
  238. public static class AnalysisBuilder {
  239. private final Map<String, String> taskProperties = new HashMap<>();
  240. private ScannerMediumTester tester;
  241. public AnalysisBuilder(ScannerMediumTester tester) {
  242. this.tester = tester;
  243. }
  244. public AnalysisResult execute() {
  245. AnalysisResult result = new AnalysisResult();
  246. Map<String, String> props = new HashMap<>();
  247. props.putAll(tester.globalProperties);
  248. props.putAll(taskProperties);
  249. Batch.builder()
  250. .setGlobalProperties(props)
  251. .setEnableLoggingConfiguration(true)
  252. .addComponents(new EnvironmentInformation("mediumTest", "1.0"),
  253. tester.pluginInstaller,
  254. tester.globalRefProvider,
  255. tester.qualityProfiles,
  256. tester.rulesLoader,
  257. tester.branchConfigurationLoader,
  258. tester.projectRefProvider,
  259. tester.activeRules,
  260. tester.globalSettingsLoader,
  261. tester.projectSettingsLoader,
  262. tester.sonarRuntime,
  263. tester.reportMetadataHolder,
  264. result)
  265. .setLogOutput(tester.logOutput)
  266. .build().execute();
  267. return result;
  268. }
  269. public AnalysisBuilder properties(Map<String, String> props) {
  270. taskProperties.putAll(props);
  271. return this;
  272. }
  273. public AnalysisBuilder property(String key, String value) {
  274. taskProperties.put(key, value);
  275. return this;
  276. }
  277. }
  278. private static class FakeRulesLoader implements RulesLoader {
  279. private List<org.sonarqube.ws.Rules.ListResponse.Rule> rules = new LinkedList<>();
  280. public FakeRulesLoader addRule(Rule rule) {
  281. rules.add(rule);
  282. return this;
  283. }
  284. @Override
  285. public List<Rule> load() {
  286. return rules;
  287. }
  288. }
  289. private static class FakeActiveRulesLoader implements ActiveRulesLoader {
  290. private List<LoadedActiveRule> activeRules = new LinkedList<>();
  291. public void addActiveRule(LoadedActiveRule activeRule) {
  292. this.activeRules.add(activeRule);
  293. }
  294. @Override
  295. public List<LoadedActiveRule> load(String qualityProfileKey) {
  296. return activeRules;
  297. }
  298. }
  299. private static class FakeMetricsRepositoryLoader implements MetricsRepositoryLoader {
  300. private int metricId = 1;
  301. private List<Metric> metrics = new ArrayList<>();
  302. @Override
  303. public MetricsRepository load() {
  304. return new MetricsRepository(metrics);
  305. }
  306. public FakeMetricsRepositoryLoader add(Metric<?> metric) {
  307. metric.setId(metricId++);
  308. metrics.add(metric);
  309. metricId++;
  310. return this;
  311. }
  312. }
  313. private static class FakeProjectRepositoriesLoader implements ProjectRepositoriesLoader {
  314. private Map<String, FileData> fileDataMap = new HashMap<>();
  315. @Override
  316. public ProjectRepositories load(String projectKey, @Nullable String branchBase) {
  317. return new SingleProjectRepository(fileDataMap);
  318. }
  319. public FakeProjectRepositoriesLoader addFileData(String path, FileData fileData) {
  320. fileDataMap.put(path, fileData);
  321. return this;
  322. }
  323. }
  324. private static class FakeBranchConfiguration implements BranchConfiguration {
  325. private BranchType branchType = BranchType.BRANCH;
  326. private String branchName = null;
  327. private String branchTarget = null;
  328. private String referenceBranchName = null;
  329. @Override
  330. public BranchType branchType() {
  331. return branchType;
  332. }
  333. @CheckForNull
  334. @Override
  335. public String branchName() {
  336. return branchName;
  337. }
  338. @CheckForNull
  339. @Override
  340. public String targetBranchName() {
  341. return branchTarget;
  342. }
  343. @CheckForNull
  344. @Override
  345. public String referenceBranchName() {
  346. return referenceBranchName;
  347. }
  348. @Override
  349. public String pullRequestKey() {
  350. return "1'";
  351. }
  352. }
  353. private static class FakeSonarRuntime implements SonarRuntime {
  354. private SonarEdition edition;
  355. FakeSonarRuntime() {
  356. this.edition = SonarEdition.COMMUNITY;
  357. }
  358. @Override
  359. public Version getApiVersion() {
  360. return Version.create(7, 8);
  361. }
  362. @Override
  363. public SonarProduct getProduct() {
  364. return SonarProduct.SONARQUBE;
  365. }
  366. @Override
  367. public SonarQubeSide getSonarQubeSide() {
  368. return SonarQubeSide.SCANNER;
  369. }
  370. @Override
  371. public SonarEdition getEdition() {
  372. return edition;
  373. }
  374. public void setEdition(SonarEdition edition) {
  375. this.edition = edition;
  376. }
  377. }
  378. public ScannerMediumTester setBranchType(BranchType branchType) {
  379. branchConfiguration.branchType = branchType;
  380. return this;
  381. }
  382. public ScannerMediumTester setBranchName(String branchName) {
  383. this.branchConfiguration.branchName = branchName;
  384. return this;
  385. }
  386. public ScannerMediumTester setBranchTarget(String branchTarget) {
  387. this.branchConfiguration.branchTarget = branchTarget;
  388. return this;
  389. }
  390. public ScannerMediumTester setReferenceBranchName(String referenceBranchNam) {
  391. this.branchConfiguration.referenceBranchName = referenceBranchNam;
  392. return this;
  393. }
  394. public ScannerMediumTester setEdition(SonarEdition edition) {
  395. this.sonarRuntime.setEdition(edition);
  396. return this;
  397. }
  398. private class FakeBranchConfigurationLoader implements BranchConfigurationLoader {
  399. @Override
  400. public BranchConfiguration load(Map<String, String> projectSettings, ProjectBranches branches, ProjectPullRequests pullRequests) {
  401. return branchConfiguration;
  402. }
  403. }
  404. private static class FakeQualityProfileLoader implements QualityProfileLoader {
  405. private List<QualityProfile> qualityProfiles = new LinkedList<>();
  406. public void add(String language, String name) {
  407. qualityProfiles.add(QualityProfile.newBuilder()
  408. .setLanguage(language)
  409. .setKey(name)
  410. .setName(name)
  411. .setRulesUpdatedAt(DateUtils.formatDateTime(new Date(1234567891212L)))
  412. .build());
  413. }
  414. @Override
  415. public List<QualityProfile> load(String projectKey) {
  416. return qualityProfiles;
  417. }
  418. }
  419. private static class FakeGlobalSettingsLoader implements GlobalSettingsLoader {
  420. private Map<String, String> globalSettings = new HashMap<>();
  421. public Map<String, String> getGlobalSettings() {
  422. return globalSettings;
  423. }
  424. @Override
  425. public Map<String, String> loadGlobalSettings() {
  426. return Collections.unmodifiableMap(globalSettings);
  427. }
  428. }
  429. private static class FakeProjectSettingsLoader implements ProjectSettingsLoader {
  430. private Map<String, String> projectSettings = new HashMap<>();
  431. public Map<String, String> getProjectSettings() {
  432. return projectSettings;
  433. }
  434. @Override
  435. public Map<String, String> loadProjectSettings() {
  436. return Collections.unmodifiableMap(projectSettings);
  437. }
  438. }
  439. }