]> source.dussan.org Git - sonar-scanner-cli.git/commitdiff
SCANCLI-145 Update to the scanner library 3.0
authorJulien HENRY <julien.henry@sonarsource.com>
Tue, 30 Apr 2024 12:59:03 +0000 (14:59 +0200)
committerJulien HENRY <julien.henry@sonarsource.com>
Fri, 3 May 2024 11:07:43 +0000 (13:07 +0200)
13 files changed:
pom.xml
src/main/java/org/sonarsource/scanner/cli/Cli.java
src/main/java/org/sonarsource/scanner/cli/Conf.java
src/main/java/org/sonarsource/scanner/cli/Logs.java
src/main/java/org/sonarsource/scanner/cli/Main.java
src/main/java/org/sonarsource/scanner/cli/ScannerEngineBootstrapperFactory.java [new file with mode: 0644]
src/main/java/org/sonarsource/scanner/cli/ScannerFactory.java [deleted file]
src/test/java/org/sonarsource/scanner/cli/CliTest.java
src/test/java/org/sonarsource/scanner/cli/ConfTest.java
src/test/java/org/sonarsource/scanner/cli/LogsTest.java
src/test/java/org/sonarsource/scanner/cli/MainTest.java
src/test/java/org/sonarsource/scanner/cli/ScannerEngineBootstrapperFactoryTest.java [new file with mode: 0644]
src/test/java/org/sonarsource/scanner/cli/ScannerFactoryTest.java [deleted file]

diff --git a/pom.xml b/pom.xml
index 9d13ffbd7a3da29dad0643d8ac2a7477b5b04855..a3e3f73793e07c26ec44412d18bea269596c2859 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -64,9 +64,9 @@
 
   <dependencies>
     <dependency>
-      <groupId>org.sonarsource.scanner.api</groupId>
-      <artifactId>sonar-scanner-api</artifactId>
-      <version>2.16.3.1081</version>
+      <groupId>org.sonarsource.scanner.lib</groupId>
+      <artifactId>sonar-scanner-java-library</artifactId>
+      <version>3.0.0.74</version>
     </dependency>
     <dependency>
       <groupId>com.google.code.findbugs</groupId>
     <dependency>
       <groupId>org.assertj</groupId>
       <artifactId>assertj-core</artifactId>
-      <version>3.23.1</version>
+      <version>3.24.2</version>
       <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.mockito</groupId>
       <artifactId>mockito-core</artifactId>
-      <version>4.10.0</version>
+      <version>5.10.0</version>
       <scope>test</scope>
     </dependency>
   </dependencies>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-shade-plugin</artifactId>
-        <version>3.5.0</version>
+        <version>3.5.1</version>
         <executions>
           <execution>
             <phase>package</phase>
             <configuration>
               <rules>
                 <requireFilesSize>
-                  <minsize>560000</minsize>
-                  <maxsize>600000</maxsize>
+                  <minsize>3000000</minsize>
+                  <maxsize>3100000</maxsize>
                   <files>
                     <file>${project.build.directory}/sonar-scanner-${project.version}.zip</file>
                   </files>
   </build>
 
   <profiles>
-    <profile>
-      <id>it</id>
-      <modules>
-        <module>it</module>
-      </modules>
-    </profile>
-
     <profile>
       <id>dist-linux</id>
       <build>
index aafed18d7c1571a2f60c4f9f57beb71a23c05172..4de2a36f2bb33204fbd80b3f87dfb8de4cc9b700 100644 (file)
@@ -20,7 +20,6 @@
 package org.sonarsource.scanner.cli;
 
 import java.util.Properties;
-import org.sonarsource.scanner.api.ScannerProperties;
 
 import static java.util.Arrays.asList;
 
@@ -73,10 +72,7 @@ class Cli {
 
   private int processNextArg(String[] args, int pos) {
     String arg = args[pos];
-    if (pos == 0 && arg.charAt(0) != '-') {
-      props.setProperty(ScannerProperties.TASK, arg);
-
-    } else if (asList("-h", "--help").contains(arg)) {
+    if (asList("-h", "--help").contains(arg)) {
       printUsage();
       exit.exit(Exit.SUCCESS);
 
index 19b020e75a5d81258232e56a03987d3402700545..4e9a53ab725246461b367420547b3e2f9b14e8f2 100644 (file)
@@ -31,7 +31,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import javax.annotation.Nullable;
-import org.sonarsource.scanner.api.Utils;
+import org.sonarsource.scanner.lib.EnvironmentConfig;
 
 class Conf {
   private static final String SCANNER_HOME = "scanner.home";
@@ -79,8 +79,8 @@ class Conf {
     return resolver.resolve();
   }
 
-  private Properties loadEnvironmentProperties() {
-    return Utils.loadEnvironmentProperties(env);
+  private Map<String, String> loadEnvironmentProperties() {
+    return EnvironmentConfig.load(logger.getLogOutputAdapter());
   }
 
   private Properties loadGlobalProperties() {
index 038e78f5035e7fff72d2963ba6b83f5fa98b2570..f8b4ce31d59867d2fd3fe906768fd287a40afad4 100644 (file)
@@ -22,6 +22,7 @@ package org.sonarsource.scanner.cli;
 import java.io.PrintStream;
 import java.time.LocalTime;
 import java.time.format.DateTimeFormatter;
+import org.sonarsource.scanner.lib.LogOutput;
 
 public class Logs {
   private DateTimeFormatter timeFormatter;
@@ -77,4 +78,37 @@ public class Logs {
       stream.println(msg);
     }
   }
+
+  /**
+   * Adapter for the scanner library.
+   */
+  public LogOutput getLogOutputAdapter() {
+    return new LogOutputAdapter(this);
+  }
+
+  static class LogOutputAdapter implements LogOutput {
+    private final Logs logs;
+
+    public LogOutputAdapter(Logs logs) {
+      this.logs = logs;
+    }
+
+    @Override
+    public void log(String formattedMessage, Level level) {
+      switch (level) {
+        case TRACE, DEBUG:
+          logs.debug(formattedMessage);
+          break;
+        case ERROR:
+          logs.error(formattedMessage);
+          break;
+        case WARN:
+          logs.warn(formattedMessage);
+          break;
+        case INFO:
+        default:
+          logs.info(formattedMessage);
+      }
+    }
+  }
 }
index ff7f96f87d230a226813dae4a6c3dd6b1685d5c3..787cc80e698d0fde19229b90612261176953fecc 100644 (file)
  */
 package org.sonarsource.scanner.cli;
 
-import java.util.Locale;
 import java.util.Map;
 import java.util.Properties;
-import org.sonarsource.scanner.api.EmbeddedScanner;
-import org.sonarsource.scanner.api.ScanProperties;
+import org.sonarsource.scanner.lib.ScanProperties;
+import org.sonarsource.scanner.lib.ScannerEngineBootstrapper;
+import org.sonarsource.scanner.lib.ScannerEngineFacade;
 
 /**
  * Arguments :
@@ -42,15 +42,15 @@ public class Main {
   private final Exit exit;
   private final Cli cli;
   private final Conf conf;
-  private EmbeddedScanner embeddedScanner;
-  private final ScannerFactory runnerFactory;
+  private ScannerEngineBootstrapper scannerEngineBootstrapper;
+  private final ScannerEngineBootstrapperFactory bootstrapperFactory;
   private final Logs logger;
 
-  Main(Exit exit, Cli cli, Conf conf, ScannerFactory runnerFactory, Logs logger) {
+  Main(Exit exit, Cli cli, Conf conf, ScannerEngineBootstrapperFactory bootstrapperFactory, Logs logger) {
     this.exit = exit;
     this.cli = cli;
     this.conf = conf;
-    this.runnerFactory = runnerFactory;
+    this.bootstrapperFactory = bootstrapperFactory;
     this.logger = logger;
   }
 
@@ -58,11 +58,11 @@ public class Main {
     Logs logs = new Logs(System.out, System.err);
     Exit exit = new Exit();
     Cli cli = new Cli(exit, logs).parse(args);
-    Main main = new Main(exit, cli, new Conf(cli, logs, System.getenv()), new ScannerFactory(logs), logs);
-    main.execute();
+    Main main = new Main(exit, cli, new Conf(cli, logs, System.getenv()), new ScannerEngineBootstrapperFactory(logs), logs);
+    main.analyze();
   }
 
-  void execute() {
+  void analyze() {
     Stats stats = new Stats(logger).start();
 
     int status = Exit.INTERNAL_ERROR;
@@ -71,15 +71,12 @@ public class Main {
       checkSkip(p);
       configureLogging(p);
       init(p);
-      embeddedScanner.start();
-      if (isSonarCloud(p)) {
-        logger.info("Analyzing on SonarCloud");
-      } else {
-        String serverVersion = embeddedScanner.serverVersion();
-        logger.info(String.format("Analyzing on SonarQube server %s", serverVersion));
+      try (var engine = scannerEngineBootstrapper.bootstrap()) {
+        logServerType(engine);
+        engine.analyze((Map) p);
+        displayExecutionResult(stats, "SUCCESS");
+        status = Exit.SUCCESS;
       }
-      execute(stats, p);
-      status = Exit.SUCCESS;
     } catch (Throwable e) {
       displayExecutionResult(stats, "FAILURE");
       showError("Error during SonarScanner execution", e, cli.isDebugEnabled());
@@ -89,13 +86,13 @@ public class Main {
     }
   }
 
-  static boolean isSonarCloud(Properties props) {
-    String hostUrl = props.getProperty(Conf.PROPERTY_SONAR_HOST_URL);
-    if (hostUrl != null) {
-      return hostUrl.toLowerCase(Locale.ENGLISH).contains("sonarcloud");
+  private void logServerType(ScannerEngineFacade engine) {
+    if (engine.isSonarCloud()) {
+      logger.info("Analyzing on SonarCloud");
+    } else {
+      String serverVersion = engine.getServerVersion();
+      logger.info(String.format("Analyzing on SonarQube server %s", serverVersion));
     }
-
-    return false;
   }
 
   private void checkSkip(Properties properties) {
@@ -111,7 +108,7 @@ public class Main {
       exit.exit(Exit.SUCCESS);
     }
 
-    embeddedScanner = runnerFactory.create(p, cli.getInvokedFrom());
+    scannerEngineBootstrapper = bootstrapperFactory.create(p, cli.getInvokedFrom());
   }
 
   private void configureLogging(Properties props) {
@@ -122,11 +119,6 @@ public class Main {
     }
   }
 
-  private void execute(Stats stats, Properties p) {
-    embeddedScanner.execute((Map) p);
-    displayExecutionResult(stats, "SUCCESS");
-  }
-
   private void displayExecutionResult(Stats stats, String resultMsg) {
     logger.info(SEPARATOR);
     logger.info("EXECUTION " + resultMsg);
diff --git a/src/main/java/org/sonarsource/scanner/cli/ScannerEngineBootstrapperFactory.java b/src/main/java/org/sonarsource/scanner/cli/ScannerEngineBootstrapperFactory.java
new file mode 100644 (file)
index 0000000..b67254c
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * SonarScanner CLI
+ * Copyright (C) 2011-2024 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.sonarsource.scanner.cli;
+
+import java.util.Map;
+import java.util.Properties;
+import org.sonarsource.scanner.lib.ScannerEngineBootstrapper;
+
+class ScannerEngineBootstrapperFactory {
+
+  private final Logs logger;
+
+  public ScannerEngineBootstrapperFactory(Logs logger) {
+    this.logger = logger;
+  }
+
+  ScannerEngineBootstrapper create(Properties props, String isInvokedFrom) {
+    String appName = "ScannerCLI";
+    String appVersion = ScannerVersion.version();
+    if (isInvokedFrom.contains("/")) {
+      appName = isInvokedFrom.split("/")[0];
+      appVersion = isInvokedFrom.split("/")[1];
+    }
+
+    return newScannerEngineBootstrapper(appName, appVersion)
+      .addBootstrapProperties((Map) props);
+  }
+
+  ScannerEngineBootstrapper newScannerEngineBootstrapper(String appName, String appVersion) {
+    return new ScannerEngineBootstrapper(appName, appVersion, logger.getLogOutputAdapter());
+  }
+
+
+}
diff --git a/src/main/java/org/sonarsource/scanner/cli/ScannerFactory.java b/src/main/java/org/sonarsource/scanner/cli/ScannerFactory.java
deleted file mode 100644 (file)
index d27165e..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * SonarScanner CLI
- * Copyright (C) 2011-2024 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.sonarsource.scanner.cli;
-
-import java.util.Map;
-import java.util.Properties;
-import org.sonarsource.scanner.api.EmbeddedScanner;
-import org.sonarsource.scanner.api.LogOutput;
-
-class ScannerFactory {
-
-  private final Logs logger;
-
-  public ScannerFactory(Logs logger) {
-    this.logger = logger;
-  }
-
-  EmbeddedScanner create(Properties props, String isInvokedFrom) {
-    String appName = "ScannerCLI";
-    String appVersion = ScannerVersion.version();
-    if (!isInvokedFrom.equals("") && isInvokedFrom.contains("/")) {
-      appName = isInvokedFrom.split("/")[0];
-      appVersion = isInvokedFrom.split("/")[1];
-    }
-
-    return EmbeddedScanner.create(appName, appVersion, new DefaultLogOutput())
-      .addGlobalProperties((Map) props);
-  }
-
-  class DefaultLogOutput implements LogOutput {
-    @Override
-    public void log(String formattedMessage, Level level) {
-      switch (level) {
-        case TRACE:
-        case DEBUG:
-          logger.debug(formattedMessage);
-          break;
-        case ERROR:
-          logger.error(formattedMessage);
-          break;
-        case WARN:
-          logger.warn(formattedMessage);
-          break;
-        case INFO:
-        default:
-          logger.info(formattedMessage);
-      }
-    }
-  }
-}
index 961f7d10ba7ebd38fd16b68b9bf30d286a014614..ce5b14070def66121bdd1b8f66d69ae9c962d3b5 100644 (file)
@@ -22,11 +22,13 @@ package org.sonarsource.scanner.cli;
 import org.junit.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatNoException;
+import static org.assertj.core.api.Assertions.entry;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 
 public class CliTest {
-  private Exit exit = mock(Exit.class);
+  private final Exit exit = mock(Exit.class);
   private Logs logs = new Logs(System.out, System.err);
   private Cli cli = new Cli(exit, logs);
 
@@ -41,17 +43,18 @@ public class CliTest {
 
   @Test
   public void should_extract_properties() {
-    cli.parse(new String[] {"-D", "foo=bar", "--define", "hello=world", "-Dboolean"});
-    assertThat(cli.properties().get("foo")).isEqualTo("bar");
-    assertThat(cli.properties().get("hello")).isEqualTo("world");
-    assertThat(cli.properties().get("boolean")).isEqualTo("true");
+    cli.parse(new String[]{"-D", "foo=bar", "--define", "hello=world", "-Dboolean"});
+    assertThat(cli.properties()).contains(
+      entry("foo", "bar"),
+      entry("hello", "world"),
+      entry("boolean", "true"));
   }
 
   @Test
   public void should_warn_on_duplicate_properties() {
     logs = mock(Logs.class);
     cli = new Cli(exit, logs);
-    cli.parse(new String[] {"-D", "foo=bar", "--define", "foo=baz"});
+    cli.parse(new String[]{"-D", "foo=bar", "--define", "foo=baz"});
     verify(logs).warn("Property 'foo' with value 'bar' is overridden with value 'baz'");
   }
 
@@ -59,75 +62,66 @@ public class CliTest {
   public void should_fail_on_missing_prop() {
     logs = mock(Logs.class);
     cli = new Cli(exit, logs);
-    cli.parse(new String[] {"-D"});
+    cli.parse(new String[]{"-D"});
     verify(logs).error("Missing argument for option -D/--define");
     verify(exit).exit(Exit.INTERNAL_ERROR);
   }
 
   @Test
   public void should_not_fail_with_errors_option() {
-    cli.parse(new String[] {"-e"});
-  }
-
-  @Test
-  public void should_parse_optional_task() {
-    cli.parse(new String[] {"-D", "foo=bar"});
-    assertThat(cli.properties().get("sonar.task")).isNull();
-
-    cli.parse(new String[] {"views", "-D", "foo=bar"});
-    assertThat(cli.properties().get("sonar.task")).isEqualTo("views");
+    assertThatNoException().isThrownBy(() -> cli.parse(new String[]{"-e"}));
   }
 
   @Test
   public void should_enable_debug_mode() {
-    cli.parse(new String[] {"-X"});
+    cli.parse(new String[]{"-X"});
     assertThat(cli.isDebugEnabled()).isTrue();
-    assertThat(cli.properties().get("sonar.verbose")).isEqualTo("true");
+    assertThat(cli.properties()).containsEntry("sonar.verbose", "true");
   }
 
   @Test
   public void should_enable_debug_mode_full() {
-    cli.parse(new String[] {"--debug"});
+    cli.parse(new String[]{"--debug"});
     assertThat(cli.isDebugEnabled()).isTrue();
-    assertThat(cli.properties().get("sonar.verbose")).isEqualTo("true");
+    assertThat(cli.properties()).containsEntry("sonar.verbose", "true");
   }
 
   @Test
   public void should_show_version() {
-    cli.parse(new String[] {"-v"});
+    cli.parse(new String[]{"-v"});
     assertThat(cli.isDisplayVersionOnly()).isTrue();
   }
 
   @Test
   public void should_show_version_full() {
-    cli.parse(new String[] {"--version"});
+    cli.parse(new String[]{"--version"});
     assertThat(cli.isDisplayVersionOnly()).isTrue();
   }
 
   @Test
   public void should_enable_stacktrace_log() {
-    cli.parse(new String[] {"-e"});
+    cli.parse(new String[]{"-e"});
     assertThat(cli.isDebugEnabled()).isFalse();
     assertThat(cli.properties().get("sonar.verbose")).isNull();
   }
 
   @Test
   public void should_enable_stacktrace_log_full() {
-    cli.parse(new String[] {"--errors"});
+    cli.parse(new String[]{"--errors"});
     assertThat(cli.isDebugEnabled()).isFalse();
     assertThat(cli.properties().get("sonar.verbose")).isNull();
   }
 
   @Test
   public void should_parse_from_argument() {
-    cli.parse(new String[] {"--from=ScannerMSBuild/4.8"});
+    cli.parse(new String[]{"--from=ScannerMSBuild/4.8"});
     assertThat(cli.getInvokedFrom()).isNotEmpty();
     assertThat(cli.getInvokedFrom()).isEqualTo("ScannerMSBuild/4.8");
   }
 
   @Test
   public void from_argument_is_only_from_let_value_empty() {
-    cli.parse(new String[] {"--from="});
+    cli.parse(new String[]{"--from="});
     assertThat(cli.getInvokedFrom()).isEmpty();
   }
 
@@ -142,7 +136,7 @@ public class CliTest {
   public void should_show_usage() {
     logs = mock(Logs.class);
     cli = new Cli(exit, logs);
-    cli.parse(new String[] {"-h"});
+    cli.parse(new String[]{"-h"});
     verify(logs).info("usage: sonar-scanner [options]");
     verify(exit).exit(Exit.SUCCESS);
   }
@@ -151,7 +145,7 @@ public class CliTest {
   public void should_show_usage_full() {
     logs = mock(Logs.class);
     cli = new Cli(exit, logs);
-    cli.parse(new String[] {"--help"});
+    cli.parse(new String[]{"--help"});
     verify(logs).info("usage: sonar-scanner [options]");
     verify(exit).exit(Exit.SUCCESS);
   }
@@ -160,7 +154,7 @@ public class CliTest {
   public void should_show_usage_on_bad_syntax() {
     logs = mock(Logs.class);
     cli = new Cli(exit, logs);
-    cli.parse(new String[] {"-w"});
+    cli.parse(new String[]{"-w"});
     verify(logs).error("Unrecognized option: -w");
     verify(logs).info("usage: sonar-scanner [options]");
     verify(exit).exit(Exit.INTERNAL_ERROR);
@@ -168,7 +162,7 @@ public class CliTest {
 
   @Test
   public void should_enable_embedded_mode() {
-    cli.parse(new String[] {"--embedded"});
+    cli.parse(new String[]{"--embedded"});
     assertThat(cli.isEmbedded()).isTrue();
   }
 }
index 5ff24419202fa2f49b5e4a074696e56923f5bee5..d28754a9b1748b6d2780ce3b047f2425ff476c17 100644 (file)
@@ -32,7 +32,6 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
-import org.sonarsource.scanner.api.internal.shaded.minimaljson.Json;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatCode;
@@ -133,26 +132,6 @@ public class ConfTest {
     assertThat(properties.getProperty("sonar.projectBaseDir")).isEqualTo(projectHome.toString());
   }
 
-  @Test
-  public void shouldLoadEnvironmentProperties() {
-    env.put("SONARQUBE_SCANNER_PARAMS", "{\"sonar.key1\" : \"v1\", \"sonar.key2\" : \"v2\"}");
-    args.put("sonar.key2", "v3");
-
-    Properties props = conf.properties();
-
-    assertThat(props.getProperty("sonar.key1")).isEqualTo("v1");
-    assertThat(props.getProperty("sonar.key2")).isEqualTo("v3");
-  }
-
-  @Test
-  public void shouldFailWithInvalidEnvironmentProperties() {
-    env.put("SONARQUBE_SCANNER_PARAMS", "{sonar.key1: \"v1\", \"sonar.key2\" : \"v2\"}");
-
-    assertThatIllegalStateException()
-      .isThrownBy(conf::properties)
-      .withMessage("Failed to parse JSON in SONARQUBE_SCANNER_PARAMS environment variable");
-  }
-
   @Test
   public void shouldSupportDeepModuleConfigurationInRoot() throws Exception {
     Path projectHome = Paths.get(getClass().getResource("ConfTest/shouldSupportDeepModuleConfigurationInRoot/project").toURI());
@@ -329,23 +308,4 @@ public class ConfTest {
     assertThat(properties).containsEntry("sonar.prop", "expected");
   }
 
-  // SQSCANNER-61
-  @Test
-  public void should_load_project_settings_using_env() throws Exception {
-    Path home = Paths.get(getClass().getResource("ConfTest/shouldOverrideProjectSettingsPath/").toURI());
-    args.setProperty("project.home", home.toAbsolutePath().toString());
-
-    Properties properties = conf.properties();
-    assertThat(properties).containsEntry("sonar.prop", "default");
-
-    String jsonString = Json.object()
-      .add("project.settings", home.resolve("conf/sq-project.properties").toAbsolutePath().toString())
-      .toString();
-
-    env.put("SONARQUBE_SCANNER_PARAMS", jsonString);
-
-    properties = conf.properties();
-    assertThat(properties).containsEntry("sonar.prop", "expected");
-  }
-
 }
index e66436596b7ccd5a85220b8ec79cfaa53e32293d..82a26ad10f58dd367a2ef789a6589f12bd03981d 100644 (file)
@@ -25,7 +25,10 @@ import org.junit.Test;
 import org.mockito.ArgumentMatchers;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.sonarsource.scanner.lib.LogOutput;
 
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 
@@ -89,4 +92,37 @@ public class LogsTest {
     logs.debug("debug");
     verifyNoMoreInteractions(stdOut, stdErr);
   }
+
+  @Test
+  public void should_forward_logs() {
+    var mockedLogs = mock(Logs.class);
+    var logOutput = new Logs.LogOutputAdapter(mockedLogs);
+
+    String msg = "test";
+
+    logOutput.log(msg, LogOutput.Level.DEBUG);
+    verify(mockedLogs).debug(msg);
+    verifyNoMoreInteractions(mockedLogs);
+    reset(mockedLogs);
+
+    logOutput.log(msg, LogOutput.Level.INFO);
+    verify(mockedLogs).info(msg);
+    verifyNoMoreInteractions(mockedLogs);
+    reset(mockedLogs);
+
+    logOutput.log(msg, LogOutput.Level.ERROR);
+    verify(mockedLogs).error(msg);
+    verifyNoMoreInteractions(mockedLogs);
+    reset(mockedLogs);
+
+    logOutput.log(msg, LogOutput.Level.WARN);
+    verify(mockedLogs).warn(msg);
+    verifyNoMoreInteractions(mockedLogs);
+    reset(mockedLogs);
+
+    logOutput.log(msg, LogOutput.Level.TRACE);
+    verify(mockedLogs).debug(msg);
+    verifyNoMoreInteractions(mockedLogs);
+    reset(mockedLogs);
+  }
 }
index 85f233cf33b17ad949f0d711e49ea1751a548926..6b8099dc742a380ad73449cf20210c25fe85bb6b 100644 (file)
@@ -29,14 +29,14 @@ import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.sonar.api.utils.MessageException;
-import org.sonarsource.scanner.api.EmbeddedScanner;
-import org.sonarsource.scanner.api.ScanProperties;
+import org.sonarsource.scanner.lib.ScanProperties;
+import org.sonarsource.scanner.lib.ScannerEngineBootstrapper;
+import org.sonarsource.scanner.lib.ScannerEngineFacade;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -53,63 +53,62 @@ public class MainTest {
   @Mock
   private Properties properties;
   @Mock
-  private ScannerFactory scannerFactory;
+  private ScannerEngineBootstrapperFactory scannerEngineBootstrapperFactory;
   @Mock
-  private EmbeddedScanner scanner;
+  private ScannerEngineBootstrapper bootstrapper;
+  @Mock
+  private ScannerEngineFacade engine;
   @Mock
   private Logs logs;
 
   @Before
   public void setUp() {
     MockitoAnnotations.initMocks(this);
-    when(scannerFactory.create(any(Properties.class), any(String.class))).thenReturn(scanner);
+    when(scannerEngineBootstrapperFactory.create(any(Properties.class), any(String.class))).thenReturn(bootstrapper);
+    when(bootstrapper.bootstrap()).thenReturn(engine);
     when(conf.properties()).thenReturn(properties);
   }
 
   @Test
-  public void should_execute_runner() {
+  public void should_execute_scanner_engine() {
     when(cli.getInvokedFrom()).thenReturn("");
-    Main main = new Main(exit, cli, conf, scannerFactory, logs);
-    main.execute();
+    Main main = new Main(exit, cli, conf, scannerEngineBootstrapperFactory, logs);
+    main.analyze();
 
     verify(exit).exit(Exit.SUCCESS);
-    verify(scannerFactory).create(properties, "");
+    verify(scannerEngineBootstrapperFactory).create(properties, "");
 
-    verify(scanner, times(1)).start();
-    verify(scanner, times(1)).execute((Map) properties);
+    verify(bootstrapper, times(1)).bootstrap();
+    verify(engine, times(1)).analyze((Map) properties);
   }
 
   @Test
   public void should_exit_with_error_on_error_during_analysis() {
-    EmbeddedScanner runner = mock(EmbeddedScanner.class);
     Exception e = new NullPointerException("NPE");
     e = new IllegalStateException("Error", e);
-    doThrow(e).when(runner).execute(any());
+    doThrow(e).when(engine).analyze(any());
     when(cli.getInvokedFrom()).thenReturn("");
-    when(scannerFactory.create(any(Properties.class), any(String.class))).thenReturn(runner);
     when(cli.isDebugEnabled()).thenReturn(true);
-    Main main = new Main(exit, cli, conf, scannerFactory, logs);
-    main.execute();
+    Main main = new Main(exit, cli, conf, scannerEngineBootstrapperFactory, logs);
+    main.analyze();
 
     verify(exit).exit(Exit.INTERNAL_ERROR);
     verify(logs).error("Error during SonarScanner execution", e);
   }
 
   @Test
-  public void should_exit_with_error_on_error_during_start() {
-    EmbeddedScanner runner = mock(EmbeddedScanner.class);
+  public void should_exit_with_error_on_error_during_bootstrap() {
     Exception e = new NullPointerException("NPE");
     e = new IllegalStateException("Error", e);
-    doThrow(e).when(runner).start();
+    doThrow(e).when(bootstrapper).bootstrap();
     when(cli.getInvokedFrom()).thenReturn("");
     when(cli.isDebugEnabled()).thenReturn(true);
-    when(scannerFactory.create(any(Properties.class), any(String.class))).thenReturn(runner);
 
-    Main main = new Main(exit, cli, conf, scannerFactory, logs);
-    main.execute();
+    Main main = new Main(exit, cli, conf, scannerEngineBootstrapperFactory, logs);
+    main.analyze();
 
-    verify(runner).start();
-    verify(runner, never()).execute(any());
+    verify(bootstrapper).bootstrap();
+    verify(engine, never()).analyze(any());
     verify(exit).exit(Exit.INTERNAL_ERROR);
     verify(logs).error("Error during SonarScanner execution", e);
   }
@@ -180,13 +179,13 @@ public class MainTest {
     when(cli.isEmbedded()).thenReturn(isEmbedded);
     when(cli.getInvokedFrom()).thenReturn("");
 
-    EmbeddedScanner runner = mock(EmbeddedScanner.class);
-    doThrow(e).when(runner).execute(any());
 
-    when(scannerFactory.create(any(Properties.class), any(String.class))).thenReturn(runner);
+    doThrow(e).when(engine).analyze(any());
+
+    when(scannerEngineBootstrapperFactory.create(any(Properties.class), any(String.class))).thenReturn(bootstrapper);
 
-    Main main = new Main(exit, cli, conf, scannerFactory, logs);
-    main.execute();
+    Main main = new Main(exit, cli, conf, scannerEngineBootstrapperFactory, logs);
+    main.analyze();
 
     verify(exit).exit(expectedExitCode);
   }
@@ -209,13 +208,13 @@ public class MainTest {
     when(cli.getInvokedFrom()).thenReturn("");
     when(conf.properties()).thenReturn(p);
 
-    Main main = new Main(exit, cli, conf, scannerFactory, logs);
-    main.execute();
+    Main main = new Main(exit, cli, conf, scannerEngineBootstrapperFactory, logs);
+    main.analyze();
 
-    InOrder inOrder = Mockito.inOrder(exit, scannerFactory);
+    InOrder inOrder = Mockito.inOrder(exit, scannerEngineBootstrapperFactory);
 
     inOrder.verify(exit, times(1)).exit(Exit.SUCCESS);
-    inOrder.verify(scannerFactory, times(1)).create(p, "");
+    inOrder.verify(scannerEngineBootstrapperFactory, times(1)).create(p, "");
     inOrder.verify(exit, times(1)).exit(Exit.SUCCESS);
   }
 
@@ -226,67 +225,43 @@ public class MainTest {
     when(conf.properties()).thenReturn(p);
     when(cli.getInvokedFrom()).thenReturn("");
 
-    Main main = new Main(exit, cli, conf, scannerFactory, logs);
-    main.execute();
+    Main main = new Main(exit, cli, conf, scannerEngineBootstrapperFactory, logs);
+    main.analyze();
 
     verify(logs).info("SonarScanner analysis skipped");
-    InOrder inOrder = Mockito.inOrder(exit, scannerFactory);
+    InOrder inOrder = Mockito.inOrder(exit, scannerEngineBootstrapperFactory);
 
     inOrder.verify(exit, times(1)).exit(Exit.SUCCESS);
-    inOrder.verify(scannerFactory, times(1)).create(p, "");
+    inOrder.verify(scannerEngineBootstrapperFactory, times(1)).create(p, "");
     inOrder.verify(exit, times(1)).exit(Exit.SUCCESS);
   }
 
   @Test
   public void shouldLogServerVersion() {
-    when(scanner.serverVersion()).thenReturn("5.5");
+    when(engine.isSonarCloud()).thenReturn(false);
+    when(engine.getServerVersion()).thenReturn("5.5");
     Properties p = new Properties();
     when(cli.isDisplayVersionOnly()).thenReturn(true);
     when(cli.getInvokedFrom()).thenReturn("");
     when(conf.properties()).thenReturn(p);
 
-    Main main = new Main(exit, cli, conf, scannerFactory, logs);
-    main.execute();
+    Main main = new Main(exit, cli, conf, scannerEngineBootstrapperFactory, logs);
+    main.analyze();
     verify(logs).info("Analyzing on SonarQube server 5.5");
   }
 
   @Test
   public void should_log_SonarCloud_server() {
+    when(engine.isSonarCloud()).thenReturn(true);
     Properties p = new Properties();
-    p.setProperty("sonar.host.url", "https://sonarcloud.io");
     when(conf.properties()).thenReturn(p);
     when(cli.getInvokedFrom()).thenReturn("");
 
-    Main main = new Main(exit, cli, conf, scannerFactory, logs);
-    main.execute();
+    Main main = new Main(exit, cli, conf, scannerEngineBootstrapperFactory, logs);
+    main.analyze();
     verify(logs).info("Analyzing on SonarCloud");
   }
 
-  // SQSCANNER-57
-  @Test
-  public void should_return_true_is_sonar_cloud() {
-
-    Properties properties = new Properties();
-    properties.setProperty("sonar.host.url", "https://sonarcloud.io");
-
-    assertThat(Main.isSonarCloud(properties)).isTrue();
-  }
-
-  // SQSCANNER-57
-  @Test
-  public void should_return_false_is_sonar_cloud() {
-    Properties properties = new Properties();
-    properties.setProperty("sonar.host.url", "https://mysonarqube.com:9000/");
-
-    assertThat(Main.isSonarCloud(properties)).isFalse();
-  }
-
-  // SQSCANNER-57
-  @Test
-  public void should_return_false_is_sonar_cloud_host_is_null() {
-    assertThat(Main.isSonarCloud(new Properties())).isFalse();
-  }
-
   @Test
   public void should_configure_logging() {
     Properties analysisProps = testLogging("sonar.verbose", "true");
@@ -327,11 +302,11 @@ public class MainTest {
     when(conf.properties()).thenReturn(p);
     when(cli.getInvokedFrom()).thenReturn("");
 
-    Main main = new Main(exit, cli, conf, scannerFactory, logs);
-    main.execute();
+    Main main = new Main(exit, cli, conf, scannerEngineBootstrapperFactory, logs);
+    main.analyze();
 
     ArgumentCaptor<Properties> propertiesCapture = ArgumentCaptor.forClass(Properties.class);
-    verify(scanner).execute((Map) propertiesCapture.capture());
+    verify(engine).analyze((Map) propertiesCapture.capture());
 
     return propertiesCapture.getValue();
   }
diff --git a/src/test/java/org/sonarsource/scanner/cli/ScannerEngineBootstrapperFactoryTest.java b/src/test/java/org/sonarsource/scanner/cli/ScannerEngineBootstrapperFactoryTest.java
new file mode 100644 (file)
index 0000000..f3ae408
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * SonarScanner CLI
+ * Copyright (C) 2011-2024 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.sonarsource.scanner.cli;
+
+import java.util.Properties;
+import org.junit.Test;
+import org.sonarsource.scanner.lib.ScannerEngineBootstrapper;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.notNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class ScannerEngineBootstrapperFactoryTest {
+
+  private final Properties props = new Properties();
+  private final Logs logs = mock(Logs.class);
+  private ScannerEngineBootstrapperFactory underTest = new ScannerEngineBootstrapperFactory(logs);
+
+  @Test
+  public void should_create_engine_bootstrapper_and_pass_app_and_properties() {
+    props.setProperty("foo", "bar");
+    var spy = spy(underTest);
+    var mockedBootstrapper = mock(ScannerEngineBootstrapper.class);
+    when(mockedBootstrapper.addBootstrapProperties(any())).thenReturn(mockedBootstrapper);
+    when(spy.newScannerEngineBootstrapper(any(), any())).thenReturn(mockedBootstrapper);
+
+    var bootstrapper = spy.create(props, "");
+
+    assertThat(bootstrapper).isNotNull();
+    verify(spy).newScannerEngineBootstrapper(eq("ScannerCLI"), notNull());
+    verify(mockedBootstrapper).addBootstrapProperties(argThat(props::equals));
+  }
+
+  @Test
+  public void should_create_engine_bootstrapper_with_app_from_argument() {
+    var spy = spy(underTest);
+    var mockedBootstrapper = mock(ScannerEngineBootstrapper.class);
+    when(mockedBootstrapper.addBootstrapProperties(any())).thenReturn(mockedBootstrapper);
+    when(spy.newScannerEngineBootstrapper(any(), any())).thenReturn(mockedBootstrapper);
+
+    var bootstrapper = spy.create(props, "ScannerMSBuild/4.8.0");
+
+    assertThat(bootstrapper).isNotNull();
+    verify(spy).newScannerEngineBootstrapper("ScannerMSBuild", "4.8.0");
+  }
+
+  @Test
+  public void if_from_argument_is_not_regex_compliant_revert_to_default_scanner_name() {
+    var spy = spy(underTest);
+    var mockedBootstrapper = mock(ScannerEngineBootstrapper.class);
+    when(mockedBootstrapper.addBootstrapProperties(any())).thenReturn(mockedBootstrapper);
+    when(spy.newScannerEngineBootstrapper(any(), any())).thenReturn(mockedBootstrapper);
+
+    var bootstrapper = spy.create(props, "ScannerMSBuild4.8.0WithoutSlash");
+
+    assertThat(bootstrapper).isNotNull();
+    verify(spy).newScannerEngineBootstrapper(eq("ScannerCLI"), notNull());
+  }
+
+
+}
diff --git a/src/test/java/org/sonarsource/scanner/cli/ScannerFactoryTest.java b/src/test/java/org/sonarsource/scanner/cli/ScannerFactoryTest.java
deleted file mode 100644 (file)
index 289da0a..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * SonarScanner CLI
- * Copyright (C) 2011-2024 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.sonarsource.scanner.cli;
-
-import java.util.Properties;
-import org.junit.Test;
-import org.sonarsource.scanner.api.EmbeddedScanner;
-import org.sonarsource.scanner.api.LogOutput;
-import org.sonarsource.scanner.api.LogOutput.Level;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-
-public class ScannerFactoryTest {
-
-  private final Properties props = new Properties();
-  private final Logs logs = mock(Logs.class);
-
-  @Test
-  public void should_create_embedded_runner() {
-    props.setProperty("foo", "bar");
-    EmbeddedScanner runner = new ScannerFactory(logs).create(props, "");
-
-    assertThat(runner).isInstanceOf(EmbeddedScanner.class);
-    assertThat(runner.globalProperties()).containsEntry("foo", "bar");
-    assertThat(runner.app()).isEqualTo("ScannerCLI");
-    assertThat(runner.appVersion()).isNotNull();
-  }
-
-  @Test
-  public void should_create_embedded_runner_with_scannername_from_argument() {
-    props.setProperty("foo", "bar");
-    EmbeddedScanner runner = new ScannerFactory(logs).create(props, "ScannerMSBuild/4.8.0");
-
-    assertThat(runner).isInstanceOf(EmbeddedScanner.class);
-    assertThat(runner.globalProperties()).containsEntry("foo", "bar");
-    assertThat(runner.app()).isEqualTo("ScannerMSBuild");
-    assertThat(runner.appVersion()).isEqualTo("4.8.0");
-    assertThat(runner.appVersion()).isNotNull();
-  }
-
-  @Test
-  public void should_create_embedded_runner_from_argument_is_not_regex_compliant_revert_to_default_scanner_name() {
-    props.setProperty("foo", "bar");
-    EmbeddedScanner runner = new ScannerFactory(logs).create(props, "ScannerMSBuild4.8.0");
-
-    assertThat(runner).isInstanceOf(EmbeddedScanner.class);
-    assertThat(runner.globalProperties()).containsEntry("foo", "bar");
-    assertThat(runner.app()).isEqualTo("ScannerCLI");
-    assertThat(runner.appVersion()).isNotNull();
-  }
-
-  @Test
-  public void should_fwd_logs() {
-    LogOutput logOutput = new ScannerFactory(logs).new DefaultLogOutput();
-
-    String msg = "test";
-
-    logOutput.log(msg, Level.DEBUG);
-    verify(logs).debug(msg);
-    verifyNoMoreInteractions(logs);
-    reset(logs);
-
-    logOutput.log(msg, Level.INFO);
-    verify(logs).info(msg);
-    verifyNoMoreInteractions(logs);
-    reset(logs);
-
-    logOutput.log(msg, Level.ERROR);
-    verify(logs).error(msg);
-    verifyNoMoreInteractions(logs);
-    reset(logs);
-
-    logOutput.log(msg, Level.WARN);
-    verify(logs).warn(msg);
-    verifyNoMoreInteractions(logs);
-    reset(logs);
-
-    logOutput.log(msg, Level.TRACE);
-    verify(logs).debug(msg);
-    verifyNoMoreInteractions(logs);
-    reset(logs);
-  }
-
-}