From: Simon Brandhof Date: Sat, 6 Apr 2013 13:23:31 +0000 (+0200) Subject: Add unit tests X-Git-Tag: 2.5-rc1~170 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=f2d5c89ce408adfadec79d8ccb81764701a77bac;p=sonar-scanner-cli.git Add unit tests --- diff --git a/sonar-runner-impl/pom.xml b/sonar-runner-impl/pom.xml index 8f77e39..77aca5d 100644 --- a/sonar-runner-impl/pom.xml +++ b/sonar-runner-impl/pom.xml @@ -38,6 +38,11 @@ fest-assert test + + org.mockito + mockito-all + test + diff --git a/sonar-runner-impl/src/main/java/org/sonar/runner/impl/BatchLauncher.java b/sonar-runner-impl/src/main/java/org/sonar/runner/impl/BatchLauncher.java index 949af5e..1d3cdb8 100644 --- a/sonar-runner-impl/src/main/java/org/sonar/runner/impl/BatchLauncher.java +++ b/sonar-runner-impl/src/main/java/org/sonar/runner/impl/BatchLauncher.java @@ -26,35 +26,46 @@ import java.util.List; import java.util.Properties; public class BatchLauncher { + final String isolatedLauncherClass; - public void execute(Properties properties, List extensions) { - FileDownloader fileDownloader = FileDownloader.create(properties); - ServerVersion serverVersion = new ServerVersion(fileDownloader); - List jarFiles; - if (serverVersion.is35Compatible()) { - jarFiles = new Jars35(fileDownloader, new JarExtractor()).download(); - } else if (serverVersion.is30Compatible()) { - String workDir = properties.getProperty("sonar.working.directory"); - jarFiles = new Jars30(fileDownloader).download(new File(workDir), new JarExtractor()); - } else { - throw new IllegalStateException("Sonar " + serverVersion.version() - + " is not supported. Please upgrade Sonar to version 3.0 or more."); - } + /** + * For unit tests + */ + BatchLauncher(String isolatedLauncherClass) { + this.isolatedLauncherClass = isolatedLauncherClass; + } + + public BatchLauncher() { + this.isolatedLauncherClass = "org.sonar.runner.batch.IsolatedLauncher"; + } + + public void execute(Properties props, List extensions) { + ServerConnection serverConnection = ServerConnection.create(props); + ServerVersion serverVersion = new ServerVersion(serverConnection); + JarDownloader jarDownloader = new JarDownloader(props, serverConnection, serverVersion); + doExecute(jarDownloader, props, extensions); + } - String unmaskedPackages = properties.getProperty(InternalProperties.RUNNER_UNMASKED_PACKAGES, ""); + /** + * @return the {@link IsolatedLauncher} instance for unit tests + */ + Object doExecute(JarDownloader jarDownloader, Properties props, List extensions) { + List jarFiles = jarDownloader.download(); + String unmaskedPackages = props.getProperty(InternalProperties.RUNNER_UNMASKED_PACKAGES, ""); IsolatedClassloader classloader = new IsolatedClassloader(getClass().getClassLoader(), unmaskedPackages.split(":")); classloader.addFiles(jarFiles); - delegateExecution(classloader, properties, extensions); + return delegateExecution(classloader, props, extensions); } - private void delegateExecution(IsolatedClassloader classloader, Properties properties, List extensions) { + private Object delegateExecution(IsolatedClassloader classloader, Properties properties, List extensions) { ClassLoader initialContextClassLoader = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(classloader); - Class launcherClass = classloader.findClass("org.sonar.runner.batch.IsolatedLauncher"); + Class launcherClass = classloader.loadClass(isolatedLauncherClass); Method executeMethod = launcherClass.getMethod("execute", Properties.class, List.class); Object launcher = launcherClass.newInstance(); executeMethod.invoke(launcher, properties, extensions); + return launcher; } catch (InvocationTargetException e) { // Unwrap original exception throw new RunnerException("Unable to execute Sonar", e.getTargetException()); diff --git a/sonar-runner-impl/src/main/java/org/sonar/runner/impl/BatchLauncherMain.java b/sonar-runner-impl/src/main/java/org/sonar/runner/impl/BatchLauncherMain.java index afeb993..0c8591a 100644 --- a/sonar-runner-impl/src/main/java/org/sonar/runner/impl/BatchLauncherMain.java +++ b/sonar-runner-impl/src/main/java/org/sonar/runner/impl/BatchLauncherMain.java @@ -27,15 +27,21 @@ import java.util.Collections; import java.util.Properties; public class BatchLauncherMain { - public static void main(String[] args) throws IOException { + private final BatchLauncher launcher; + + BatchLauncherMain(BatchLauncher l) { + this.launcher = l; + } + + void execute(String[] args) throws IOException { if (args.length == 0) { throw new IllegalArgumentException("Missing path to properties file"); } Properties props = loadProperties(args[0]); - new BatchLauncher().execute(props, Collections.emptyList()); + launcher.execute(props, Collections.emptyList()); } - private static Properties loadProperties(String arg) throws IOException { + private Properties loadProperties(String arg) throws IOException { Properties props = new Properties(); FileInputStream input = new FileInputStream(arg); try { @@ -49,4 +55,7 @@ public class BatchLauncherMain { return props; } + public static void main(String[] args) throws IOException { + new BatchLauncherMain(new BatchLauncher()).execute(args); + } } diff --git a/sonar-runner-impl/src/main/java/org/sonar/runner/impl/FileDownloader.java b/sonar-runner-impl/src/main/java/org/sonar/runner/impl/FileDownloader.java deleted file mode 100644 index 3597f92..0000000 --- a/sonar-runner-impl/src/main/java/org/sonar/runner/impl/FileDownloader.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Sonar Runner - Implementation - * Copyright (C) 2011 SonarSource - * dev@sonar.codehaus.org - * - * 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.apache.commons.io.IOUtils; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.net.ConnectException; -import java.net.HttpURLConnection; -import java.net.URL; -import java.net.UnknownHostException; -import java.util.Properties; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -class FileDownloader { - - - static final int CONNECT_TIMEOUT_MILLISECONDS = 30000; - static final int READ_TIMEOUT_MILLISECONDS = 60000; - private static final Pattern CHARSET_PATTERN = Pattern.compile("(?i)\\bcharset=\\s*\"?([^\\s;\"]*)"); - - private final String serverUrl; - private final String userAgent; - - private FileDownloader(String serverUrl, String app, String appVersion) { - this.serverUrl = serverUrl; - this.userAgent = app + "/" + appVersion; - } - - static FileDownloader create(Properties properties) { - String serverUrl = properties.getProperty("sonar.host.url"); - String app = properties.getProperty(InternalProperties.RUNNER_APP); - String appVersion = properties.getProperty(InternalProperties.RUNNER_APP_VERSION); - return new FileDownloader(serverUrl, app, appVersion); - } - - void download(String path, File toFile) { - InputStream input = null; - FileOutputStream output = null; - String fullUrl = serverUrl + path; - try { - if (Logs.isDebugEnabled()) { - Logs.debug("Download " + fullUrl + " to " + toFile.getAbsolutePath()); - } - HttpURLConnection connection = newHttpConnection(new URL(fullUrl)); - int statusCode = connection.getResponseCode(); - if (statusCode != HttpURLConnection.HTTP_OK) { - throw new IOException("Status returned by url : '" + fullUrl + "' is invalid : " + statusCode); - } - output = new FileOutputStream(toFile, false); - input = connection.getInputStream(); - IOUtils.copyLarge(input, output); - - } catch (Exception e) { - if (e instanceof ConnectException || e instanceof UnknownHostException) { - Logs.error("Sonar server '" + serverUrl + "' can not be reached"); - } - IOUtils.closeQuietly(output); - FileUtils.deleteQuietly(toFile); - throw new IllegalStateException("Fail to download: " + fullUrl, e); - - } finally { - IOUtils.closeQuietly(input); - IOUtils.closeQuietly(output); - } - } - - String downloadString(String path) throws IOException { - String fullUrl = serverUrl + path; - HttpURLConnection conn = newHttpConnection(new URL(fullUrl)); - String charset = getCharsetFromContentType(conn.getContentType()); - if (charset == null || "".equals(charset)) { - charset = "UTF-8"; - } - Reader reader = null; - try { - int statusCode = conn.getResponseCode(); - if (statusCode != HttpURLConnection.HTTP_OK) { - throw new IOException("Status returned by url : '" + fullUrl + "' is invalid : " + statusCode); - } - reader = new InputStreamReader(conn.getInputStream(), charset); - return IOUtils.toString(reader); - } catch (IOException e) { - if (e instanceof ConnectException || e instanceof UnknownHostException) { - Logs.error("Sonar server '" + serverUrl + "' can not be reached"); - } - throw e; - - } finally { - IOUtils.closeQuietly(reader); - conn.disconnect(); - } - } - - private HttpURLConnection newHttpConnection(URL url) throws IOException { - //TODO send credentials - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - connection.setConnectTimeout(CONNECT_TIMEOUT_MILLISECONDS); - connection.setReadTimeout(READ_TIMEOUT_MILLISECONDS); - connection.setInstanceFollowRedirects(true); - connection.setRequestMethod("GET"); - connection.setRequestProperty("User-Agent", userAgent); - return connection; - } - - /** - * Parse out a charset from a content type header. - * - * @param contentType e.g. "text/html; charset=EUC-JP" - * @return "EUC-JP", or null if not found. Charset is trimmed and upper-cased. - */ - static String getCharsetFromContentType(String contentType) { - if (contentType == null) { - return null; - } - - Matcher m = CHARSET_PATTERN.matcher(contentType); - if (m.find()) { - return m.group(1).trim().toUpperCase(); - } - return null; - } -} diff --git a/sonar-runner-impl/src/main/java/org/sonar/runner/impl/JarDownloader.java b/sonar-runner-impl/src/main/java/org/sonar/runner/impl/JarDownloader.java new file mode 100644 index 0000000..7517f7b --- /dev/null +++ b/sonar-runner-impl/src/main/java/org/sonar/runner/impl/JarDownloader.java @@ -0,0 +1,58 @@ +/* + * Sonar Runner - Implementation + * Copyright (C) 2011 SonarSource + * dev@sonar.codehaus.org + * + * 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 java.io.File; +import java.util.List; +import java.util.Properties; + +class JarDownloader { + private final ServerConnection serverConnection; + private final ServerVersion serverVersion; + private final Properties props; + + JarDownloader(Properties props, ServerConnection conn, ServerVersion version) { + this.props = props; + this.serverConnection = conn; + this.serverVersion = version; + } + + List download() { + List jarFiles; + if (serverVersion.is35Compatible()) { + jarFiles = download35(); + } else if (serverVersion.is30Compatible()) { + jarFiles = download30(); + } else { + throw new IllegalStateException("Sonar " + serverVersion.version() + + " is not supported. Please upgrade Sonar to version 3.0 or more."); + } + return jarFiles; + } + + List download30() { + String workDir = props.getProperty("sonar.working.directory"); + return new Jars30(serverConnection).download(new File(workDir), new JarExtractor()); + } + + List download35() { + return new Jars35(serverConnection, new JarExtractor()).download(); + } +} diff --git a/sonar-runner-impl/src/main/java/org/sonar/runner/impl/Jars30.java b/sonar-runner-impl/src/main/java/org/sonar/runner/impl/Jars30.java index b12536a..3ea1c7e 100644 --- a/sonar-runner-impl/src/main/java/org/sonar/runner/impl/Jars30.java +++ b/sonar-runner-impl/src/main/java/org/sonar/runner/impl/Jars30.java @@ -27,9 +27,9 @@ import java.util.List; class Jars30 { private static final String BATCH_PATH = "/batch/"; - private final FileDownloader downloader; + private final ServerConnection downloader; - Jars30(FileDownloader downloader) { + Jars30(ServerConnection downloader) { this.downloader = downloader; } diff --git a/sonar-runner-impl/src/main/java/org/sonar/runner/impl/Jars35.java b/sonar-runner-impl/src/main/java/org/sonar/runner/impl/Jars35.java index eca7a99..b36bd38 100644 --- a/sonar-runner-impl/src/main/java/org/sonar/runner/impl/Jars35.java +++ b/sonar-runner-impl/src/main/java/org/sonar/runner/impl/Jars35.java @@ -34,10 +34,10 @@ class Jars35 { static final String BATCH_PATH = "/batch/"; private final FileCache fileCache; - private final FileDownloader downloader; + private final ServerConnection downloader; private final JarExtractor jarExtractor; - Jars35(FileDownloader downloader, JarExtractor jarExtractor) { + Jars35(ServerConnection downloader, JarExtractor jarExtractor) { this.fileCache = new FileCacheBuilder().setLog(new StandardLog()).build(); this.downloader = downloader; this.jarExtractor = jarExtractor; @@ -72,9 +72,9 @@ class Jars35 { } private static class JarDownloader implements FileCache.Downloader { - private final FileDownloader downloader; + private final ServerConnection downloader; - private JarDownloader(FileDownloader downloader) { + private JarDownloader(ServerConnection downloader) { this.downloader = downloader; } diff --git a/sonar-runner-impl/src/main/java/org/sonar/runner/impl/RunnerException.java b/sonar-runner-impl/src/main/java/org/sonar/runner/impl/RunnerException.java index 718ee4c..facbe7b 100644 --- a/sonar-runner-impl/src/main/java/org/sonar/runner/impl/RunnerException.java +++ b/sonar-runner-impl/src/main/java/org/sonar/runner/impl/RunnerException.java @@ -17,35 +17,10 @@ * 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; -/** - * Exception thrown by the Sonar Runner when something bad happens. - * - * @since 1.2 - */ public class RunnerException extends RuntimeException { - private static final long serialVersionUID = 4810407777585753030L; - - /** - * See {@link RuntimeException} - */ - public RunnerException(String message) { - super(message); - } - - /** - * See {@link RuntimeException} - */ - public RunnerException(Throwable cause) { - super(cause); - } - - /** - * See {@link RuntimeException} - */ public RunnerException(String message, Throwable cause) { super(message, cause); } diff --git a/sonar-runner-impl/src/main/java/org/sonar/runner/impl/ServerConnection.java b/sonar-runner-impl/src/main/java/org/sonar/runner/impl/ServerConnection.java new file mode 100644 index 0000000..ec3510a --- /dev/null +++ b/sonar-runner-impl/src/main/java/org/sonar/runner/impl/ServerConnection.java @@ -0,0 +1,146 @@ +/* + * Sonar Runner - Implementation + * Copyright (C) 2011 SonarSource + * dev@sonar.codehaus.org + * + * 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.apache.commons.io.IOUtils; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.ConnectException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.UnknownHostException; +import java.util.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +class ServerConnection { + + static final int CONNECT_TIMEOUT_MILLISECONDS = 30000; + static final int READ_TIMEOUT_MILLISECONDS = 60000; + private static final Pattern CHARSET_PATTERN = Pattern.compile("(?i)\\bcharset=\\s*\"?([^\\s;\"]*)"); + + private final String serverUrl; + private final String userAgent; + + private ServerConnection(String serverUrl, String app, String appVersion) { + this.serverUrl = serverUrl; + this.userAgent = app + "/" + appVersion; + } + + static ServerConnection create(Properties properties) { + String serverUrl = properties.getProperty("sonar.host.url"); + String app = properties.getProperty(InternalProperties.RUNNER_APP); + String appVersion = properties.getProperty(InternalProperties.RUNNER_APP_VERSION); + return new ServerConnection(serverUrl, app, appVersion); + } + + void download(String path, File toFile) { + InputStream input = null; + FileOutputStream output = null; + String fullUrl = serverUrl + path; + try { + if (Logs.isDebugEnabled()) { + Logs.debug("Download " + fullUrl + " to " + toFile.getAbsolutePath()); + } + HttpURLConnection connection = newHttpConnection(new URL(fullUrl)); + int statusCode = connection.getResponseCode(); + if (statusCode != HttpURLConnection.HTTP_OK) { + throw new IOException("Status returned by url : '" + fullUrl + "' is invalid : " + statusCode); + } + output = new FileOutputStream(toFile, false); + input = connection.getInputStream(); + IOUtils.copyLarge(input, output); + + } catch (Exception e) { + if (e instanceof ConnectException || e instanceof UnknownHostException) { + Logs.error("Sonar server '" + serverUrl + "' can not be reached"); + } + IOUtils.closeQuietly(output); + FileUtils.deleteQuietly(toFile); + throw new IllegalStateException("Fail to download: " + fullUrl, e); + + } finally { + IOUtils.closeQuietly(input); + IOUtils.closeQuietly(output); + } + } + + String downloadString(String path) throws IOException { + String fullUrl = serverUrl + path; + HttpURLConnection conn = newHttpConnection(new URL(fullUrl)); + String charset = getCharsetFromContentType(conn.getContentType()); + if (charset == null || "".equals(charset)) { + charset = "UTF-8"; + } + Reader reader = null; + try { + int statusCode = conn.getResponseCode(); + if (statusCode != HttpURLConnection.HTTP_OK) { + throw new IOException("Status returned by url : '" + fullUrl + "' is invalid : " + statusCode); + } + reader = new InputStreamReader(conn.getInputStream(), charset); + return IOUtils.toString(reader); + } catch (IOException e) { + if (e instanceof ConnectException || e instanceof UnknownHostException) { + Logs.error("Sonar server '" + serverUrl + "' can not be reached"); + } + throw e; + + } finally { + IOUtils.closeQuietly(reader); + conn.disconnect(); + } + } + + private HttpURLConnection newHttpConnection(URL url) throws IOException { + //TODO send credentials + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setConnectTimeout(CONNECT_TIMEOUT_MILLISECONDS); + connection.setReadTimeout(READ_TIMEOUT_MILLISECONDS); + connection.setInstanceFollowRedirects(true); + connection.setRequestMethod("GET"); + connection.setRequestProperty("User-Agent", userAgent); + return connection; + } + + /** + * Parse out a charset from a content type header. + * + * @param contentType e.g. "text/html; charset=EUC-JP" + * @return "EUC-JP", or null if not found. Charset is trimmed and upper-cased. + */ + static String getCharsetFromContentType(String contentType) { + if (contentType == null) { + return null; + } + + Matcher m = CHARSET_PATTERN.matcher(contentType); + if (m.find()) { + return m.group(1).trim().toUpperCase(); + } + return null; + } +} diff --git a/sonar-runner-impl/src/main/java/org/sonar/runner/impl/ServerVersion.java b/sonar-runner-impl/src/main/java/org/sonar/runner/impl/ServerVersion.java index 8f5af45..423fde1 100644 --- a/sonar-runner-impl/src/main/java/org/sonar/runner/impl/ServerVersion.java +++ b/sonar-runner-impl/src/main/java/org/sonar/runner/impl/ServerVersion.java @@ -27,11 +27,11 @@ class ServerVersion { private static final String[] LESS_THAN_3_0 = {"0", "1", "2"}; private static final String[] LESS_THAN_3_5 = {"0", "1", "2", "3.0", "3.1", "3.2", "3.3", "3.4"}; - private final FileDownloader fileDownloader; + private final ServerConnection serverConnection; private String version; - ServerVersion(FileDownloader fileDownloader) { - this.fileDownloader = fileDownloader; + ServerVersion(ServerConnection serverConnection) { + this.serverConnection = serverConnection; } String version() { @@ -46,7 +46,7 @@ class ServerVersion { private String downloadVersion() { String result; try { - result = fileDownloader.downloadString("/api/server/version"); + result = serverConnection.downloadString("/api/server/version"); } catch (IOException e) { throw new IllegalStateException("Fail to request server version", e); } diff --git a/sonar-runner-impl/src/test/java/org/sonar/runner/impl/BatchLauncherMainTest.java b/sonar-runner-impl/src/test/java/org/sonar/runner/impl/BatchLauncherMainTest.java new file mode 100644 index 0000000..d72d8b8 --- /dev/null +++ b/sonar-runner-impl/src/test/java/org/sonar/runner/impl/BatchLauncherMainTest.java @@ -0,0 +1,80 @@ +/* + * Sonar Runner - Implementation + * Copyright (C) 2011 SonarSource + * dev@sonar.codehaus.org + * + * 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.junit.Test; +import org.mockito.ArgumentMatcher; + +import java.io.File; +import java.net.URL; +import java.util.List; +import java.util.Properties; + +import static org.fest.assertions.Fail.fail; +import static org.mockito.Matchers.argThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +public class BatchLauncherMainTest { + + BatchLauncher launcher = mock(BatchLauncher.class); + + @Test + public void should_load_properties_and_execute() throws Exception { + URL url = getClass().getResource("/org/sonar/runner/impl/BatchLauncherMainTest/props.properties"); + BatchLauncherMain main = new BatchLauncherMain(launcher); + main.execute(new String[]{new File(url.toURI()).getAbsolutePath()}); + + verify(launcher).execute(argThat(new ArgumentMatcher() { + @Override + public boolean matches(Object o) { + return ((Properties) o).get("sonar.login").equals("foo"); + } + }), argThat(new ArgumentMatcher>() { + @Override + public boolean matches(Object o) { + return ((List) o).isEmpty(); + } + })); + } + + @Test + public void should_fail_if_missing_path_to_properties_file() { + try { + BatchLauncherMain main = new BatchLauncherMain(launcher); + main.execute(new String[0]); + fail(); + } catch (Exception e) { + // success + } + } + + @Test + public void should_fail_if_properties_file_does_not_exist() { + try { + BatchLauncherMain main = new BatchLauncherMain(launcher); + main.execute(new String[]{"unknown/file.properties"}); + fail(); + } catch (Exception e) { + // success + } + + } +} diff --git a/sonar-runner-impl/src/test/java/org/sonar/runner/impl/BatchLauncherTest.java b/sonar-runner-impl/src/test/java/org/sonar/runner/impl/BatchLauncherTest.java new file mode 100644 index 0000000..2d8f2e7 --- /dev/null +++ b/sonar-runner-impl/src/test/java/org/sonar/runner/impl/BatchLauncherTest.java @@ -0,0 +1,103 @@ +/* + * Sonar Runner - Implementation + * Copyright (C) 2011 SonarSource + * dev@sonar.codehaus.org + * + * 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.junit.Test; +import org.sonar.runner.batch.IsolatedLauncher; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Properties; + +import static org.fest.assertions.Assertions.assertThat; +import static org.fest.assertions.Fail.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; + +public class BatchLauncherTest { + + JarDownloader jarDownloader = mock(JarDownloader.class); + + @Test + public void should_download_jars_and_execute_batch() { + BatchLauncher launcher = new BatchLauncher(FakeIsolatedLauncher.class.getName()); + Properties props = new Properties(); + props.put("foo", "bar"); + + // Unmask the current classloader in order to access FakeIsolatedLauncher + props.put(InternalProperties.RUNNER_UNMASKED_PACKAGES, "org.sonar.runner.impl"); + List extensions = new ArrayList(); + + FakeIsolatedLauncher isolatedLauncher = (FakeIsolatedLauncher) launcher.doExecute(jarDownloader, props, extensions); + assertThat(isolatedLauncher.props.get("foo")).isEqualTo("bar"); + assertThat(isolatedLauncher.extensions).isSameAs(extensions); + verify(jarDownloader).download(); + } + + @Test + public void should_use_isolated_classloader() { + BatchLauncher launcher = new BatchLauncher(FakeIsolatedLauncher.class.getName()); + Properties props = new Properties(); + + // The current classloader in not available -> fail to load FakeIsolatedLauncher + props.put(InternalProperties.RUNNER_UNMASKED_PACKAGES, ""); + try { + launcher.doExecute(jarDownloader, props, Collections.emptyList()); + fail(); + } catch (RunnerException e) { + // success + } + } + + @Test + public void verify_isolated_classloader_name() { + // the class IsolatedLauncher should not be loaded in the classloader of BatchLauncher, + // that's why it's referenced by its name + assertThat(new BatchLauncher().isolatedLauncherClass).isEqualTo(IsolatedLauncher.class.getName()); + } + + @Test + public void test_real_execution() { + // verify the creation of dependent components + Properties props = new Properties(); + List extensions = Collections.emptyList(); + BatchLauncher launcher = spy(new BatchLauncher()); + doReturn(new Object()).when(launcher).doExecute(any(JarDownloader.class), eq(props), eq(extensions)); + + launcher.execute(props, extensions); + + verify(launcher).execute(props, extensions); + } + + public static class FakeIsolatedLauncher { + public Properties props = null; + public List extensions = null; + + public void execute(Properties props, List extensions) { + this.props = props; + this.extensions = extensions; + } + } +} diff --git a/sonar-runner-impl/src/test/java/org/sonar/runner/impl/JarDownloaderTest.java b/sonar-runner-impl/src/test/java/org/sonar/runner/impl/JarDownloaderTest.java new file mode 100644 index 0000000..9e5ca80 --- /dev/null +++ b/sonar-runner-impl/src/test/java/org/sonar/runner/impl/JarDownloaderTest.java @@ -0,0 +1,72 @@ +/* + * Sonar Runner - Implementation + * Copyright (C) 2011 SonarSource + * dev@sonar.codehaus.org + * + * 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.junit.Test; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import static org.fest.assertions.Assertions.assertThat; +import static org.fest.assertions.Fail.fail; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +public class JarDownloaderTest { + + ServerConnection serverConnection = mock(ServerConnection.class); + ServerVersion serverVersion = mock(ServerVersion.class); + Properties props = new Properties(); + JarDownloader downloader = spy(new JarDownloader(props, serverConnection, serverVersion)); + + @Test + public void should_download_3_5_jar_files() { + when(serverVersion.is35Compatible()).thenReturn(true); + doReturn(new ArrayList()).when(downloader).download35(); + List jarFiles = downloader.download(); + assertThat(jarFiles).isNotNull(); + } + + @Test + public void should_download_3_0_jar_files() { + when(serverVersion.is35Compatible()).thenReturn(false); + when(serverVersion.is30Compatible()).thenReturn(true); + doReturn(new ArrayList()).when(downloader).download30(); + List jarFiles = downloader.download(); + assertThat(jarFiles).isNotNull(); + } + + @Test + public void should_fail_if_2_x() { + when(serverVersion.version()).thenReturn("2.10"); + when(serverVersion.is30Compatible()).thenReturn(false); + when(serverVersion.is35Compatible()).thenReturn(false); + try { + downloader.download(); + fail(); + } catch (IllegalStateException e) { + assertThat(e).hasMessage("Sonar 2.10 is not supported. Please upgrade Sonar to version 3.0 or more."); + } + } +} diff --git a/sonar-runner-impl/src/test/java/org/sonar/runner/impl/JarExtractorTest.java b/sonar-runner-impl/src/test/java/org/sonar/runner/impl/JarExtractorTest.java index 0f81031..3cc1247 100644 --- a/sonar-runner-impl/src/test/java/org/sonar/runner/impl/JarExtractorTest.java +++ b/sonar-runner-impl/src/test/java/org/sonar/runner/impl/JarExtractorTest.java @@ -25,6 +25,7 @@ import org.junit.Test; import java.io.File; import static org.fest.assertions.Assertions.assertThat; +import static org.fest.assertions.Fail.fail; public class JarExtractorTest { @Test @@ -34,4 +35,14 @@ public class JarExtractorTest { assertThat(FileUtils.readFileToString(jarFile, "UTF-8")).isEqualTo("Fake jar for unit tests"); assertThat(jarFile.toURI().toURL().toString()).doesNotContain("jar:file"); } + + @Test + public void should_fail_to_extract() throws Exception { + try { + new JarExtractor().extract("unknown"); + fail(); + } catch (IllegalStateException e) { + assertThat(e).hasMessage("Fail to extract unknown.jar"); + } + } } diff --git a/sonar-runner-impl/src/test/java/org/sonar/runner/impl/ServerVersionTest.java b/sonar-runner-impl/src/test/java/org/sonar/runner/impl/ServerVersionTest.java new file mode 100644 index 0000000..5e58519 --- /dev/null +++ b/sonar-runner-impl/src/test/java/org/sonar/runner/impl/ServerVersionTest.java @@ -0,0 +1,122 @@ +/* + * Sonar Runner - Implementation + * Copyright (C) 2011 SonarSource + * dev@sonar.codehaus.org + * + * 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.junit.Test; + +import java.net.ConnectException; + +import static org.fest.assertions.Assertions.assertThat; +import static org.fest.assertions.Fail.fail; +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 ServerVersionTest { + + ServerConnection connection = mock(ServerConnection.class); + ServerVersion version = new ServerVersion(connection); + + @Test + public void should_fail_on_connection_error() throws Exception { + when(connection.downloadString("/api/server/version")).thenThrow(new ConnectException()); + try { + version.version(); + fail(); + } catch (IllegalStateException e) { + // success + } + } + + @Test + public void should_fail_if_bad_version() throws Exception { + when(connection.downloadString("/api/server/version")).thenReturn(""); + try { + version.version(); + fail(); + } catch (IllegalStateException e) { + assertThat(e).hasMessage("Server version is not set"); + } + } + + @Test + public void test_2_x() throws Exception { + when(connection.downloadString("/api/server/version")).thenReturn("2.10"); + assertThat(version.version()).isEqualTo("2.10"); + assertThat(version.is30Compatible()).isFalse(); + assertThat(version.is35Compatible()).isFalse(); + verify(connection, times(1)).downloadString("/api/server/version"); + } + + @Test + public void test_3_0() throws Exception { + when(connection.downloadString("/api/server/version")).thenReturn("3.0"); + assertThat(version.version()).isEqualTo("3.0"); + assertThat(version.is30Compatible()).isTrue(); + assertThat(version.is35Compatible()).isFalse(); + verify(connection, times(1)).downloadString("/api/server/version"); + } + + @Test + public void test_3_1() throws Exception { + when(connection.downloadString("/api/server/version")).thenReturn("3.1"); + assertThat(version.version()).isEqualTo("3.1"); + assertThat(version.is30Compatible()).isTrue(); + assertThat(version.is35Compatible()).isFalse(); + verify(connection, times(1)).downloadString("/api/server/version"); + } + + @Test + public void test_3_5() throws Exception { + when(connection.downloadString("/api/server/version")).thenReturn("3.5"); + assertThat(version.version()).isEqualTo("3.5"); + assertThat(version.is30Compatible()).isTrue(); + assertThat(version.is35Compatible()).isTrue(); + verify(connection, times(1)).downloadString("/api/server/version"); + } + + @Test + public void test_3_5_1() throws Exception { + when(connection.downloadString("/api/server/version")).thenReturn("3.5.1"); + assertThat(version.version()).isEqualTo("3.5.1"); + assertThat(version.is30Compatible()).isTrue(); + assertThat(version.is35Compatible()).isTrue(); + verify(connection, times(1)).downloadString("/api/server/version"); + } + + @Test + public void test_3_6() throws Exception { + when(connection.downloadString("/api/server/version")).thenReturn("3.6"); + assertThat(version.version()).isEqualTo("3.6"); + assertThat(version.is30Compatible()).isTrue(); + assertThat(version.is35Compatible()).isTrue(); + verify(connection, times(1)).downloadString("/api/server/version"); + } + + @Test + public void test_4_0() throws Exception { + when(connection.downloadString("/api/server/version")).thenReturn("4.0"); + assertThat(version.version()).isEqualTo("4.0"); + assertThat(version.is30Compatible()).isTrue(); + assertThat(version.is35Compatible()).isTrue(); + verify(connection, times(1)).downloadString("/api/server/version"); + } +} diff --git a/sonar-runner-impl/src/test/resources/org/sonar/runner/impl/BatchLauncherMainTest/props.properties b/sonar-runner-impl/src/test/resources/org/sonar/runner/impl/BatchLauncherMainTest/props.properties new file mode 100644 index 0000000..82640ae --- /dev/null +++ b/sonar-runner-impl/src/test/resources/org/sonar/runner/impl/BatchLauncherMainTest/props.properties @@ -0,0 +1,2 @@ +sonar.login=foo +sonar.password=bar \ No newline at end of file