]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10206 Allow to configure the location where scanner writes report-task.txt
authorDuarte Meneses <duarte.meneses@sonarsource.com>
Wed, 6 Jun 2018 07:17:31 +0000 (09:17 +0200)
committerSonarTech <sonartech@sonarsource.com>
Mon, 11 Jun 2018 18:20:48 +0000 (20:20 +0200)
12 files changed:
sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MetadataPublisher.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ReportPublisher.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultQualityProfileLoader.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ScanProperties.java [new file with mode: 0644]
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/InputFileBuilder.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/ScannerMediumTester.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ReportPublisherTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/DefaultQualityProfileLoaderTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ScanPropertiesTest.java [new file with mode: 0644]
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/InputFileBuilderTest.java

index a17c691f8bb1d4df85284aac8121b73f6b61bc39..4cb964ab2c4829d40388605896bc7a36a2bf7e78 100644 (file)
@@ -28,7 +28,6 @@ import javax.annotation.Nullable;
 import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
 import org.sonar.api.batch.scm.ScmProvider;
-import org.sonar.api.config.Configuration;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 import org.sonar.scanner.ProjectAnalysisInfo;
@@ -40,6 +39,7 @@ import org.sonar.scanner.protocol.output.ScannerReport.Metadata.BranchType;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
 import org.sonar.scanner.rule.ModuleQProfiles;
 import org.sonar.scanner.rule.QProfile;
+import org.sonar.scanner.scan.ScanProperties;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
 import org.sonar.scanner.scm.ScmConfiguration;
 
@@ -49,7 +49,7 @@ public class MetadataPublisher implements ReportPublisherStep {
 
   private static final Logger LOG = Loggers.get(MetadataPublisher.class);
 
-  private final Configuration settings;
+  private final ScanProperties properties;
   private final ModuleQProfiles qProfiles;
   private final ProjectAnalysisInfo projectAnalysisInfo;
   private final InputModuleHierarchy moduleHierarchy;
@@ -60,12 +60,12 @@ public class MetadataPublisher implements ReportPublisherStep {
   @Nullable
   private final ScmConfiguration scmConfiguration;
 
-  public MetadataPublisher(ProjectAnalysisInfo projectAnalysisInfo, InputModuleHierarchy moduleHierarchy, Configuration settings,
+  public MetadataPublisher(ProjectAnalysisInfo projectAnalysisInfo, InputModuleHierarchy moduleHierarchy, ScanProperties properties,
     ModuleQProfiles qProfiles, CpdSettings cpdSettings, ScannerPluginRepository pluginRepository, BranchConfiguration branchConfiguration,
     @Nullable ScmConfiguration scmConfiguration) {
     this.projectAnalysisInfo = projectAnalysisInfo;
     this.moduleHierarchy = moduleHierarchy;
-    this.settings = settings;
+    this.properties = properties;
     this.qProfiles = qProfiles;
     this.cpdSettings = cpdSettings;
     this.pluginRepository = pluginRepository;
@@ -73,9 +73,9 @@ public class MetadataPublisher implements ReportPublisherStep {
     this.scmConfiguration = scmConfiguration;
   }
 
-  public MetadataPublisher(ProjectAnalysisInfo projectAnalysisInfo, InputModuleHierarchy moduleHierarchy, Configuration settings,
+  public MetadataPublisher(ProjectAnalysisInfo projectAnalysisInfo, InputModuleHierarchy moduleHierarchy, ScanProperties properties,
     ModuleQProfiles qProfiles, CpdSettings cpdSettings, ScannerPluginRepository pluginRepository, BranchConfiguration branchConfiguration) {
-    this(projectAnalysisInfo, moduleHierarchy, settings, qProfiles, cpdSettings, pluginRepository, branchConfiguration, null);
+    this(projectAnalysisInfo, moduleHierarchy, properties, qProfiles, cpdSettings, pluginRepository, branchConfiguration, null);
   }
 
   @Override
@@ -88,7 +88,7 @@ public class MetadataPublisher implements ReportPublisherStep {
       .setCrossProjectDuplicationActivated(cpdSettings.isCrossProjectDuplicationEnabled())
       .setRootComponentRef(rootProject.batchId());
 
-    settings.get(ORGANIZATION).ifPresent(builder::setOrganizationKey);
+    properties.organizationKey().ifPresent(builder::setOrganizationKey);
 
     if (branchConfiguration.branchName() != null) {
       addBranchInformation(builder);
index 714199de09cf712caaa4d9bbab5daf186590ef62..11cd6a0f63dce33b212ef44a4e405914608721d5 100644 (file)
@@ -38,7 +38,6 @@ import org.apache.commons.io.FileUtils;
 import org.picocontainer.Startable;
 import org.sonar.api.batch.ScannerSide;
 import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
-import org.sonar.api.config.Configuration;
 import org.sonar.api.platform.Server;
 import org.sonar.api.utils.MessageException;
 import org.sonar.api.utils.TempFolder;
@@ -48,6 +47,7 @@ import org.sonar.api.utils.log.Loggers;
 import org.sonar.scanner.bootstrap.GlobalAnalysisMode;
 import org.sonar.scanner.bootstrap.ScannerWsClient;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
+import org.sonar.scanner.scan.ScanProperties;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
 import org.sonarqube.ws.Ce;
 import org.sonarqube.ws.MediaTypes;
@@ -58,8 +58,6 @@ import org.sonarqube.ws.client.WsResponse;
 import static java.net.URLEncoder.encode;
 import static org.apache.commons.lang.StringUtils.EMPTY;
 import static org.apache.commons.lang.StringUtils.isBlank;
-import static org.sonar.core.config.ScannerProperties.BRANCH_NAME;
-import static org.sonar.core.config.ScannerProperties.ORGANIZATION;
 import static org.sonar.core.util.FileUtils.deleteQuietly;
 import static org.sonar.scanner.scan.branch.BranchType.LONG;
 import static org.sonar.scanner.scan.branch.BranchType.PULL_REQUEST;
@@ -69,18 +67,12 @@ import static org.sonar.scanner.scan.branch.BranchType.SHORT;
 public class ReportPublisher implements Startable {
 
   private static final Logger LOG = Loggers.get(ReportPublisher.class);
-
-  public static final String KEEP_REPORT_PROP_KEY = "sonar.scanner.keepReport";
-  public static final String VERBOSE_KEY = "sonar.verbose";
-  public static final String METADATA_DUMP_FILENAME = "report-task.txt";
   private static final String CHARACTERISTIC = "characteristic";
-
   private static final String DASHBOARD = "dashboard";
   private static final String BRANCH = "branch";
   private static final String ID = "id";
   private static final String RESOLVED = "resolved";
 
-  private final Configuration settings;
   private final ScannerWsClient wsClient;
   private final AnalysisContextReportPublisher contextPublisher;
   private final InputModuleHierarchy moduleHierarchy;
@@ -89,13 +81,13 @@ public class ReportPublisher implements Startable {
   private final ReportPublisherStep[] publishers;
   private final Server server;
   private final BranchConfiguration branchConfiguration;
+  private final ScanProperties properties;
 
   private Path reportDir;
   private ScannerReportWriter writer;
 
-  public ReportPublisher(Configuration settings, ScannerWsClient wsClient, Server server, AnalysisContextReportPublisher contextPublisher,
+  public ReportPublisher(ScanProperties properties, ScannerWsClient wsClient, Server server, AnalysisContextReportPublisher contextPublisher,
     InputModuleHierarchy moduleHierarchy, GlobalAnalysisMode analysisMode, TempFolder temp, ReportPublisherStep[] publishers, BranchConfiguration branchConfiguration) {
-    this.settings = settings;
     this.wsClient = wsClient;
     this.server = server;
     this.contextPublisher = contextPublisher;
@@ -104,6 +96,7 @@ public class ReportPublisher implements Startable {
     this.temp = temp;
     this.publishers = publishers;
     this.branchConfiguration = branchConfiguration;
+    this.properties = properties;
   }
 
   @Override
@@ -122,7 +115,7 @@ public class ReportPublisher implements Startable {
 
   @Override
   public void stop() {
-    if (!shouldKeepReport()) {
+    if (!properties.shouldKeepReport()) {
       deleteQuietly(reportDir);
     }
   }
@@ -140,7 +133,7 @@ public class ReportPublisher implements Startable {
     String taskId = null;
     if (!analysisMode.isIssues()) {
       File report = generateReportFile();
-      if (shouldKeepReport()) {
+      if (properties.shouldKeepReport()) {
         LOG.info("Analysis report generated in " + reportDir);
       }
       if (!analysisMode.isMediumTest()) {
@@ -150,10 +143,6 @@ public class ReportPublisher implements Startable {
     logSuccess(taskId);
   }
 
-  private boolean shouldKeepReport() {
-    return settings.getBoolean(KEEP_REPORT_PROP_KEY).orElse(false) || settings.getBoolean(VERBOSE_KEY).orElse(false);
-  }
-
   private File generateReportFile() {
     try {
       long startTime = System.currentTimeMillis();
@@ -184,7 +173,7 @@ public class ReportPublisher implements Startable {
     PostRequest.Part filePart = new PostRequest.Part(MediaTypes.ZIP, report);
     PostRequest post = new PostRequest("api/ce/submit")
       .setMediaType(MediaTypes.PROTOBUF)
-      .setParam("organization", settings.get(ORGANIZATION).orElse(null))
+      .setParam("organization", properties.organizationKey().orElse(null))
       .setParam("projectKey", moduleHierarchy.root().key())
       .setParam("projectName", moduleHierarchy.root().getOriginalName())
       .setParam("projectBranch", moduleHierarchy.root().getBranch())
@@ -225,11 +214,11 @@ public class ReportPublisher implements Startable {
 
       Map<String, String> metadata = new LinkedHashMap<>();
       String effectiveKey = moduleHierarchy.root().getKeyWithBranch();
-      settings.get(ORGANIZATION).ifPresent(org -> metadata.put("organization", org));
+      properties.organizationKey().ifPresent(org -> metadata.put("organization", org));
       metadata.put("projectKey", effectiveKey);
       metadata.put("serverUrl", server.getPublicRootUrl());
       metadata.put("serverVersion", server.getVersion());
-      settings.get(BRANCH_NAME).ifPresent(branch -> metadata.put(BRANCH, branch));
+      properties.branch().ifPresent(branch -> metadata.put("branch", branch));
 
       URL dashboardUrl = buildDashboardUrl(server.getPublicRootUrl(), effectiveKey);
       metadata.put("dashboardUrl", dashboardUrl.toExternalForm());
@@ -311,7 +300,7 @@ public class ReportPublisher implements Startable {
   }
 
   private static String encoded(@Nullable String queryParameter) {
-    if (isBlank(queryParameter)){
+    if (isBlank(queryParameter)) {
       return EMPTY;
     }
     try {
@@ -322,13 +311,16 @@ public class ReportPublisher implements Startable {
   }
 
   private void dumpMetadata(Map<String, String> metadata) {
-    Path file = moduleHierarchy.root().getWorkDir().resolve(METADATA_DUMP_FILENAME);
-    try (Writer output = Files.newBufferedWriter(file, StandardCharsets.UTF_8)) {
-      for (Map.Entry<String, String> entry : metadata.entrySet()) {
-        output.write(entry.getKey());
-        output.write("=");
-        output.write(entry.getValue());
-        output.write("\n");
+    Path file = properties.metadataFilePath();
+    try {
+      Files.createDirectories(file.getParent());
+      try (Writer output = Files.newBufferedWriter(file, StandardCharsets.UTF_8)) {
+        for (Map.Entry<String, String> entry : metadata.entrySet()) {
+          output.write(entry.getKey());
+          output.write("=");
+          output.write(entry.getValue());
+          output.write("\n");
+        }
       }
 
       LOG.debug("Report metadata written to {}", file);
index d8b31de23936c64a7b26fe0da840b671e151b671..0b2be6f39e9251b4c11056f843d4cb6655f551c9 100644 (file)
@@ -25,30 +25,27 @@ import java.util.ArrayList;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Optional;
 import java.util.function.BinaryOperator;
 import javax.annotation.Nullable;
-import org.apache.commons.io.IOUtils;
-import org.sonar.api.config.Configuration;
 import org.sonar.api.utils.MessageException;
 import org.sonar.scanner.bootstrap.ScannerWsClient;
+import org.sonar.scanner.scan.ScanProperties;
 import org.sonarqube.ws.Qualityprofiles.SearchWsResponse;
 import org.sonarqube.ws.Qualityprofiles.SearchWsResponse.QualityProfile;
 import org.sonarqube.ws.client.GetRequest;
 
 import static java.util.function.Function.identity;
 import static java.util.stream.Collectors.toMap;
-import static org.sonar.core.config.ScannerProperties.ORGANIZATION;
 import static org.sonar.scanner.util.ScannerUtils.encodeForUrl;
 
 public class DefaultQualityProfileLoader implements QualityProfileLoader {
   private static final String WS_URL = "/api/qualityprofiles/search.protobuf";
 
-  private final Configuration settings;
   private final ScannerWsClient wsClient;
+  private final ScanProperties properties;
 
-  public DefaultQualityProfileLoader(Configuration settings, ScannerWsClient wsClient) {
-    this.settings = settings;
+  public DefaultQualityProfileLoader(ScanProperties properties, ScannerWsClient wsClient) {
+    this.properties = properties;
     this.wsClient = wsClient;
   }
 
@@ -65,13 +62,13 @@ public class DefaultQualityProfileLoader implements QualityProfileLoader {
   }
 
   private List<QualityProfile> loadAndOverrideIfNeeded(@Nullable String profileName, StringBuilder url) {
-    getOrganizationKey().ifPresent(k -> url.append("&organization=").append(encodeForUrl(k)));
+    properties.organizationKey().ifPresent(k -> url.append("&organization=").append(encodeForUrl(k)));
     Map<String, QualityProfile> result = call(url.toString());
 
     if (profileName != null) {
       StringBuilder urlForName = new StringBuilder(WS_URL + "?profileName=");
       urlForName.append(encodeForUrl(profileName));
-      getOrganizationKey().ifPresent(k -> urlForName.append("&organization=").append(encodeForUrl(k)));
+      properties.organizationKey().ifPresent(k -> urlForName.append("&organization=").append(encodeForUrl(k)));
       result.putAll(call(urlForName.toString()));
     }
     if (result.isEmpty()) {
@@ -81,26 +78,16 @@ public class DefaultQualityProfileLoader implements QualityProfileLoader {
     return new ArrayList<>(result.values());
   }
 
-  private Optional<String> getOrganizationKey() {
-    return settings.get(ORGANIZATION);
-  }
-
   private Map<String, QualityProfile> call(String url) {
     GetRequest getRequest = new GetRequest(url);
-    InputStream is = wsClient.call(getRequest).contentStream();
-    SearchWsResponse profiles;
-
-    try {
-      profiles = SearchWsResponse.parseFrom(is);
+    try (InputStream is = wsClient.call(getRequest).contentStream()) {
+      SearchWsResponse profiles = SearchWsResponse.parseFrom(is);
+      List<QualityProfile> profilesList = profiles.getProfilesList();
+      return profilesList.stream().collect(toMap(QualityProfile::getLanguage, identity(), throwingMerger(), LinkedHashMap::new));
     } catch (IOException e) {
       throw new IllegalStateException("Failed to load quality profiles", e);
-    } finally {
-      IOUtils.closeQuietly(is);
     }
 
-    List<QualityProfile> profilesList = profiles.getProfilesList();
-    return profilesList.stream()
-      .collect(toMap(QualityProfile::getLanguage, identity(), throwingMerger(), LinkedHashMap::new));
   }
 
   private static <T> BinaryOperator<T> throwingMerger() {
index c81845047b1ddea46d810c2a779590d91a0e98db..a44ac36b0ec53b42f577f2b44bd323e0bb66966d 100644 (file)
@@ -134,6 +134,7 @@ public class ProjectScanContainer extends ComponentContainer {
     add(
       props,
       ProjectReactorBuilder.class,
+      ScanProperties.class,
       WorkDirectoriesInitializer.class,
       new MutableProjectReactorProvider(),
       ProjectBuildersExecutor.class,
@@ -197,6 +198,7 @@ public class ProjectScanContainer extends ComponentContainer {
       SensorStrategy.class,
 
       MutableProjectSettings.class,
+      ScannerProperties.class,
       new ProjectSettingsProvider(),
 
       // Report
@@ -244,13 +246,13 @@ public class ProjectScanContainer extends ComponentContainer {
   protected void doAfterStart() {
     GlobalAnalysisMode analysisMode = getComponentByType(GlobalAnalysisMode.class);
     InputModuleHierarchy tree = getComponentByType(InputModuleHierarchy.class);
+    ScanProperties properties = getComponentByType(ScanProperties.class);
+    properties.validate();
 
     LOG.info("Project key: {}", tree.root().key());
     LOG.info("Project base dir: {}", tree.root().getBaseDir());
-    String organization = props.property("sonar.organization");
-    if (StringUtils.isNotEmpty(organization)) {
-      LOG.info("Organization key: {}", organization);
-    }
+    properties.organizationKey().ifPresent(k -> LOG.info("Organization key: {}", k));
+    
     String branch = tree.root().definition().getBranch();
     if (branch != null) {
       LOG.info("Branch key: {}", branch);
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ScanProperties.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ScanProperties.java
new file mode 100644 (file)
index 0000000..e7cd97e
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.scanner.scan;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Optional;
+import org.sonar.api.batch.ScannerSide;
+import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
+import org.sonar.api.config.Configuration;
+import org.sonar.api.utils.MessageException;
+
+import static org.sonar.core.config.ScannerProperties.BRANCH_NAME;
+import static org.sonar.core.config.ScannerProperties.ORGANIZATION;
+
+/**
+ * Properties that can be passed to the scanners and are not exposed in SonarQube.
+ */
+@ScannerSide
+public class ScanProperties {
+  public static final String METADATA_FILE_PATH_KEY = "sonar.scanner.metadataFilePath";
+  public static final String KEEP_REPORT_PROP_KEY = "sonar.scanner.keepReport";
+  public static final String VERBOSE_KEY = "sonar.verbose";
+  public static final String METADATA_DUMP_FILENAME = "report-task.txt";
+  public static final String SONAR_REPORT_EXPORT_PATH = "sonar.report.export.path";
+  public static final String PRELOAD_FILE_METADATA_KEY = "sonar.preloadFileMetadata";
+  public static final String FORCE_RELOAD_KEY = "sonar.scm.forceReloadAll";
+
+  private final Configuration configuration;
+  private final InputModuleHierarchy moduleHierarchy;
+
+  public ScanProperties(Configuration configuration, InputModuleHierarchy moduleHierarchy) {
+    this.configuration = configuration;
+    this.moduleHierarchy = moduleHierarchy;
+  }
+
+  public boolean shouldKeepReport() {
+    return configuration.getBoolean(KEEP_REPORT_PROP_KEY).orElse(false) || configuration.getBoolean(VERBOSE_KEY).orElse(false);
+  }
+
+  public boolean preloadFileMetadata() {
+    return configuration.getBoolean(PRELOAD_FILE_METADATA_KEY).orElse(false);
+  }
+
+  public Optional<String> organizationKey() {
+    return configuration.get(ORGANIZATION);
+  }
+
+  public Optional<String> branch() {
+    return configuration.get(BRANCH_NAME);
+  }
+
+  public Path metadataFilePath() {
+    Optional<String> metadataFilePath = configuration.get(METADATA_FILE_PATH_KEY);
+    if (metadataFilePath.isPresent()) {
+      Path metadataPath = Paths.get(metadataFilePath.get());
+      if (!metadataPath.isAbsolute()) {
+        throw MessageException.of(String.format("Property '%s' must point to an absolute path: %s", METADATA_FILE_PATH_KEY, metadataFilePath.get()));
+      }
+      return moduleHierarchy.root().getBaseDir().resolve(metadataPath);
+    } else {
+      return moduleHierarchy.root().getWorkDir().resolve(METADATA_DUMP_FILENAME);
+    }
+  }
+
+  /**
+   * This should be called in the beginning of the analysis to fail fast
+   */
+  public void validate() {
+    metadataFilePath();
+  }
+}
index 33e3bcbf3d180eb57375463f3245e326a62678f5..b6bf1899b6fab560d82b9986744d3e01f394c48b 100644 (file)
@@ -27,11 +27,10 @@ import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
 import org.sonar.api.batch.fs.internal.SensorStrategy;
-import org.sonar.api.config.Configuration;
 import org.sonar.api.utils.PathUtils;
+import org.sonar.scanner.scan.ScanProperties;
 
 public class InputFileBuilder {
-  public static final String PRELOAD_FILE_METADATA_KEY = "sonar.preloadFileMetadata";
   private final String moduleKey;
   private final Path moduleBaseDir;
   private final BatchIdGenerator idGenerator;
@@ -42,7 +41,8 @@ public class InputFileBuilder {
   private final SensorStrategy sensorStrategy;
 
   public InputFileBuilder(DefaultInputModule module, MetadataGenerator metadataGenerator,
-    BatchIdGenerator idGenerator, Configuration settings, ModuleFileSystemInitializer moduleFileSystemInitializer, InputModuleHierarchy hierarchy, SensorStrategy sensorStrategy) {
+    BatchIdGenerator idGenerator, ScanProperties properties, ModuleFileSystemInitializer moduleFileSystemInitializer, InputModuleHierarchy hierarchy,
+    SensorStrategy sensorStrategy) {
     this.sensorStrategy = sensorStrategy;
     this.projectBaseDir = hierarchy.root().getBaseDir();
     this.moduleFileSystemInitializer = moduleFileSystemInitializer;
@@ -50,7 +50,7 @@ public class InputFileBuilder {
     this.moduleBaseDir = module.getBaseDir();
     this.metadataGenerator = metadataGenerator;
     this.idGenerator = idGenerator;
-    this.preloadMetadata = settings.getBoolean(PRELOAD_FILE_METADATA_KEY).orElse(false);
+    this.preloadMetadata = properties.preloadFileMetadata();
   }
 
   DefaultInputFile create(InputFile.Type type, Path absolutePath, @Nullable String language) {
index eb28ba1a3d078bf59ca2bdfb636d23c9a34395b1..896df5554312ef40299b70d6db728208e04fd4b7 100644 (file)
@@ -53,6 +53,7 @@ import org.sonar.api.utils.DateUtils;
 import org.sonar.batch.bootstrapper.Batch;
 import org.sonar.batch.bootstrapper.EnvironmentInformation;
 import org.sonar.batch.bootstrapper.LogOutput;
+import org.sonar.core.config.ScannerProperties;
 import org.sonar.scanner.bootstrap.GlobalAnalysisMode;
 import org.sonar.scanner.issue.tracking.ServerLineHashesLoader;
 import org.sonar.scanner.protocol.input.ScannerInput.ServerIssue;
@@ -68,6 +69,7 @@ import org.sonar.scanner.repository.settings.SettingsLoader;
 import org.sonar.scanner.rule.ActiveRulesLoader;
 import org.sonar.scanner.rule.LoadedActiveRule;
 import org.sonar.scanner.rule.RulesLoader;
+import org.sonar.scanner.scan.ScanProperties;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
 import org.sonar.scanner.scan.branch.BranchConfigurationLoader;
 import org.sonar.scanner.scan.branch.BranchType;
@@ -243,7 +245,7 @@ public class ScannerMediumTester extends ExternalResource {
     }
     registerCoreMetrics();
     globalProperties.put(GlobalAnalysisMode.MEDIUM_TEST_ENABLED, "true");
-    globalProperties.put(ReportPublisher.KEEP_REPORT_PROP_KEY, "true");
+    globalProperties.put(ScanProperties.KEEP_REPORT_PROP_KEY, "true");
     globalProperties.put("sonar.userHome", userHome.toString());
   }
 
index f8af70d532c7a5a09d6749cece63acade652fa8e..46290e6a4bf558ca71857061a9fb6d2ae28aefbc 100644 (file)
@@ -25,6 +25,7 @@ import java.io.IOException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Date;
+import java.util.Optional;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -46,6 +47,7 @@ import org.sonar.scanner.protocol.output.ScannerReportReader;
 import org.sonar.scanner.protocol.output.ScannerReportWriter;
 import org.sonar.scanner.rule.ModuleQProfiles;
 import org.sonar.scanner.rule.QProfile;
+import org.sonar.scanner.scan.ScanProperties;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
 import org.sonar.scanner.scan.branch.BranchType;
 import org.sonar.scanner.scm.ScmConfiguration;
@@ -65,26 +67,19 @@ public class MetadataPublisherTest {
 
   private DefaultInputModule rootModule;
   private MetadataPublisher underTest;
-  private MapSettings settings;
-  private ModuleQProfiles qProfiles;
-  private ProjectAnalysisInfo projectAnalysisInfo;
-  private CpdSettings cpdSettings;
+  private ScanProperties properties = mock(ScanProperties.class);
+  private ModuleQProfiles qProfiles = mock(ModuleQProfiles.class);
+  private ProjectAnalysisInfo projectAnalysisInfo = mock(ProjectAnalysisInfo.class);
+  private CpdSettings cpdSettings = mock(CpdSettings.class);
   private InputModuleHierarchy inputModuleHierarchy;
-  private ScannerPluginRepository pluginRepository;
+  private ScannerPluginRepository pluginRepository = mock(ScannerPluginRepository.class);
   private BranchConfiguration branches;
   private ScmConfiguration scmConfiguration;
-  private ScmProvider scmProvider;
+  private ScmProvider scmProvider = mock(ScmProvider.class);
 
   @Before
   public void prepare() throws IOException {
-    projectAnalysisInfo = mock(ProjectAnalysisInfo.class);
-    cpdSettings = mock(CpdSettings.class);
     when(projectAnalysisInfo.analysisDate()).thenReturn(new Date(1234567L));
-    settings = new MapSettings();
-    qProfiles = mock(ModuleQProfiles.class);
-    pluginRepository = mock(ScannerPluginRepository.class);
-
-    scmProvider = mock(ScmProvider.class);
     when(scmProvider.relativePathFromScmRoot(any(Path.class))).thenReturn(Paths.get("dummy/path"));
     when(scmProvider.revisionId(any(Path.class))).thenReturn("dummy-sha1");
 
@@ -99,13 +94,12 @@ public class MetadataPublisherTest {
     branches = mock(BranchConfiguration.class);
     scmConfiguration = mock(ScmConfiguration.class);
     when(scmConfiguration.provider()).thenReturn(scmProvider);
-    underTest = new MetadataPublisher(projectAnalysisInfo, inputModuleHierarchy, settings.asConfig(), qProfiles, cpdSettings,
+    underTest = new MetadataPublisher(projectAnalysisInfo, inputModuleHierarchy, properties, qProfiles, cpdSettings,
       pluginRepository, branches, scmConfiguration);
   }
 
   @Test
   public void write_metadata() throws Exception {
-    settings.setProperty(CoreProperties.CPD_CROSS_PROJECT, "true");
     Date date = new Date();
     when(qProfiles.findAll()).thenReturn(asList(new QProfile("q1", "Q1", "java", date)));
     when(pluginRepository.getPluginsByKey()).thenReturn(ImmutableMap.of(
@@ -140,8 +134,6 @@ public class MetadataPublisherTest {
   @Test
   public void write_project_branch() throws Exception {
     when(cpdSettings.isCrossProjectDuplicationEnabled()).thenReturn(false);
-    settings.setProperty(CoreProperties.CPD_CROSS_PROJECT, "true");
-    settings.setProperty(CoreProperties.PROJECT_BRANCH_PROPERTY, "myBranch");
 
     ProjectDefinition projectDef = ProjectDefinition.create()
       .setKey("foo")
@@ -163,7 +155,7 @@ public class MetadataPublisherTest {
 
   @Test
   public void write_project_organization() throws Exception {
-    settings.setProperty(ScannerProperties.ORGANIZATION, "SonarSource");
+    when(properties.organizationKey()).thenReturn(Optional.of("SonarSource"));
 
     File outputDir = temp.newFolder();
     ScannerReportWriter writer = new ScannerReportWriter(outputDir);
@@ -172,7 +164,7 @@ public class MetadataPublisherTest {
 
     ScannerReportReader reader = new ScannerReportReader(outputDir);
     ScannerReport.Metadata metadata = reader.readMetadata();
-    assertThat(metadata.getOrganizationKey()).isEqualTo("SonarSource");
+    assertThat(properties.organizationKey()).isEqualTo(Optional.of("SonarSource"));
   }
 
   @Test
index 9213c5d0146e5bb64b62fe029838654a57eb488a..43293b246e127fe6552a32afbd5ff3ceac6b31ec 100644 (file)
  */
 package org.sonar.scanner.report;
 
-import java.io.File;
 import java.io.IOException;
 import java.io.PipedInputStream;
 import java.io.PipedOutputStream;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.util.Optional;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -35,17 +36,14 @@ import org.mockito.Mockito;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
 import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
-import org.sonar.api.config.PropertyDefinitions;
-import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.platform.Server;
 import org.sonar.api.utils.MessageException;
 import org.sonar.api.utils.TempFolder;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
-import org.sonar.core.config.CorePropertyDefinitions;
-import org.sonar.core.config.ScannerProperties;
 import org.sonar.scanner.bootstrap.GlobalAnalysisMode;
 import org.sonar.scanner.bootstrap.ScannerWsClient;
+import org.sonar.scanner.scan.ScanProperties;
 import org.sonar.scanner.scan.branch.BranchConfiguration;
 import org.sonarqube.ws.Ce;
 import org.sonarqube.ws.client.HttpException;
@@ -54,7 +52,6 @@ import org.sonarqube.ws.client.WsResponse;
 
 import static org.apache.commons.io.FileUtils.readFileToString;
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.entry;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
@@ -75,29 +72,30 @@ public class ReportPublisherTest {
   public ExpectedException exception = ExpectedException.none();
 
   GlobalAnalysisMode mode = mock(GlobalAnalysisMode.class);
-  MapSettings settings = new MapSettings(new PropertyDefinitions(CorePropertyDefinitions.all()));
-  ScannerWsClient wsClient;
+  ScanProperties properties = mock(ScanProperties.class);
+  ScannerWsClient wsClient = mock(ScannerWsClient.class, Mockito.RETURNS_DEEP_STUBS);
   Server server = mock(Server.class);
   InputModuleHierarchy moduleHierarchy = mock(InputModuleHierarchy.class);
   DefaultInputModule root;
   AnalysisContextReportPublisher contextPublisher = mock(AnalysisContextReportPublisher.class);
   BranchConfiguration branchConfiguration = mock(BranchConfiguration.class);
+  ReportPublisher underTest = new ReportPublisher(properties, wsClient, server, contextPublisher, moduleHierarchy, mode, mock(TempFolder.class),
+    new ReportPublisherStep[0], branchConfiguration);
 
   @Before
   public void setUp() throws IOException {
-    wsClient = mock(ScannerWsClient.class, Mockito.RETURNS_DEEP_STUBS);
     root = new DefaultInputModule(ProjectDefinition.create().setKey("org.sonarsource.sonarqube:sonarqube").setBaseDir(temp.newFolder()).setWorkDir(temp.getRoot()));
     when(moduleHierarchy.root()).thenReturn(root);
     when(server.getPublicRootUrl()).thenReturn("https://localhost");
     when(server.getVersion()).thenReturn("6.4");
+    when(properties.metadataFilePath()).thenReturn(temp.newFolder().toPath()
+      .resolve("folder")
+      .resolve("report-task.txt"));
   }
 
   @Test
   public void log_and_dump_information_about_report_uploading() throws IOException {
-    ReportPublisher underTest = new ReportPublisher(settings.asConfig(), wsClient, server, contextPublisher, moduleHierarchy, mode,
-      mock(TempFolder.class), new ReportPublisherStep[0], branchConfiguration);
-    settings.setProperty(ScannerProperties.ORGANIZATION, "MyOrg");
-
+    when(properties.organizationKey()).thenReturn(Optional.of("MyOrg"));
     underTest.logSuccess("TASK-123");
 
     assertThat(logTester.logs(LoggerLevel.INFO))
@@ -105,8 +103,7 @@ public class ReportPublisherTest {
       .contains("Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report")
       .contains("More about the report processing at https://localhost/api/ce/task?id=TASK-123");
 
-    File detailsFile = new File(temp.getRoot(), "report-task.txt");
-    assertThat(readFileToString(detailsFile)).isEqualTo(
+    assertThat(readFileToString(properties.metadataFilePath().toFile(), StandardCharsets.UTF_8)).isEqualTo(
       "organization=MyOrg\n" +
         "projectKey=org.sonarsource.sonarqube:sonarqube\n" +
         "serverUrl=https://localhost\n" +
@@ -118,8 +115,6 @@ public class ReportPublisherTest {
 
   @Test
   public void parse_upload_error_message() throws IOException {
-    ReportPublisher underTest = new ReportPublisher(settings.asConfig(), wsClient, server, contextPublisher, moduleHierarchy, mode,
-      mock(TempFolder.class), new ReportPublisherStep[0], branchConfiguration);
     HttpException ex = new HttpException("url", 404, "{\"errors\":[{\"msg\":\"Organization with key 'MyOrg' does not exist\"}]}");
     WsResponse response = mock(WsResponse.class);
     when(response.failIfNotSuccessful()).thenThrow(ex);
@@ -133,8 +128,6 @@ public class ReportPublisherTest {
   @Test
   public void log_public_url_if_defined_for_main_branch() throws IOException {
     when(server.getPublicRootUrl()).thenReturn("https://publicserver/sonarqube");
-    ReportPublisher underTest = new ReportPublisher(settings.asConfig(), wsClient, server, contextPublisher, moduleHierarchy, mode, mock(TempFolder.class),
-      new ReportPublisherStep[0], branchConfiguration);
 
     underTest.logSuccess("TASK-123");
 
@@ -142,8 +135,7 @@ public class ReportPublisherTest {
       .contains("ANALYSIS SUCCESSFUL, you can browse https://publicserver/sonarqube/dashboard?id=org.sonarsource.sonarqube%3Asonarqube")
       .contains("More about the report processing at https://publicserver/sonarqube/api/ce/task?id=TASK-123");
 
-    File detailsFile = new File(temp.getRoot(), "report-task.txt");
-    assertThat(readFileToString(detailsFile)).isEqualTo(
+    assertThat(readFileToString(properties.metadataFilePath().toFile(), StandardCharsets.UTF_8)).isEqualTo(
       "projectKey=org.sonarsource.sonarqube:sonarqube\n" +
         "serverUrl=https://publicserver/sonarqube\n" +
         "serverVersion=6.4\n" +
@@ -157,7 +149,7 @@ public class ReportPublisherTest {
     when(server.getPublicRootUrl()).thenReturn("https://publicserver/sonarqube");
     when(branchConfiguration.branchType()).thenReturn(LONG);
     when(branchConfiguration.branchName()).thenReturn("branch-6.7");
-    ReportPublisher underTest = new ReportPublisher(settings.asConfig(), wsClient, server, contextPublisher, moduleHierarchy, mode, mock(TempFolder.class),
+    ReportPublisher underTest = new ReportPublisher(properties, wsClient, server, contextPublisher, moduleHierarchy, mode, mock(TempFolder.class),
       new ReportPublisherStep[0], branchConfiguration);
 
     underTest.logSuccess("TASK-123");
@@ -165,8 +157,7 @@ public class ReportPublisherTest {
       .contains("ANALYSIS SUCCESSFUL, you can browse https://publicserver/sonarqube/dashboard?id=org.sonarsource.sonarqube%3Asonarqube&branch=branch-6.7")
       .contains("More about the report processing at https://publicserver/sonarqube/api/ce/task?id=TASK-123");
 
-    File detailsFile = new File(temp.getRoot(), "report-task.txt");
-    assertThat(readFileToString(detailsFile)).isEqualTo(
+    assertThat(readFileToString(properties.metadataFilePath().toFile(), StandardCharsets.UTF_8)).isEqualTo(
       "projectKey=org.sonarsource.sonarqube:sonarqube\n" +
         "serverUrl=https://publicserver/sonarqube\n" +
         "serverVersion=6.4\n" +
@@ -180,7 +171,7 @@ public class ReportPublisherTest {
     when(server.getPublicRootUrl()).thenReturn("https://publicserver/sonarqube");
     when(branchConfiguration.branchType()).thenReturn(SHORT);
     when(branchConfiguration.branchName()).thenReturn("branch-6.7");
-    ReportPublisher underTest = new ReportPublisher(settings.asConfig(), wsClient, server, contextPublisher, moduleHierarchy, mode, mock(TempFolder.class),
+    ReportPublisher underTest = new ReportPublisher(properties, wsClient, server, contextPublisher, moduleHierarchy, mode, mock(TempFolder.class),
       new ReportPublisherStep[0], branchConfiguration);
 
     underTest.logSuccess("TASK-123");
@@ -188,8 +179,7 @@ public class ReportPublisherTest {
       .contains("ANALYSIS SUCCESSFUL, you can browse https://publicserver/sonarqube/dashboard?id=org.sonarsource.sonarqube%3Asonarqube&branch=branch-6.7&resolved=false")
       .contains("More about the report processing at https://publicserver/sonarqube/api/ce/task?id=TASK-123");
 
-    File detailsFile = new File(temp.getRoot(), "report-task.txt");
-    assertThat(readFileToString(detailsFile)).isEqualTo(
+    assertThat(readFileToString(properties.metadataFilePath().toFile(), StandardCharsets.UTF_8)).isEqualTo(
       "projectKey=org.sonarsource.sonarqube:sonarqube\n" +
         "serverUrl=https://publicserver/sonarqube\n" +
         "serverVersion=6.4\n" +
@@ -205,7 +195,7 @@ public class ReportPublisherTest {
     when(branchConfiguration.branchType()).thenReturn(PULL_REQUEST);
     when(branchConfiguration.pullRequestKey()).thenReturn("105");
 
-    ReportPublisher underTest = new ReportPublisher(settings.asConfig(), wsClient, server, contextPublisher, moduleHierarchy, mode, mock(TempFolder.class),
+    ReportPublisher underTest = new ReportPublisher(properties, wsClient, server, contextPublisher, moduleHierarchy, mode, mock(TempFolder.class),
       new ReportPublisherStep[0], branchConfiguration);
 
     underTest.logSuccess("TASK-123");
@@ -214,8 +204,7 @@ public class ReportPublisherTest {
       .contains("ANALYSIS SUCCESSFUL, you can browse https://publicserver/sonarqube/project/issues?id=org.sonarsource.sonarqube%3Asonarqube&pullRequest=105&resolved=false")
       .contains("More about the report processing at https://publicserver/sonarqube/api/ce/task?id=TASK-123");
 
-    File detailsFile = new File(temp.getRoot(), "report-task.txt");
-    assertThat(readFileToString(detailsFile)).isEqualTo(
+    assertThat(readFileToString(properties.metadataFilePath().toFile(), StandardCharsets.UTF_8)).isEqualTo(
       "projectKey=org.sonarsource.sonarqube:sonarqube\n" +
         "serverUrl=https://publicserver/sonarqube\n" +
         "serverVersion=6.4\n" +
@@ -227,8 +216,6 @@ public class ReportPublisherTest {
   @Test
   public void fail_if_public_url_malformed() {
     when(server.getPublicRootUrl()).thenReturn("invalid");
-    ReportPublisher underTest = new ReportPublisher(settings.asConfig(), wsClient, server, contextPublisher, moduleHierarchy, mode, mock(TempFolder.class),
-      new ReportPublisherStep[0], branchConfiguration);
 
     exception.expect(MessageException.class);
     exception.expectMessage("Failed to parse public URL set in SonarQube server: invalid");
@@ -236,27 +223,29 @@ public class ReportPublisherTest {
   }
 
   @Test
-  public void log_but_not_dump_information_when_report_is_not_uploaded() {
-    ReportPublisher underTest = new ReportPublisher(settings.asConfig(), wsClient, server, contextPublisher, moduleHierarchy, mode, mock(TempFolder.class),
-      new ReportPublisherStep[0], branchConfiguration);
-
+  public void log_but_not_dump_information_when_report_is_not_uploaded() throws IOException {
     underTest.logSuccess(/* report not uploaded, no server task */null);
 
     assertThat(logTester.logs(LoggerLevel.INFO))
       .contains("ANALYSIS SUCCESSFUL")
       .doesNotContain("dashboard/index");
 
-    File detailsFile = new File(temp.getRoot(), ReportPublisher.METADATA_DUMP_FILENAME);
-    assertThat(detailsFile).doesNotExist();
+    assertThat(properties.metadataFilePath()).doesNotExist();
+  }
+
+  @Test
+  public void log_and_dump_information_to_custom_path() throws IOException {
+    underTest.logSuccess("TASK-123");
+
+    assertThat(properties.metadataFilePath()).exists();
+    assertThat(logTester.logs(LoggerLevel.DEBUG)).contains("Report metadata written to " + properties.metadataFilePath());
   }
 
   @Test
   public void should_not_delete_report_if_property_is_set() throws IOException {
-    settings.setProperty("sonar.scanner.keepReport", true);
+    when(properties.shouldKeepReport()).thenReturn(true);
     Path reportDir = temp.getRoot().toPath().resolve("scanner-report");
     Files.createDirectory(reportDir);
-    ReportPublisher underTest = new ReportPublisher(settings.asConfig(), wsClient, server, contextPublisher, moduleHierarchy, mode, mock(TempFolder.class),
-      new ReportPublisherStep[0], branchConfiguration);
 
     underTest.start();
     underTest.stop();
@@ -267,21 +256,15 @@ public class ReportPublisherTest {
   public void should_delete_report_by_default() throws IOException {
     Path reportDir = temp.getRoot().toPath().resolve("scanner-report");
     Files.createDirectory(reportDir);
-    ReportPublisher job = new ReportPublisher(settings.asConfig(), wsClient, server, contextPublisher, moduleHierarchy, mode, mock(TempFolder.class),
-      new ReportPublisherStep[0],
-      branchConfiguration);
 
-    job.start();
-    job.stop();
+    underTest.start();
+    underTest.stop();
     assertThat(reportDir).doesNotExist();
   }
 
   @Test
   public void test_ws_parameters() throws Exception {
-    ReportPublisher underTest = new ReportPublisher(settings.asConfig(), wsClient, server, contextPublisher, moduleHierarchy, mode, mock(TempFolder.class),
-      new ReportPublisherStep[0], branchConfiguration);
-
-    settings.setProperty(ScannerProperties.ORGANIZATION, "MyOrg");
+    when(properties.organizationKey()).thenReturn(Optional.of("MyOrg"));
 
     WsResponse response = mock(WsResponse.class);
 
@@ -300,18 +283,15 @@ public class ReportPublisherTest {
     verify(wsClient).call(capture.capture());
 
     WsRequest wsRequest = capture.getValue();
-    assertThat(wsRequest.getParams()).containsOnly(
-      entry("organization", "MyOrg"),
-      entry("projectKey", "org.sonarsource.sonarqube:sonarqube"));
+    assertThat(wsRequest.getParameters().getKeys()).containsOnly("organization", "projectKey");
+    assertThat(wsRequest.getParameters().getValue("organization")).isEqualTo("MyOrg");
+    assertThat(wsRequest.getParameters().getValue("projectKey")).isEqualTo("org.sonarsource.sonarqube:sonarqube");
   }
 
   @Test
   public void test_send_branches_characteristics() throws Exception {
-    ReportPublisher underTest = new ReportPublisher(settings.asConfig(), wsClient, server, contextPublisher, moduleHierarchy, mode, mock(TempFolder.class),
-      new ReportPublisherStep[0], branchConfiguration);
-
     String orgName = "MyOrg";
-    settings.setProperty(ScannerProperties.ORGANIZATION, orgName);
+    when(properties.organizationKey()).thenReturn(Optional.of(orgName));
 
     String branchName = "feature";
     when(branchConfiguration.branchName()).thenReturn(branchName);
@@ -343,11 +323,8 @@ public class ReportPublisherTest {
 
   @Test
   public void send_pull_request_characteristic() throws Exception {
-    ReportPublisher underTest = new ReportPublisher(settings.asConfig(), wsClient, server, contextPublisher, moduleHierarchy, mode, mock(TempFolder.class),
-      new ReportPublisherStep[0], branchConfiguration);
-
     String orgName = "MyOrg";
-    settings.setProperty(ScannerProperties.ORGANIZATION, orgName);
+    when(properties.organizationKey()).thenReturn(Optional.of(orgName));
 
     String branchName = "feature";
     String pullRequestId = "pr-123";
index c37dd15b17344904b9969801acaffdb1fb2ed373..b1786ef3ad92eae649c77f4540b9eed07252fd14 100644 (file)
@@ -23,26 +23,28 @@ import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Optional;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.utils.MessageException;
 import org.sonar.scanner.WsTestUtil;
 import org.sonar.scanner.bootstrap.ScannerWsClient;
+import org.sonar.scanner.scan.ScanProperties;
 import org.sonarqube.ws.Qualityprofiles;
 import org.sonarqube.ws.Qualityprofiles.SearchWsResponse.QualityProfile;
 
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
 
 public class DefaultQualityProfileLoaderTest {
   @Rule
   public ExpectedException exception = ExpectedException.none();
 
   private ScannerWsClient wsClient = mock(ScannerWsClient.class);
-  private MapSettings settings = new MapSettings();
-  private DefaultQualityProfileLoader underTest = new DefaultQualityProfileLoader(settings.asConfig(), wsClient);
+  private ScanProperties properties = mock(ScanProperties.class);
+  private DefaultQualityProfileLoader underTest = new DefaultQualityProfileLoader(properties, wsClient);
 
   @Test
   public void load_gets_profiles_for_specified_project_and_profile_name() throws IOException {
@@ -71,7 +73,7 @@ public class DefaultQualityProfileLoaderTest {
 
   @Test
   public void load_sets_organization_parameter_if_defined_in_settings() throws IOException {
-    settings.setProperty("sonar.organization", "my-org");
+    when(properties.organizationKey()).thenReturn(Optional.of("my-org"));
     prepareCallWithResults();
     underTest.load("foo", null);
     verifyCalledPath("/api/qualityprofiles/search.protobuf?projectKey=foo&organization=my-org");
@@ -95,7 +97,7 @@ public class DefaultQualityProfileLoaderTest {
 
   @Test
   public void loadDefault_sets_organization_parameter_if_defined_in_settings() throws IOException {
-    settings.setProperty("sonar.organization", "my-org");
+    when(properties.organizationKey()).thenReturn(Optional.of("my-org"));
     WsTestUtil.mockStream(wsClient, "/api/qualityprofiles/search.protobuf?defaults=true&organization=my-org", createStreamOfProfiles("qp"));
     WsTestUtil.mockStream(wsClient, "/api/qualityprofiles/search.protobuf?profileName=foo&organization=my-org", createStreamOfProfiles("qp"));
     underTest.loadDefault("foo");
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ScanPropertiesTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ScanPropertiesTest.java
new file mode 100644 (file)
index 0000000..01fe698
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.scanner.scan;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Optional;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
+import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.utils.MessageException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class ScanPropertiesTest {
+  private MapSettings settings = new MapSettings();
+  private InputModuleHierarchy inputModuleHierarchy = mock(InputModuleHierarchy.class);
+  private ScanProperties underTest = new ScanProperties(settings.asConfig(), inputModuleHierarchy);
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+  
+  @Rule
+  public ExpectedException exception = ExpectedException.none();
+
+  @Before
+  public void setUp() throws IOException {
+    DefaultInputModule root = mock(DefaultInputModule.class);
+    when(root.getBaseDir()).thenReturn(temp.newFolder().toPath());
+    when(root.getWorkDir()).thenReturn(temp.newFolder().toPath());
+    when(inputModuleHierarchy.root()).thenReturn(root);
+  }
+
+  @Test
+  public void defaults_if_no_setting_defined() {
+    assertThat(underTest.branch()).isEmpty();
+    assertThat(underTest.organizationKey()).isEmpty();
+    assertThat(underTest.preloadFileMetadata()).isFalse();
+    assertThat(underTest.shouldKeepReport()).isFalse();
+    assertThat(underTest.metadataFilePath()).isEqualTo(inputModuleHierarchy.root().getWorkDir().resolve("report-task.txt"));
+    underTest.validate();
+  }
+
+  @Test
+  public void should_define_organization_key() {
+    settings.setProperty("sonar.organization", "org");
+    assertThat(underTest.organizationKey()).isEqualTo(Optional.of("org"));
+  }
+  
+  @Test
+  public void should_define_branch_name() {
+    settings.setProperty("sonar.branch.name", "name");
+    assertThat(underTest.branch()).isEqualTo(Optional.of("name"));
+  }
+  
+  @Test
+  public void should_define_preload_file_metadata() {
+    settings.setProperty("sonar.preloadFileMetadata", "true");
+    assertThat(underTest.preloadFileMetadata()).isTrue();
+  }
+  
+  @Test
+  public void should_define_keep_report() {
+    settings.setProperty("sonar.scanner.keepReport", "true");
+    assertThat(underTest.shouldKeepReport()).isTrue();
+  }
+  
+  @Test
+  public void should_define_metadata_file_path() throws IOException {
+    Path path = temp.newFolder().toPath().resolve("report");
+    settings.setProperty("sonar.scanner.metadataFilePath", path.toString());
+    assertThat(underTest.metadataFilePath()).isEqualTo(path);
+  }
+  
+  @Test
+  public void validate_fails_if_metadata_file_location_is_not_absolute() {
+    settings.setProperty("sonar.scanner.metadataFilePath", "relative");
+
+    exception.expect(MessageException.class);
+    exception.expectMessage("Property 'sonar.scanner.metadataFilePath' must point to an absolute path: relative");
+    underTest.validate();
+
+  }
+}
index 38315790c36ee7714d187bd09a706e9f61a7965d..580a0ac6d7bcfde463455cb79e5a8684063be29f 100644 (file)
@@ -34,6 +34,7 @@ import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.api.batch.fs.internal.SensorStrategy;
 import org.sonar.api.config.internal.MapSettings;
 import org.sonar.scanner.scan.DefaultInputModuleHierarchy;
+import org.sonar.scanner.scan.ScanProperties;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
@@ -66,11 +67,11 @@ public class InputFileBuilderTest {
 
     MetadataGenerator metadataGenerator = mock(MetadataGenerator.class);
     BatchIdGenerator idGenerator = new BatchIdGenerator();
-    MapSettings settings = new MapSettings();
+    ScanProperties properties = mock(ScanProperties.class);
     ModuleFileSystemInitializer moduleFileSystemInitializer = mock(ModuleFileSystemInitializer.class);
     when(moduleFileSystemInitializer.defaultEncoding()).thenReturn(StandardCharsets.UTF_8);
     sensorStrategy = new SensorStrategy();
-    builder = new InputFileBuilder(module, metadataGenerator, idGenerator, settings.asConfig(), moduleFileSystemInitializer, new DefaultInputModuleHierarchy(root),
+    builder = new InputFileBuilder(module, metadataGenerator, idGenerator, properties, moduleFileSystemInitializer, new DefaultInputModuleHierarchy(root),
       sensorStrategy);
   }