Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

ScannerMediumTester.java 18KB

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