aboutsummaryrefslogtreecommitdiffstats
path: root/src/test/java/org/sonarsource/scanner
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/java/org/sonarsource/scanner')
-rw-r--r--src/test/java/org/sonarsource/scanner/cli/CliTest.java92
-rw-r--r--src/test/java/org/sonarsource/scanner/cli/ConfTest.java152
-rw-r--r--src/test/java/org/sonarsource/scanner/cli/LogsTest.java83
-rw-r--r--src/test/java/org/sonarsource/scanner/cli/MainTest.java177
-rw-r--r--src/test/java/org/sonarsource/scanner/cli/RunnerFactoryTest.java90
-rw-r--r--src/test/java/org/sonarsource/scanner/cli/ShutdownTest.java90
-rw-r--r--src/test/java/org/sonarsource/scanner/cli/StatsTest.java53
-rw-r--r--src/test/java/org/sonarsource/scanner/cli/SystemInfoTest.java97
8 files changed, 834 insertions, 0 deletions
diff --git a/src/test/java/org/sonarsource/scanner/cli/CliTest.java b/src/test/java/org/sonarsource/scanner/cli/CliTest.java
new file mode 100644
index 0000000..564146c
--- /dev/null
+++ b/src/test/java/org/sonarsource/scanner/cli/CliTest.java
@@ -0,0 +1,92 @@
+/*
+ * SonarQube Scanner
+ * 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.sonarsource.scanner.cli;
+
+import org.junit.Test;
+import org.sonarsource.scanner.cli.Cli;
+import org.sonarsource.scanner.cli.Exit;
+import org.sonarsource.scanner.cli.Logs;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+public class CliTest {
+ Exit exit = mock(Exit.class);
+ Logs logs = new Logs(System.out, System.err);
+ Cli cli = new Cli(exit, logs);
+
+ @Test
+ public void should_parse_empty_arguments() {
+ cli.parse(new String[0]);
+ assertThat(cli.properties()).isNotEmpty();
+ assertThat(cli.isDebugMode()).isFalse();
+ assertThat(cli.isDisplayStackTrace()).isFalse();
+ assertThat(cli.isDisplayVersionOnly()).isFalse();
+ }
+
+ @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");
+ }
+
+ @Test
+ public void dont_allow_interactive_fork() {
+ cli.parse(new String[] {"-i", "-DsonarRunner.mode=fork"});
+ cli.verify();
+ verify(exit).exit(Exit.SUCCESS);
+ }
+
+ @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");
+ }
+
+ @Test
+ public void should_enable_debug_mode() {
+ cli.parse(new String[] {"-X"});
+ assertThat(cli.isDebugMode()).isTrue();
+ assertThat(cli.isDisplayStackTrace()).isTrue();
+ assertThat(cli.properties().get("sonar.verbose")).isEqualTo("true");
+ }
+
+ @Test
+ public void should_enable_stacktrace_log() {
+ cli.parse(new String[] {"-e"});
+ assertThat(cli.isDebugMode()).isFalse();
+ assertThat(cli.isDisplayStackTrace()).isTrue();
+ assertThat(cli.properties().get("sonar.verbose")).isNull();
+ }
+
+ @Test
+ public void should_disable_debug_mode_and_stacktrace_log_by_default() {
+ cli.parse(new String[0]);
+ assertThat(cli.isDebugMode()).isFalse();
+ assertThat(cli.isDisplayStackTrace()).isFalse();
+ assertThat(cli.properties().get("sonar.verbose")).isNull();
+ }
+}
diff --git a/src/test/java/org/sonarsource/scanner/cli/ConfTest.java b/src/test/java/org/sonarsource/scanner/cli/ConfTest.java
new file mode 100644
index 0000000..a6d8149
--- /dev/null
+++ b/src/test/java/org/sonarsource/scanner/cli/ConfTest.java
@@ -0,0 +1,152 @@
+/*
+ * SonarQube Scanner
+ * 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.sonarsource.scanner.cli;
+
+import java.io.File;
+import java.util.Properties;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class ConfTest {
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ Properties args = new Properties();
+ Logs logs = new Logs(System.out, System.err);
+ Cli cli = mock(Cli.class);
+ Conf conf = new Conf(cli, logs);
+
+ @Before
+ public void initConf() {
+ when(cli.properties()).thenReturn(args);
+ }
+
+ @Test
+ public void should_load_global_settings_by_home() throws Exception {
+ File home = new File(getClass().getResource("ConfTest/shouldLoadRunnerSettingsByHome/").toURI());
+ args.setProperty("runner.home", home.getCanonicalPath());
+
+ assertThat(conf.properties().get("sonar.prop")).isEqualTo("value");
+ }
+
+ @Test
+ public void should_not_fail_if_no_home() throws Exception {
+ assertThat(conf.properties()).isNotEmpty();
+ }
+
+ @Test
+ public void should_load_conf_by_direct_path() throws Exception {
+ File settings = new File(getClass().getResource("ConfTest/shouldLoadRunnerSettingsByDirectPath/other-conf.properties").toURI());
+ args.setProperty("runner.settings", settings.getCanonicalPath());
+
+ assertThat(conf.properties().get("sonar.prop")).isEqualTo("otherValue");
+ }
+
+ @Test
+ public void shouldLoadCompleteConfiguration() throws Exception {
+ File runnerHome = new File(getClass().getResource("ConfTest/shouldLoadCompleteConfiguration/runner").toURI());
+ File projectHome = new File(getClass().getResource("ConfTest/shouldLoadCompleteConfiguration/project").toURI());
+ args.setProperty("runner.home", runnerHome.getCanonicalPath());
+ args.setProperty("project.home", projectHome.getCanonicalPath());
+
+ Properties properties = conf.properties();
+
+ assertThat(properties.getProperty("project.prop")).isEqualTo("foo");
+ assertThat(properties.getProperty("overridden.prop")).isEqualTo("project scope");
+ assertThat(properties.getProperty("global.prop")).isEqualTo("jdbc:mysql:localhost/sonar");
+ }
+
+ @Test
+ public void shouldLoadModuleConfiguration() throws Exception {
+ File projectHome = new File(getClass().getResource("ConfTest/shouldLoadModuleConfiguration/project").toURI());
+ args.setProperty("project.home", projectHome.getCanonicalPath());
+
+ Properties properties = conf.properties();
+
+ assertThat(properties.getProperty("module1.sonar.projectName")).isEqualTo("Module 1");
+ assertThat(properties.getProperty("module2.sonar.projectName")).isEqualTo("Module 2");
+ }
+
+ @Test
+ public void shouldSupportDeepModuleConfigurationInRoot() throws Exception {
+ File projectHome = new File(getClass().getResource("ConfTest/shouldSupportDeepModuleConfigurationInRoot/project").toURI());
+ args.setProperty("project.home", projectHome.getCanonicalPath());
+
+ Properties properties = conf.properties();
+
+ assertThat(properties.getProperty("1.sonar.projectName")).isEqualTo("Module 1");
+ assertThat(properties.getProperty("1.11.sonar.projectName")).isEqualTo("Module 11");
+ assertThat(properties.getProperty("1.11.111.sonar.projectName")).isEqualTo("Module 111");
+ assertThat(properties.getProperty("1.12.sonar.projectName")).isEqualTo("Module 12");
+ assertThat(properties.getProperty("2.sonar.projectName")).isEqualTo("Module 2");
+
+ // SONARUNNER-125
+ assertThat(properties.getProperty("11.111.sonar.projectName")).isNull();
+ }
+
+ @Test
+ public void shouldLoadModuleConfigurationOverrideBasedir() throws Exception {
+ File projectHome = new File(getClass().getResource("ConfTest/shouldLoadModuleConfigurationOverrideBasedir/project").toURI());
+ args.setProperty("project.home", projectHome.getCanonicalPath());
+
+ Properties properties = conf.properties();
+
+ assertThat(properties.getProperty("module1.sonar.projectName")).isEqualTo("Module 1");
+ assertThat(properties.getProperty("module2.sonar.projectName")).isEqualTo("Module 2");
+ assertThat(properties.getProperty("module3.sonar.projectName")).isEqualTo("Module 3");
+ }
+
+ @Test
+ public void shouldSupportSettingBaseDirFromCli() throws Exception {
+ File projectHome = new File(getClass().getResource("ConfTest/shouldLoadModuleConfiguration/project").toURI());
+ args.setProperty("project.home", temp.newFolder().getCanonicalPath());
+ args.setProperty("sonar.projectBaseDir", projectHome.getCanonicalPath());
+
+ Properties properties = conf.properties();
+
+ assertThat(properties.getProperty("module1.sonar.projectName")).isEqualTo("Module 1");
+ assertThat(properties.getProperty("module2.sonar.projectName")).isEqualTo("Module 2");
+ }
+
+ @Test
+ public void ignoreEmptyModule() throws Exception {
+ File projectHome = new File(getClass().getResource("ConfTest/emptyModules/project").toURI());
+ args.setProperty("project.home", temp.newFolder().getCanonicalPath());
+ args.setProperty("sonar.projectBaseDir", projectHome.getCanonicalPath());
+
+ conf.properties();
+ }
+
+ @Test
+ public void shouldGetList() {
+ Properties props = new Properties();
+
+ props.put("prop", " foo ,, bar , \n\ntoto,tutu");
+ assertThat(Conf.getListFromProperty(props, "prop")).containsOnly("foo", "bar", "toto", "tutu");
+ }
+
+}
diff --git a/src/test/java/org/sonarsource/scanner/cli/LogsTest.java b/src/test/java/org/sonarsource/scanner/cli/LogsTest.java
new file mode 100644
index 0000000..39bedff
--- /dev/null
+++ b/src/test/java/org/sonarsource/scanner/cli/LogsTest.java
@@ -0,0 +1,83 @@
+/*
+ * SonarQube Scanner
+ * 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.sonarsource.scanner.cli;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.sonarsource.scanner.cli.Logs;
+import java.io.PrintStream;
+
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verify;
+
+public class LogsTest {
+ @Mock
+ private PrintStream stdOut;
+
+ @Mock
+ private PrintStream stdErr;
+
+ private Logs logs;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ logs = new Logs(stdOut, stdErr);
+ }
+
+ @Test
+ public void testInfo() {
+ logs.info("info");
+ verify(stdOut).println("INFO: info");
+ verifyNoMoreInteractions(stdOut, stdErr);
+ }
+
+ @Test
+ public void testError() {
+ Exception e = new NullPointerException("exception");
+ logs.setDisplayStackTrace(false);
+ logs.error("error1");
+ verify(stdErr).println("ERROR: error1");
+
+ logs.error("error2", e);
+ verify(stdErr).println("ERROR: error2");
+
+ verifyNoMoreInteractions(stdOut, stdErr);
+
+ logs.setDisplayStackTrace(true);
+ logs.error("error3", e);
+ verify(stdErr).println("ERROR: error3");
+ // other interactions to print the exception..
+ }
+
+ @Test
+ public void testDebug() {
+ logs.setDebugEnabled(true);
+
+ logs.debug("debug");
+ verify(stdOut).println("DEBUG: debug");
+
+ logs.setDebugEnabled(false);
+ logs.debug("debug");
+ verifyNoMoreInteractions(stdOut, stdErr);
+ }
+}
diff --git a/src/test/java/org/sonarsource/scanner/cli/MainTest.java b/src/test/java/org/sonarsource/scanner/cli/MainTest.java
new file mode 100644
index 0000000..6875d1e
--- /dev/null
+++ b/src/test/java/org/sonarsource/scanner/cli/MainTest.java
@@ -0,0 +1,177 @@
+/*
+ * SonarQube Scanner
+ * 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.sonarsource.scanner.cli;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+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;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.sonar.runner.api.EmbeddedRunner;
+import org.sonarsource.scanner.cli.Cli;
+import org.sonarsource.scanner.cli.Conf;
+import org.sonarsource.scanner.cli.Exit;
+import org.sonarsource.scanner.cli.Logs;
+import org.sonarsource.scanner.cli.Main;
+import org.sonarsource.scanner.cli.RunnerFactory;
+import org.sonarsource.scanner.cli.Shutdown;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class MainTest {
+
+ @Mock
+ private Shutdown shutdown;
+ @Mock
+ private Cli cli;
+ @Mock
+ private Conf conf;
+ @Mock
+ private Properties properties;
+ @Mock
+ private RunnerFactory runnerFactory;
+ @Mock
+ private EmbeddedRunner runner;
+ @Mock
+ private Logs logs;
+
+ @Before
+ public void setUp() throws IOException {
+ MockitoAnnotations.initMocks(this);
+ when(runnerFactory.create(any(Properties.class))).thenReturn(runner);
+ when(conf.properties()).thenReturn(properties);
+
+ }
+
+ @Test
+ public void should_execute_runner() {
+ Main main = new Main(shutdown, cli, conf, runnerFactory, logs);
+ main.execute();
+
+ verify(shutdown).exit(Exit.SUCCESS);
+ verify(runnerFactory).create(properties);
+
+ verify(runner, times(1)).start();
+ verify(runner, times(1)).runAnalysis(properties);
+ verify(runner, times(1)).stop();
+ }
+
+ @Test
+ public void should_stop_on_error() {
+ EmbeddedRunner runner = mock(EmbeddedRunner.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(shutdown, cli, conf, runnerFactory, logs);
+ main.execute();
+
+ verify(runner).stop();
+ verify(shutdown).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(shutdown, cli, conf, runnerFactory, logs);
+ main.execute();
+
+ verify(runner).stop();
+ verify(shutdown).exit(Exit.ERROR);
+ verify(logs).error("Error during Sonar runner execution", e);
+ }
+
+ @Test
+ public void should_not_stop_on_error_in_interactive_mode() throws Exception {
+ EmbeddedRunner runner = mock(EmbeddedRunner.class);
+ doThrow(new IllegalStateException("Error")).when(runner).runAnalysis(any(Properties.class));
+ when(runnerFactory.create(any(Properties.class))).thenReturn(runner);
+ when(cli.isInteractive()).thenReturn(true);
+
+ Main main = new Main(shutdown, cli, conf, runnerFactory, logs);
+ BufferedReader inputReader = mock(BufferedReader.class);
+ when(inputReader.readLine()).thenReturn("");
+ when(shutdown.shouldExit()).thenReturn(false).thenReturn(true);
+ main.setInputReader(inputReader);
+ main.execute();
+
+ verify(runner, times(2)).runAnalysis(any(Properties.class));
+ verify(runner).stop();
+ verify(shutdown).exit(Exit.SUCCESS);
+ }
+
+ @Test
+ public void should_only_display_version() throws IOException {
+
+ Properties p = new Properties();
+ when(cli.isDisplayVersionOnly()).thenReturn(true);
+ when(conf.properties()).thenReturn(p);
+
+ Main main = new Main(shutdown, cli, conf, runnerFactory, logs);
+ main.execute();
+
+ InOrder inOrder = Mockito.inOrder(shutdown, runnerFactory);
+
+ inOrder.verify(shutdown, times(1)).exit(Exit.SUCCESS);
+ inOrder.verify(runnerFactory, times(1)).create(p);
+ inOrder.verify(shutdown, times(1)).exit(Exit.SUCCESS);
+ }
+
+ @Test(timeout = 30000)
+ public void test_interactive_mode() throws IOException {
+ String inputStr = "qwe" + System.lineSeparator() + "qwe" + System.lineSeparator();
+ InputStream input = new ByteArrayInputStream(inputStr.getBytes(StandardCharsets.UTF_8));
+ System.setIn(input);
+ input.close();
+
+ when(cli.isInteractive()).thenReturn(true);
+ when(cli.isDebugMode()).thenReturn(true);
+ when(cli.isDisplayStackTrace()).thenReturn(true);
+
+ Main main = new Main(shutdown, cli, conf, runnerFactory, logs);
+ main.execute();
+
+ verify(runner, times(1)).start();
+ verify(runner, times(3)).runAnalysis(any(Properties.class));
+ verify(runner, times(1)).stop();
+ }
+}
diff --git a/src/test/java/org/sonarsource/scanner/cli/RunnerFactoryTest.java b/src/test/java/org/sonarsource/scanner/cli/RunnerFactoryTest.java
new file mode 100644
index 0000000..1caf5d5
--- /dev/null
+++ b/src/test/java/org/sonarsource/scanner/cli/RunnerFactoryTest.java
@@ -0,0 +1,90 @@
+/*
+ * SonarQube Scanner
+ * 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.sonarsource.scanner.cli;
+
+import org.sonar.runner.api.LogOutput.Level;
+import org.sonarsource.scanner.cli.Logs;
+import org.sonarsource.scanner.cli.RunnerFactory;
+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(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);
+ }
+
+}
diff --git a/src/test/java/org/sonarsource/scanner/cli/ShutdownTest.java b/src/test/java/org/sonarsource/scanner/cli/ShutdownTest.java
new file mode 100644
index 0000000..0d6b3ba
--- /dev/null
+++ b/src/test/java/org/sonarsource/scanner/cli/ShutdownTest.java
@@ -0,0 +1,90 @@
+/*
+ * SonarQube Scanner
+ * 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.sonarsource.scanner.cli;
+
+import com.jayway.awaitility.Duration;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.sonarsource.scanner.cli.Exit;
+import org.sonarsource.scanner.cli.Shutdown;
+
+import static com.jayway.awaitility.Awaitility.await;
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.verify;
+
+public class ShutdownTest {
+ @Mock
+ private Exit exit;
+ private Shutdown shutdown;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ shutdown = new Shutdown(exit, true);
+ }
+
+ @Test
+ public void testShutdown() {
+ shutdown.exit(3);
+ verify(exit).exit(3);
+ }
+
+ @Test(timeout = 60_000)
+ public void testWaitReady() throws InterruptedException {
+ shutdown = new Shutdown(exit, true, 100_000);
+ shutdown.signalReady(false);
+ assertThat(shutdown.shouldExit()).isFalse();
+
+ final Thread t = new HookCaller();
+ t.start();
+
+ await().atMost(Duration.TWO_SECONDS).pollDelay(50, TimeUnit.MILLISECONDS).until(new Callable<Boolean>() {
+ @Override
+ public Boolean call() throws Exception {
+ return t.isAlive();
+ }
+ });
+
+ assertThat(shutdown.shouldExit()).isTrue();
+
+ shutdown.signalReady(true);
+ t.join();
+ }
+
+ @Test(timeout = 60_000)
+ public void testTimeout() throws InterruptedException {
+ shutdown = new Shutdown(exit, true, 0);
+
+ Thread t = new HookCaller();
+ t.start();
+ t.join();
+ }
+
+ private class HookCaller extends Thread {
+ @Override
+ public void run() {
+ shutdown.hook.run();
+ }
+ }
+}
diff --git a/src/test/java/org/sonarsource/scanner/cli/StatsTest.java b/src/test/java/org/sonarsource/scanner/cli/StatsTest.java
new file mode 100644
index 0000000..2d0034e
--- /dev/null
+++ b/src/test/java/org/sonarsource/scanner/cli/StatsTest.java
@@ -0,0 +1,53 @@
+/*
+ * SonarQube Scanner
+ * 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.sonarsource.scanner.cli;
+
+import org.mockito.Mockito;
+import org.sonarsource.scanner.cli.Logs;
+import org.sonarsource.scanner.cli.Stats;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.mock;
+import org.junit.Test;
+import static org.fest.assertions.Assertions.assertThat;
+
+public class StatsTest {
+ private PrintStream stdOut = mock(PrintStream.class);
+ private PrintStream stdErr;
+ private Logs logs = new Logs(stdOut, stdErr);
+
+ @Test
+ public void shouldPrintStats() throws UnsupportedEncodingException {
+ new Stats(logs).start().stop();
+
+ verify(stdOut).println(Mockito.contains("Total time: "));
+ verify(stdOut).println(Mockito.contains("Final Memory: "));
+ }
+
+ @Test
+ public void shouldFormatTime() {
+ assertThat(Stats.formatTime(1 * 60 * 60 * 1000 + 2 * 60 * 1000 + 3 * 1000 + 400)).isEqualTo("1:02:03.400s");
+ assertThat(Stats.formatTime(2 * 60 * 1000 + 3 * 1000 + 400)).isEqualTo("2:03.400s");
+ assertThat(Stats.formatTime(3 * 1000 + 400)).isEqualTo("3.400s");
+ assertThat(Stats.formatTime(400)).isEqualTo("0.400s");
+ }
+}
diff --git a/src/test/java/org/sonarsource/scanner/cli/SystemInfoTest.java b/src/test/java/org/sonarsource/scanner/cli/SystemInfoTest.java
new file mode 100644
index 0000000..67bbf35
--- /dev/null
+++ b/src/test/java/org/sonarsource/scanner/cli/SystemInfoTest.java
@@ -0,0 +1,97 @@
+/*
+ * SonarQube Scanner
+ * 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.sonarsource.scanner.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.sonarsource.scanner.cli.Logs;
+import org.sonarsource.scanner.cli.SystemInfo;
+import org.sonarsource.scanner.cli.SystemInfo.System2;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class SystemInfoTest {
+ System2 mockSystem;
+ Logs logs;
+
+ @Before
+ public void setUp() {
+ mockSystem = mock(System2.class);
+ logs = mock(Logs.class);
+ SystemInfo.setSystem(mockSystem);
+ }
+
+ @Test
+ public void test_java() {
+ mockJava();
+ assertThat(SystemInfo.java()).isEqualTo("Java 1.9 oracle (64-bit)");
+
+ when(mockSystem.getProperty("sun.arch.data.model")).thenReturn("32");
+ assertThat(SystemInfo.java()).isEqualTo("Java 1.9 oracle (32-bit)");
+
+ when(mockSystem.getProperty("sun.arch.data.model")).thenReturn(null);
+ assertThat(SystemInfo.java()).isEqualTo("Java 1.9 oracle");
+ }
+
+ @Test
+ public void test_os() {
+ mockOs();
+
+ assertThat(SystemInfo.os()).isEqualTo("linux 2.5 x64");
+ }
+
+ private void mockJava() {
+ when(mockSystem.getProperty("java.version")).thenReturn("1.9");
+ when(mockSystem.getProperty("java.vendor")).thenReturn("oracle");
+ when(mockSystem.getProperty("sun.arch.data.model")).thenReturn("64");
+ }
+
+ private void mockOs() {
+ when(mockSystem.getProperty("os.version")).thenReturn("2.5");
+ when(mockSystem.getProperty("os.arch")).thenReturn("x64");
+ when(mockSystem.getProperty("os.name")).thenReturn("linux");
+ }
+
+ @Test
+ public void should_print() {
+ mockOs();
+ mockJava();
+ when(mockSystem.getenv("SONAR_RUNNER_OPTS")).thenReturn("arg");
+
+ 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);
+ }
+}