]> source.dussan.org Git - sonar-scanner-cli.git/commitdiff
Improve unit tests
authorDuarte Meneses <duarte.meneses@sonarsource.com>
Tue, 1 Sep 2015 11:56:05 +0000 (13:56 +0200)
committerDuarte Meneses <duarte.meneses@sonarsource.com>
Tue, 1 Sep 2015 11:56:05 +0000 (13:56 +0200)
16 files changed:
sonar-runner-api/src/main/java/org/sonar/runner/impl/ServerConnection.java
sonar-runner-api/src/test/java/org/sonar/runner/impl/ServerConnectionTest.java
sonar-runner-api/src/test/java/org/sonar/runner/impl/SimulatedLauncherTest.java [new file with mode: 0644]
sonar-runner-cli/src/main/java/org/sonar/runner/cli/Cli.java
sonar-runner-cli/src/main/java/org/sonar/runner/cli/Conf.java
sonar-runner-cli/src/main/java/org/sonar/runner/cli/Logs.java
sonar-runner-cli/src/main/java/org/sonar/runner/cli/Main.java
sonar-runner-cli/src/main/java/org/sonar/runner/cli/RunnerFactory.java
sonar-runner-cli/src/main/java/org/sonar/runner/cli/Stats.java
sonar-runner-cli/src/main/java/org/sonar/runner/cli/SystemInfo.java
sonar-runner-cli/src/test/java/org/sonar/runner/cli/CliTest.java
sonar-runner-cli/src/test/java/org/sonar/runner/cli/ConfTest.java
sonar-runner-cli/src/test/java/org/sonar/runner/cli/MainTest.java
sonar-runner-cli/src/test/java/org/sonar/runner/cli/RunnerFactoryTest.java
sonar-runner-cli/src/test/java/org/sonar/runner/cli/StatsTest.java
sonar-runner-cli/src/test/java/org/sonar/runner/cli/SystemInfoTest.java

index 88a92d99306d4d9c0df0ef518e4a397920796ab7..7156ebc44c76ea19bdc28e1ee1683c3235499263 100644 (file)
@@ -61,9 +61,6 @@ class ServerConnection {
   }
 
   private static String removeEndSlash(String url) {
-    if (url == null) {
-      return null;
-    }
     return url.endsWith("/") ? url.substring(0, url.length() - 1) : url;
   }
 
index 4698576e5b766db7e222da95d51a51295df9a001..8723c97c8c6e16642255029a4bb0bef66c5bb471 100644 (file)
@@ -19,6 +19,8 @@
  */
 package org.sonar.runner.impl;
 
+import org.sonar.home.cache.PersistentCacheLoader;
+
 import com.github.kevinsawicki.http.HttpRequest;
 
 import java.io.File;
@@ -27,6 +29,11 @@ import java.net.ConnectException;
 import java.net.SocketTimeoutException;
 import java.util.Properties;
 
+import static org.mockito.Matchers.startsWith;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
 import static org.junit.Assert.*;
 import org.apache.commons.io.FileUtils;
 import org.junit.Before;
@@ -48,20 +55,29 @@ public class ServerConnectionTest {
   @Rule
   public TemporaryFolder temp = new TemporaryFolder();
 
-  private PersistentCache cache = null;
+  private PersistentCache cache;
+  private Logger logger;
 
   @Before
   public void setUp() {
     cache = new PersistentCacheBuilder(mock(Logger.class)).setSonarHome(temp.getRoot().toPath()).build();
+    logger = mock(Logger.class);
   }
 
   @Test
-  public void should_download_to_string() throws Exception {
-    httpServer.setMockResponseData("abcde");
-    Properties props = new Properties();
-    props.setProperty("sonar.host.url", httpServer.url());
+  public void continue_if_cache_put_fails() throws Exception {
+    cache = mock(PersistentCache.class);
+    doThrow(IOException.class).when(cache).put(anyString(), any(byte[].class));
+    ServerConnection connection = createSimpleServerConnection(httpServer.url(), null, true);
+    String response = connection.downloadStringCache("/batch/index.txt");
 
-    ServerConnection connection = ServerConnection.create(props, cache, mock(Logger.class));
+    assertThat(response).isEqualTo("abcde");
+    verify(logger).warn(startsWith("Failed to cache WS call:"));
+  }
+
+  @Test
+  public void should_download_to_string() throws Exception {
+    ServerConnection connection = createSimpleServerConnection(httpServer.url(), null);
     String response = connection.downloadStringCache("/batch/index.txt");
 
     assertThat(response).isEqualTo("abcde");
@@ -69,27 +85,34 @@ public class ServerConnectionTest {
 
   @Test
   public void should_download_to_file() throws Exception {
-    httpServer.setMockResponseData("abcde");
-    Properties props = new Properties();
-    props.setProperty("sonar.host.url", httpServer.url());
-
-    ServerConnection connection = ServerConnection.create(props, cache, mock(Logger.class));
+    ServerConnection connection = createSimpleServerConnection(httpServer.url(), null);
     File toFile = temp.newFile();
     connection.download("/batch/index.txt", toFile);
 
     assertThat(FileUtils.readFileToString(toFile)).isEqualTo("abcde");
   }
 
+  @Test
+  public void should_throw_original_exception_fallback() throws IOException {
+    cache = mock(PersistentCache.class);
+    ServerConnection connection = createSimpleServerConnection("http://localhost", NetworkUtil.getNextAvailablePort(), true);
+
+    try {
+      connection.downloadStringCache("/batch/index.txt");
+      fail();
+    } catch (HttpRequest.HttpRequestException e) {
+      verify(cache).getString(anyString(), any(PersistentCacheLoader.class));
+      assertThat(e.getCause()).isInstanceOf(ConnectException.class);
+    }
+  }
+
   @Test
   public void should_cache_jar_list() throws Exception {
     File cacheDir = new File(temp.getRoot(), "ws_cache");
-    httpServer.setMockResponseData("abcde");
-    Properties props = new Properties();
-    props.setProperty("sonar.host.url", httpServer.url() + "/");
-    props.setProperty("sonar.analysis.mode", "issues");
+
+    ServerConnection connection = createSimpleServerConnection(httpServer.url() + "/", null, true);
 
     assertThat(cacheDir.list().length).isEqualTo(0);
-    ServerConnection connection = ServerConnection.create(props, cache, mock(Logger.class));
     String str = connection.downloadStringCache("/batch/index.txt");
 
     assertThat(str).isEqualTo("abcde");
@@ -103,12 +126,9 @@ public class ServerConnectionTest {
   @Test
   public void should_throw_connection_exception_() throws IOException {
     File cacheDir = new File(temp.getRoot(), "ws_cache");
-    httpServer.setMockResponseData("abcde");
-    Properties props = new Properties();
-    props.setProperty("sonar.host.url", httpServer.url() + "/");
+    ServerConnection connection = createSimpleServerConnection(httpServer.url() + "/", null);
 
     assertThat(cacheDir.list().length).isEqualTo(0);
-    ServerConnection connection = ServerConnection.create(props, cache, mock(Logger.class));
     String str = connection.downloadStringCache("/batch/index.txt");
     assertThat(str).isEqualTo("abcde");
 
@@ -128,14 +148,11 @@ public class ServerConnectionTest {
   }
 
   @Test
-  public void should_not_cache_not_preview() throws Exception {
+  public void should_not_cache_not_issues_mode() throws Exception {
     File cacheDir = new File(temp.getRoot(), "ws_cache");
-    httpServer.setMockResponseData("abcde");
-    Properties props = new Properties();
-    props.setProperty("sonar.host.url", httpServer.url() + "/");
+    ServerConnection connection = createSimpleServerConnection(httpServer.url() + "/", null);
 
     assertThat(cacheDir.list().length).isEqualTo(0);
-    ServerConnection connection = ServerConnection.create(props, cache, mock(Logger.class));
     String str = connection.downloadStringCache("/batch/index.txt");
 
     assertThat(str).isEqualTo("abcde");
@@ -149,11 +166,7 @@ public class ServerConnectionTest {
   // SONARPLUGINS-3061
   @Test
   public void should_support_trailing_slash() throws Exception {
-    httpServer.setMockResponseData("abcde");
-    Properties props = new Properties();
-    props.setProperty("sonar.host.url", httpServer.url() + "/");
-
-    ServerConnection connection = ServerConnection.create(props, cache, mock(Logger.class));
+    ServerConnection connection = createSimpleServerConnection(httpServer.url() + "/", null);
     File toFile = temp.newFile();
     connection.download("/batch/index.txt", toFile);
 
@@ -162,10 +175,8 @@ public class ServerConnectionTest {
 
   @Test
   public void should_not_download_file_when_host_is_down() throws Exception {
-    Properties props = new Properties();
-    props.setProperty("sonar.host.url", "http://localhost:" + NetworkUtil.getNextAvailablePort());
+    ServerConnection connection = createSimpleServerConnection("http://localhost", NetworkUtil.getNextAvailablePort());
 
-    ServerConnection connection = ServerConnection.create(props, cache, mock(Logger.class));
     File toFile = temp.newFile();
     try {
       connection.download("/batch/index.txt", toFile);
@@ -177,10 +188,8 @@ public class ServerConnectionTest {
 
   @Test
   public void should_not_download_string_when_host_is_down() throws Exception {
-    Properties props = new Properties();
-    props.setProperty("sonar.host.url", "http://localhost:" + NetworkUtil.getNextAvailablePort());
+    ServerConnection connection = createSimpleServerConnection("http://localhost", NetworkUtil.getNextAvailablePort());
 
-    ServerConnection connection = ServerConnection.create(props, cache, mock(Logger.class));
     try {
       connection.downloadStringCache("/batch/index.txt");
       fail();
@@ -188,4 +197,19 @@ public class ServerConnectionTest {
       // success
     }
   }
+
+  private ServerConnection createSimpleServerConnection(String url, Integer port) {
+    return createSimpleServerConnection(url, port, false);
+  }
+
+  private ServerConnection createSimpleServerConnection(String url, Integer port, boolean issuesMode) {
+    httpServer.setMockResponseData("abcde");
+    String fullUrl = port == null ? url : url + ":" + port;
+    Properties props = new Properties();
+    props.setProperty("sonar.host.url", fullUrl);
+    if (issuesMode) {
+      props.setProperty("sonar.analysis.mode", "issues");
+    }
+    return ServerConnection.create(props, cache, logger);
+  }
 }
diff --git a/sonar-runner-api/src/test/java/org/sonar/runner/impl/SimulatedLauncherTest.java b/sonar-runner-api/src/test/java/org/sonar/runner/impl/SimulatedLauncherTest.java
new file mode 100644 (file)
index 0000000..5f34023
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * SonarQube Runner - API
+ * Copyright (C) 2011 SonarSource
+ * sonarqube@googlegroups.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  02
+ */
+package org.sonar.runner.impl;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.home.cache.Logger;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+import java.util.Properties;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+public class SimulatedLauncherTest {
+  private static final String VERSION = "5.2";
+  private SimulatedLauncher launcher;
+  private Logger logger;
+  private String filename;
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  @Before
+  public void setUp() {
+    logger = mock(Logger.class);
+    launcher = new SimulatedLauncher(VERSION, logger);
+    filename = new File(temp.getRoot(), "props").getAbsolutePath();
+  }
+
+  @Test
+  public void testDump() throws IOException {
+    Properties global = new Properties();
+    global.putAll(createProperties(true));
+    Properties analysis = new Properties();
+    analysis.putAll(createProperties(false));
+
+    launcher.start(global, null, false);
+    launcher.execute(analysis);
+    assertDump(global, analysis);
+  }
+
+  @Test(expected = IllegalStateException.class)
+  public void error_if_no_dump_file() {
+    launcher.execute(new Properties());
+  }
+
+  @Test
+  public void no_ops() {
+    launcher.syncProject(null);
+  }
+
+  @Test
+  public void testOldExecute() {
+    Properties global = new Properties();
+    global.putAll(createProperties(true));
+    Properties analysis = new Properties();
+    analysis.putAll(createProperties(false));
+
+    launcher.start(global, null, false);
+    launcher.executeOldVersion(analysis, null);
+
+  }
+
+  private Properties createProperties(boolean global) {
+    Properties prop = new Properties();
+    prop.put("key1_" + global, "value1");
+    prop.put("key2_" + global, "value2");
+    prop.put(InternalProperties.RUNNER_DUMP_TO_FILE, filename);
+    return prop;
+  }
+
+  @Test
+  public void version() {
+    assertThat(launcher.getVersion()).isEqualTo(VERSION);
+  }
+
+  private void assertDump(Properties global, Properties analysis) throws IOException {
+    if (analysis != null) {
+      String content = FileUtils.readFileToString(new File(filename));
+      for (Map.Entry<Object, Object> e : analysis.entrySet()) {
+        assertThat(content).contains(e.getKey() + "=" + e.getValue());
+      }
+    } else {
+      assertThat(new File(filename)).doesNotExist();
+    }
+
+    if (global != null) {
+      String content = FileUtils.readFileToString(new File(filename + ".global"));
+      for (Map.Entry<Object, Object> e : global.entrySet()) {
+        assertThat(content).contains(e.getKey() + "=" + e.getValue());
+      }
+    } else {
+      assertThat(new File(filename + ".global")).doesNotExist();
+    }
+  }
+
+}
index f1a038b2b5abf745a2906ab4b0bdc56aeadcb125..8a346072e60d92959ab2b9241133c0401559a4d8 100644 (file)
@@ -29,10 +29,12 @@ class Cli {
   private boolean displayStackTrace = false;
   private boolean interactive = false;
   private Properties props = new Properties();
-  private Exit exit;
+  private final Exit exit;
+  private Logs logger;
 
-  public Cli(Exit exit) {
+  public Cli(Exit exit, Logs logger) {
     this.exit = exit;
+    this.logger = logger;
   }
 
   boolean isDebugMode() {
@@ -71,14 +73,14 @@ class Cli {
 
       } else if ("-e".equals(arg) || "--errors".equals(arg)) {
         displayStackTrace = true;
-        Logs.setDisplayStackTrace(true);
+        logger.setDisplayStackTrace(true);
 
       } else if ("-X".equals(arg) || "--debug".equals(arg)) {
         props.setProperty("sonar.verbose", "true");
         displayStackTrace = true;
         debugMode = true;
-        Logs.setDebugEnabled(true);
-        Logs.setDisplayStackTrace(true);
+        logger.setDebugEnabled(true);
+        logger.setDisplayStackTrace(true);
 
       } else if ("-D".equals(arg) || "--define".equals(arg)) {
         i++;
@@ -130,21 +132,21 @@ class Cli {
   }
 
   private void printError(String message) {
-    Logs.error(message);
+    logger.error(message);
     printUsage();
   }
 
   private void printUsage() {
-    Logs.info("");
-    Logs.info("usage: sonar-runner [options]");
-    Logs.info("");
-    Logs.info("Options:");
-    Logs.info(" -D,--define <arg>     Define property");
-    Logs.info(" -e,--errors           Produce execution error messages");
-    Logs.info(" -h,--help             Display help information");
-    Logs.info(" -v,--version          Display version information");
-    Logs.info(" -X,--debug            Produce execution debug output");
-    Logs.info(" -i,--interactive      Run interactively");
+    logger.info("");
+    logger.info("usage: sonar-runner [options]");
+    logger.info("");
+    logger.info("Options:");
+    logger.info(" -D,--define <arg>     Define property");
+    logger.info(" -e,--errors           Produce execution error messages");
+    logger.info(" -h,--help             Display help information");
+    logger.info(" -v,--version          Display version information");
+    logger.info(" -X,--debug            Produce execution debug output");
+    logger.info(" -i,--interactive      Run interactively");
     exit.exit(Exit.SUCCESS);
   }
 }
index 68627f7fa1fb3233277c8aef0848a28abdac01c9..ac7248f4caca9b8916ea60928e21ee6c05fade06 100644 (file)
@@ -39,9 +39,11 @@ class Conf {
   private static final String SONAR_PROJECT_PROPERTIES_FILENAME = "sonar-project.properties";
 
   private final Cli cli;
+  private final Logs logger;
 
-  Conf(Cli cli) {
+  Conf(Cli cli, Logs logger) {
     this.cli = cli;
+    this.logger = logger;
   }
 
   Properties properties() throws IOException {
@@ -57,10 +59,10 @@ class Conf {
   private Properties loadGlobalProperties() throws IOException {
     File settingsFile = locatePropertiesFile(cli.properties(), RUNNER_HOME, "conf/sonar-runner.properties", RUNNER_SETTINGS);
     if (settingsFile != null && settingsFile.isFile() && settingsFile.exists()) {
-      Logs.info("Runner configuration file: " + settingsFile.getAbsolutePath());
+      logger.info("Runner configuration file: " + settingsFile.getAbsolutePath());
       return toProperties(settingsFile);
     }
-    Logs.info("Runner configuration file: NONE");
+    logger.info("Runner configuration file: NONE");
     return new Properties();
   }
 
@@ -70,7 +72,7 @@ class Conf {
       SONAR_PROJECT_PROPERTIES_FILENAME,
       PROJECT_SETTINGS);
     if (rootSettingsFile != null && rootSettingsFile.isFile() && rootSettingsFile.exists()) {
-      Logs.info("Project configuration file: " + rootSettingsFile.getAbsolutePath());
+      logger.info("Project configuration file: " + rootSettingsFile.getAbsolutePath());
       Properties projectProps = new Properties();
       Properties rootProps = toProperties(rootSettingsFile);
       projectProps.putAll(rootProps);
@@ -78,7 +80,7 @@ class Conf {
       loadModulesProperties(rootProps, projectProps, "");
       return projectProps;
     }
-    Logs.info("Project configuration file: NONE");
+    logger.info("Project configuration file: NONE");
     return new Properties();
   }
 
index d69f3fd9554a28dd1313af9fe383c2042f9e54d3..6577a819a37de7265e39c2dd75ece8130aa6a134 100644 (file)
 package org.sonar.runner.cli;
 
 public class Logs {
+  private boolean debugEnabled = false;
+  private boolean displayStackTrace = false;
 
-  private Logs() {
+  public void setDebugEnabled(boolean debugEnabled) {
+    this.debugEnabled = debugEnabled;
   }
 
-  private static boolean debugEnabled = false;
-  private static boolean displayStackTrace = false;
-
-  public static void setDebugEnabled(boolean debugEnabled) {
-    Logs.debugEnabled = debugEnabled;
-  }
-
-  public static void setDisplayStackTrace(boolean displayStackTrace) {
-    Logs.displayStackTrace = displayStackTrace;
+  public void setDisplayStackTrace(boolean displayStackTrace) {
+    this.displayStackTrace = displayStackTrace;
   }
 
-  public static boolean isDebugEnabled() {
+  public boolean isDebugEnabled() {
     return debugEnabled;
   }
 
-  public static void debug(String message) {
+  public void debug(String message) {
     if (isDebugEnabled()) {
       System.out.println("DEBUG: " + message);
     }
   }
 
-  public static void info(String message) {
+  public void info(String message) {
     System.out.println("INFO: " + message);
   }
 
-  public static void warn(String message) {
+  public void warn(String message) {
     System.out.println("WARN: " + message);
   }
 
-  public static void error(String message) {
+  public void error(String message) {
     System.err.println("ERROR: " + message);
   }
 
-  public static void error(String message, Throwable t) {
+  public void error(String message, Throwable t) {
     System.err.println("ERROR: " + message);
     if (t != null && displayStackTrace) {
       t.printStackTrace(System.err);
index 88b45103038bedd79ab0bee5e06605c29e0eb0b9..0229cc9435b91f21131baef4095a523d9facb53d 100644 (file)
@@ -46,25 +46,28 @@ public class Main {
   private EmbeddedRunner runner;
   private BufferedReader inputReader;
   private RunnerFactory runnerFactory;
+  private Logs logger;
 
-  Main(Shutdown shutdown, Cli cli, Conf conf, RunnerFactory runnerFactory) {
+  Main(Shutdown shutdown, Cli cli, Conf conf, RunnerFactory runnerFactory, Logs logger) {
     this.shutdown = shutdown;
     this.cli = cli;
     this.conf = conf;
     this.runnerFactory = runnerFactory;
+    this.logger = logger;
   }
 
   public static void main(String[] args) {
     Exit exit = new Exit();
     Shutdown shutdown = new Shutdown(exit);
-    Cli cli = new Cli(exit).parse(args);
+    Logs logs = new Logs();
+    Cli cli = new Cli(exit, logs).parse(args);
     cli.verify();
-    Main main = new Main(shutdown, cli, new Conf(cli), new RunnerFactory());
+    Main main = new Main(shutdown, cli, new Conf(cli, logs), new RunnerFactory(logs), logs);
     main.execute();
   }
 
   void execute() {
-    Stats stats = new Stats().start();
+    Stats stats = new Stats(logger).start();
 
     try {
       Properties p = conf.properties();
@@ -88,7 +91,7 @@ public class Main {
 
   private void interactiveLoop(Properties p) throws IOException {
     do {
-      Stats stats = new Stats().start();
+      Stats stats = new Stats(logger).start();
       try {
         runAnalysis(stats, p);
       } catch (Exception e) {
@@ -99,13 +102,13 @@ public class Main {
   }
 
   private void init(Properties p) throws IOException {
-    SystemInfo.print();
+    SystemInfo.print(logger);
     if (cli.isDisplayVersionOnly()) {
       shutdown.exit(Exit.SUCCESS);
     }
 
     if (cli.isDisplayStackTrace()) {
-      Logs.info("Error stacktraces are turned on.");
+      logger.info("Error stacktraces are turned on.");
     }
 
     runner = runnerFactory.create(p);
@@ -140,43 +143,43 @@ public class Main {
     this.inputReader = inputReader;
   }
 
-  private static void displayExecutionResult(Stats stats, String resultMsg) {
-    Logs.info("------------------------------------------------------------------------");
-    Logs.info("EXECUTION " + resultMsg);
-    Logs.info("------------------------------------------------------------------------");
+  private void displayExecutionResult(Stats stats, String resultMsg) {
+    logger.info("------------------------------------------------------------------------");
+    logger.info("EXECUTION " + resultMsg);
+    logger.info("------------------------------------------------------------------------");
     stats.stop();
-    Logs.info("------------------------------------------------------------------------");
+    logger.info("------------------------------------------------------------------------");
   }
 
   private void showError(String message, Throwable e, boolean showStackTrace) {
     if (showStackTrace) {
-      Logs.error(message, e);
+      logger.error(message, e);
       if (!cli.isDebugMode()) {
-        Logs.error("");
+        logger.error("");
         suggestDebugMode();
       }
     } else {
-      Logs.error(message);
+      logger.error(message);
       if (e != null) {
-        Logs.error(e.getMessage());
+        logger.error(e.getMessage());
         String previousMsg = "";
         for (Throwable cause = e.getCause(); cause != null
           && cause.getMessage() != null
           && !cause.getMessage().equals(previousMsg); cause = cause.getCause()) {
-          Logs.error("Caused by: " + cause.getMessage());
+          logger.error("Caused by: " + cause.getMessage());
           previousMsg = cause.getMessage();
         }
       }
-      Logs.error("");
-      Logs.error("To see the full stack trace of the errors, re-run SonarQube Runner with the -e switch.");
+      logger.error("");
+      logger.error("To see the full stack trace of the errors, re-run SonarQube Runner with the -e switch.");
       if (!cli.isDebugMode()) {
         suggestDebugMode();
       }
     }
   }
 
-  private static void suggestDebugMode() {
-    Logs.error("Re-run SonarQube Runner using the -X switch to enable full debug logging.");
+  private void suggestDebugMode() {
+    logger.error("Re-run SonarQube Runner using the -X switch to enable full debug logging.");
   }
 
 }
index 3abe645100c19c4ac9b68b479ae1974d97f8bdbb..69406baa57bf6b9d91e42f022dfde7fd06d1b7bb 100644 (file)
@@ -25,26 +25,32 @@ import org.sonar.runner.api.LogOutput;
 
 class RunnerFactory {
 
+  private final Logs logger;
+
+  public RunnerFactory(Logs logger) {
+    this.logger = logger;
+  }
+
   EmbeddedRunner create(Properties props) {
-    return EmbeddedRunner.create(new LogOutput() {
+    return EmbeddedRunner.create(new DefaultLogOutput()).addGlobalProperties(props);
+  }
 
-      @Override
-      public void log(String formattedMessage, Level level) {
-        switch (level) {
-          case TRACE:
-          case DEBUG:
-            Logs.debug(formattedMessage);
-            break;
-          case ERROR:
-            Logs.error(formattedMessage);
-            break;
-          case INFO:
-          case WARN:
-          default:
-            Logs.info(formattedMessage);
-        }
+  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 INFO:
+        case WARN:
+        default:
+          logger.info(formattedMessage);
       }
-    }).addGlobalProperties(props);
+    }
   }
-
 }
index 5173137ccc2cb7009cb786efb866dd7f2f5bc584..82fbdb52e82fcb98689e0d8b10894bd319c03368 100644 (file)
 package org.sonar.runner.cli;
 
 class Stats {
+  private final Logs logger;
   private long startTime;
 
-  Stats() {
+  Stats(Logs logger) {
+    this.logger = logger;
   }
 
   Stats start() {
@@ -32,12 +34,12 @@ class Stats {
 
   Stats stop() {
     long stopTime = System.currentTimeMillis() - startTime;
-    Logs.info("Total time: " + formatTime(stopTime));
+    logger.info("Total time: " + formatTime(stopTime));
 
     System.gc();
     Runtime r = Runtime.getRuntime();
     long mb = 1024L * 1024;
-    Logs.info("Final Memory: " + (r.totalMemory() - r.freeMemory()) / mb + "M/" + r.totalMemory() / mb + "M");
+    logger.info("Final Memory: " + (r.totalMemory() - r.freeMemory()) / mb + "M/" + r.totalMemory() / mb + "M");
 
     return this;
   }
index 43b27abb277bf167d64a65ad2c88b3034f9da686..5d987202f5ec50b35ef6b07ad84dff1fd0cd1fee 100644 (file)
@@ -31,13 +31,13 @@ class SystemInfo {
     SystemInfo.system = system;
   }
 
-  static void print() {
-    Logs.info("SonarQube Runner " + RunnerVersion.version());
-    Logs.info(java());
-    Logs.info(os());
+  static void print(Logs logger) {
+    logger.info("SonarQube Runner " + RunnerVersion.version());
+    logger.info(java());
+    logger.info(os());
     String runnerOpts = system.getenv("SONAR_RUNNER_OPTS");
     if (runnerOpts != null) {
-      Logs.info("SONAR_RUNNER_OPTS=" + runnerOpts);
+      logger.info("SONAR_RUNNER_OPTS=" + runnerOpts);
     }
   }
 
index a0332c2b27758b3627862ee4289d93c4165d1dc2..d343561691cf5319a4582e1bdca1d313c2cc723e 100644 (file)
@@ -31,7 +31,8 @@ import static org.fest.assertions.Assertions.assertThat;
 
 public class CliTest {
   Exit exit = mock(Exit.class);
-  Cli cli = new Cli(exit);
+  Logs logs = new Logs();
+  Cli cli = new Cli(exit, logs);
 
   @Test
   public void should_parse_empty_arguments() {
index 94524636264c067bf58a33d394c3092d686a943f..4c9d77512575575f25c35c8b48fd504fe38e2ad7 100644 (file)
@@ -38,8 +38,9 @@ public class ConfTest {
   public TemporaryFolder temp = new TemporaryFolder();
 
   Properties args = new Properties();
+  Logs logs = new Logs();
   Cli cli = mock(Cli.class);
-  Conf conf = new Conf(cli);
+  Conf conf = new Conf(cli, logs);
 
   @Before
   public void initConf() {
index 857ed8c6ca4b9db90ad73293aa6cf59eca4678f0..a0dec5c0129765689c7ebd36cc4de0586ea5bb9e 100644 (file)
@@ -25,6 +25,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 import java.util.Properties;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.InOrder;
@@ -32,7 +33,6 @@ import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.sonar.runner.api.EmbeddedRunner;
-
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
@@ -54,6 +54,8 @@ public class MainTest {
   private RunnerFactory runnerFactory;
   @Mock
   private EmbeddedRunner runner;
+  @Mock
+  private Logs logs;
 
   @Before
   public void setUp() throws IOException {
@@ -65,7 +67,7 @@ public class MainTest {
 
   @Test
   public void should_execute_runner() {
-    Main main = new Main(exit, cli, conf, runnerFactory);
+    Main main = new Main(exit, cli, conf, runnerFactory, logs);
     main.execute();
 
     verify(exit).exit(Exit.SUCCESS);
@@ -79,14 +81,36 @@ public class MainTest {
   @Test
   public void should_stop_on_error() {
     EmbeddedRunner runner = mock(EmbeddedRunner.class);
-    doThrow(new IllegalStateException("Error")).when(runner).runAnalysis(any(Properties.class));
+    Exception e = new NullPointerException("NPE");
+    e = new IllegalStateException("Error", e);
+    doThrow(e).when(runner).runAnalysis(any(Properties.class));
+    when(runnerFactory.create(any(Properties.class))).thenReturn(runner);
+
+    Main main = new Main(exit, cli, conf, runnerFactory, logs);
+    main.execute();
+
+    verify(runner).stop();
+    verify(exit).exit(Exit.ERROR);
+    verify(logs).error("Caused by: NPE" );
+    
+  }
+  
+  @Test
+  public void show_error_stacktrace() {
+    Exception e = new NullPointerException("NPE");
+    e = new IllegalStateException("Error", e);
+    when(cli.isDisplayStackTrace()).thenReturn(true);
+    
+    EmbeddedRunner runner = mock(EmbeddedRunner.class);
+    doThrow(e).when(runner).runAnalysis(any(Properties.class));
     when(runnerFactory.create(any(Properties.class))).thenReturn(runner);
 
-    Main main = new Main(exit, cli, conf, runnerFactory);
+    Main main = new Main(exit, cli, conf, runnerFactory, logs);
     main.execute();
 
     verify(runner).stop();
     verify(exit).exit(Exit.ERROR);
+    verify(logs).error("Error during Sonar runner execution", e);
   }
 
   @Test
@@ -96,7 +120,7 @@ public class MainTest {
     when(runnerFactory.create(any(Properties.class))).thenReturn(runner);
     when(cli.isInteractive()).thenReturn(true);
 
-    Main main = new Main(exit, cli, conf, runnerFactory);
+    Main main = new Main(exit, cli, conf, runnerFactory, logs);
     BufferedReader inputReader = mock(BufferedReader.class);
     when(inputReader.readLine()).thenReturn("");
     when(exit.shouldExit()).thenReturn(false).thenReturn(true);
@@ -115,7 +139,7 @@ public class MainTest {
     when(cli.isDisplayVersionOnly()).thenReturn(true);
     when(conf.properties()).thenReturn(p);
 
-    Main main = new Main(exit, cli, conf, runnerFactory);
+    Main main = new Main(exit, cli, conf, runnerFactory, logs);
     main.execute();
 
     InOrder inOrder = Mockito.inOrder(exit, runnerFactory);
@@ -136,7 +160,7 @@ public class MainTest {
     when(cli.isDebugMode()).thenReturn(true);
     when(cli.isDisplayStackTrace()).thenReturn(true);
 
-    Main main = new Main(exit, cli, conf, runnerFactory);
+    Main main = new Main(exit, cli, conf, runnerFactory, logs);
     main.execute();
 
     verify(runner, times(1)).start();
index 7ca26886c87750110ee5a2a288413c2411f40b90..169ea30c7619bd827af96cabe79cc2a8ea0b6e9f 100644 (file)
  */
 package org.sonar.runner.cli;
 
+import org.sonar.runner.api.LogOutput.Level;
+import org.sonar.runner.api.LogOutput;
+import org.junit.Before;
+
 import java.util.Properties;
+
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.mock;
 import org.junit.Test;
 import org.sonar.runner.api.EmbeddedRunner;
-
 import static org.fest.assertions.Assertions.assertThat;
 
 public class RunnerFactoryTest {
 
   Properties props = new Properties();
+  Logs logs;
+
+  @Before
+  public void setUp() {
+    logs = mock(Logs.class);
+  }
 
   @Test
   public void should_create_embedded_runner() {
     props.setProperty("foo", "bar");
-    EmbeddedRunner runner = new RunnerFactory().create(props);
+    EmbeddedRunner runner = new RunnerFactory(logs).create(props);
 
     assertThat(runner).isInstanceOf(EmbeddedRunner.class);
     assertThat(runner.globalProperties().get("foo")).isEqualTo("bar");
   }
 
+  @Test
+  public void should_fwd_logs() {
+    LogOutput logOutput = new RunnerFactory(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).info(msg);
+    verifyNoMoreInteractions(logs);
+    reset(logs);
+
+    logOutput.log(msg, Level.TRACE);
+    verify(logs).debug(msg);
+    verifyNoMoreInteractions(logs);
+    reset(logs);
+  }
+
 }
index ff8fa0b6eb769578eff0431508084fbf81b6dc4b..1037483f287e6df133c58f7d26abe5f12c171f03 100644 (file)
@@ -27,6 +27,7 @@ import org.junit.Test;
 import static org.fest.assertions.Assertions.assertThat;
 
 public class StatsTest {
+  Logs logs = new Logs();
 
   @Test
   public void shouldPrintStats() throws UnsupportedEncodingException {
@@ -36,7 +37,7 @@ public class StatsTest {
     try {
       System.setOut(new PrintStream(baos));
 
-      new Stats().start().stop();
+      new Stats(logs).start().stop();
 
       String out = baos.toString();
       String[] lines = out.split(System.lineSeparator());
index cfedfe7ee9d6ab008a175412407e4e0be938ef84..e77700321c906a49b20d66cdd20d6d98e192e2b9 100644 (file)
@@ -21,9 +21,11 @@ package org.sonar.runner.cli;
 
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
-
 import static org.mockito.Mockito.verify;
 
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import org.sonar.runner.api.RunnerVersion;
 import org.junit.Before;
 import org.sonar.runner.cli.SystemInfo.System2;
 import org.junit.Test;
@@ -31,10 +33,13 @@ import org.sonar.runner.cli.SystemInfo;
 import static org.fest.assertions.Assertions.assertThat;
 
 public class SystemInfoTest {
-  System2 mockSystem = mock(System2.class);
+  System2 mockSystem;
+  Logs logs;
 
   @Before
   public void setUp() {
+    mockSystem = mock(System2.class);
+    logs = mock(Logs.class);
     SystemInfo.setSystem(mockSystem);
   }
 
@@ -74,11 +79,17 @@ public class SystemInfoTest {
     mockOs();
     mockJava();
     when(mockSystem.getenv("SONAR_RUNNER_OPTS")).thenReturn("arg");
-    
-    SystemInfo.print();
-    
+
+    SystemInfo.print(logs);
+
     verify(mockSystem).getProperty("java.version");
     verify(mockSystem).getProperty("os.version");
     verify(mockSystem).getenv("SONAR_RUNNER_OPTS");
+
+    verify(logs).info("SonarQube Runner " + RunnerVersion.version());
+    verify(logs).info("Java 1.9 oracle (64-bit)");
+    verify(logs).info("linux 2.5 x64");
+    verify(logs).info("SONAR_RUNNER_OPTS=arg");
+    verifyNoMoreInteractions(logs);
   }
 }