From 09208690d6e97b2d0c6d11e9d0350563dddc799f Mon Sep 17 00:00:00 2001 From: Duarte Meneses Date: Tue, 15 Nov 2016 16:50:03 +0100 Subject: [PATCH] SLI-123 Add ITs standalone mode --- build.gradle | 4 +- cix.sh | 4 + gradle.properties | 2 + its/LICENSE | 17 ++ its/build.gradle | 52 ++++++ .../intellij/its/StandaloneTest.java | 152 ++++++++++++++++++ .../intellij/its/TestClientInputFile.java | 70 ++++++++ 7 files changed, 299 insertions(+), 2 deletions(-) create mode 100644 its/LICENSE create mode 100644 its/build.gradle create mode 100644 its/src/test/java/org/sonarlint/intellij/its/StandaloneTest.java create mode 100644 its/src/test/java/org/sonarlint/intellij/its/TestClientInputFile.java diff --git a/build.gradle b/build.gradle index 4488611a6..4ba67f57a 100644 --- a/build.gradle +++ b/build.gradle @@ -68,8 +68,8 @@ configurations { } dependencies { - compile 'org.sonarsource.sonarlint.core:sonarlint-client-api:2.5.0.36' - compile 'org.sonarsource.sonarlint.core:sonarlint-core:2.5.0.36' + compile "org.sonarsource.sonarlint.core:sonarlint-client-api:$sonarlintCoreVersion" + compile "org.sonarsource.sonarlint.core:sonarlint-core:$sonarlintCoreVersion" compile 'commons-lang:commons-lang:2.6' compile 'com.google.code.findbugs:jsr305:2.0.2' // provided by the core: diff --git a/cix.sh b/cix.sh index a826913f9..ddb8853e0 100644 --- a/cix.sh +++ b/cix.sh @@ -4,3 +4,7 @@ echo "Running with IDEA_VERSION=$IDEA_VERSION" ./gradlew buildPlugin check -Djava.awt.headless=true -Dawt.toolkit=sun.awt.HeadlessToolkit -PijVersion=$IDEA_VERSION --stacktrace +echo "\n\n#### Running ITs ####\n\n" + +./gradlew -p its check --stacktrace + diff --git a/gradle.properties b/gradle.properties index a3f856b64..59cef65d6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,4 @@ version=2.5-SNAPSHOT org.gradle.jvmargs=-XX:MaxPermSize=256M +sonarlintCoreVersion=2.5.0.36 + diff --git a/its/LICENSE b/its/LICENSE new file mode 100644 index 000000000..78c8f9268 --- /dev/null +++ b/its/LICENSE @@ -0,0 +1,17 @@ +SonarLint for IntelliJ IDEA +Copyright (C) 2015 SonarSource +sonarlint@sonarsource.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 diff --git a/its/build.gradle b/its/build.gradle new file mode 100644 index 000000000..ca25fe9a6 --- /dev/null +++ b/its/build.gradle @@ -0,0 +1,52 @@ +#!groovy +// The above triggers groovy syntax highlighting in vim + +plugins { + id "java" + id "com.github.hierynomus.license" version "0.11.0" +} + +apply plugin: 'maven' +apply plugin: 'java' +apply plugin: 'license' + +group = 'org.sonarsource.sonarlint.intellij.its' +description = 'ITs for SonarLint IntelliJ' + +sourceCompatibility = 1.8 +targetCompatibility = 1.8 + +repositories { + jcenter() + mavenLocal() + mavenCentral() + maven { + url "https://repox.sonarsource.com/sonarsource" + } +} + +def props = new Properties() +props.load(new FileInputStream("$project.rootDir/../gradle.properties")) +props.each { prop -> + println prop.key + project.ext.set(prop.key, prop.value) +} + + +dependencies { + testCompile "org.sonarsource.sonarlint.core:sonarlint-client-api:$sonarlintCoreVersion" + testCompile "org.sonarsource.sonarlint.core:sonarlint-core:$sonarlintCoreVersion" + testCompile 'org.sonarsource.orchestrator:sonar-orchestrator:3.12' + testCompile 'org.assertj:assertj-core:2.3.0' + testCompile 'junit:junit:4.11' + testCompile 'org.mockito:mockito-core:1.10.19' +} + +license { + mapping { + java = 'SLASHSTAR_STYLE' + } + strictCheck true +} + + diff --git a/its/src/test/java/org/sonarlint/intellij/its/StandaloneTest.java b/its/src/test/java/org/sonarlint/intellij/its/StandaloneTest.java new file mode 100644 index 000000000..ca9a8cb4b --- /dev/null +++ b/its/src/test/java/org/sonarlint/intellij/its/StandaloneTest.java @@ -0,0 +1,152 @@ +/* + * SonarLint for IntelliJ IDEA + * Copyright (C) 2015 SonarSource + * sonarlint@sonarsource.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.sonarlint.intellij.its; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.sonarsource.sonarlint.core.StandaloneSonarLintEngineImpl; +import org.sonarsource.sonarlint.core.client.api.common.analysis.ClientInputFile; +import org.sonarsource.sonarlint.core.client.api.common.analysis.Issue; +import org.sonarsource.sonarlint.core.client.api.standalone.StandaloneAnalysisConfiguration; +import org.sonarsource.sonarlint.core.client.api.standalone.StandaloneGlobalConfiguration; +import org.sonarsource.sonarlint.core.client.api.standalone.StandaloneSonarLintEngine; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; + +public class StandaloneTest { + private static final Path PLUGINS_FOLDER = Paths.get("../src/main/resources/plugins/"); + @ClassRule + public static TemporaryFolder temp = new TemporaryFolder(); + + private static StandaloneSonarLintEngine sonarlintEngine; + private static File baseDir; + + @BeforeClass + public static void prepare() throws Exception { + StandaloneGlobalConfiguration config = StandaloneGlobalConfiguration.builder() + .addPlugins(getPlugins(PLUGINS_FOLDER).toArray(new URL[0])) + .setSonarLintUserHome(temp.newFolder("sonarlint").toPath()) + .setLogOutput((msg, level) -> System.out.println("[" + level + "]: " + msg)) + .build(); + sonarlintEngine = new StandaloneSonarLintEngineImpl(config); + baseDir = temp.newFolder(); + } + + private static List getPlugins(Path folder) throws IOException { + return Files.list(folder) + .filter(p -> p.getFileName().toString().endsWith(".jar")) + .peek(p -> System.out.println("Plugin: " + p.getFileName())) + .map(p -> { + try { + return p.toUri().toURL(); + } catch (MalformedURLException e) { + throw new IllegalStateException(e); + } + }) + .collect(Collectors.toList()); + } + + @Test + public void simpleJava() throws Exception { + ClientInputFile inputFile = prepareInputFile("Foo.java", + "public class Foo {\n" + + " public void foo() {\n" + + " int x;\n" + + " System.out.println(\"Foo\");\n" + + " System.out.println(\"Foo\"); //NOSONAR\n" + + " }\n" + + "}"); + List issues = analyze(inputFile); + + assertThat(issues) + .extracting("ruleKey", "startLine", "inputFile.path", "severity") + .containsOnly( + tuple("squid:S106", 4, inputFile.getPath(), "MAJOR"), + tuple("squid:S1220", null, inputFile.getPath(), "MINOR"), + tuple("squid:S1481", 3, inputFile.getPath(), "MINOR")); + } + + @Test + public void simpleJavascript() throws Exception { + ClientInputFile inputFile = prepareInputFile("Foo.js", + "var Person = function(first, last, middle) {\n" + + " this.middle = middle; this.last = last;\n" + + "};"); + List issues = analyze(inputFile); + + assertThat(issues) + .extracting("ruleKey", "startLine", "inputFile.path", "severity") + .containsOnly( + tuple("javascript:OneStatementPerLine", 2, inputFile.getPath(), "MAJOR")); + } + + @Test + public void simplePython() throws Exception { + ClientInputFile inputFile = prepareInputFile("Foo.py", "print \"Hello world!\""); + List issues = analyze(inputFile); + + assertThat(issues) + .extracting("ruleKey", "startLine", "inputFile.path", "severity") + .containsOnly( + tuple("python:PrintStatementUsage", 1, inputFile.getPath(), "MAJOR")); + } + + @Test + public void simplePHP() throws Exception { + ClientInputFile inputFile = prepareInputFile("Foo.php", ""); + List issues = analyze(inputFile); + + assertThat(issues) + .extracting("ruleKey", "startLine", "inputFile.path", "severity") + .containsOnly( + tuple("php:S101", 1, inputFile.getPath(), "MINOR")); + } + + private static List analyze(ClientInputFile inputFile) throws IOException { + List issues = new ArrayList<>(); + sonarlintEngine.analyze(new StandaloneAnalysisConfiguration(baseDir.toPath(), + temp.newFolder().toPath(), Collections.singletonList(inputFile), Collections.emptyMap()), issues::add); + return issues; + } + + private static ClientInputFile prepareInputFile(String fileName, String content) throws IOException { + Path testFile = temp.newFile(fileName).toPath(); + System.out.println("Writing: " + testFile); + Files.write(testFile, content.getBytes(StandardCharsets.UTF_8)); + return new TestClientInputFile(testFile, false, StandardCharsets.UTF_8); + } +} diff --git a/its/src/test/java/org/sonarlint/intellij/its/TestClientInputFile.java b/its/src/test/java/org/sonarlint/intellij/its/TestClientInputFile.java new file mode 100644 index 000000000..f175ae0ee --- /dev/null +++ b/its/src/test/java/org/sonarlint/intellij/its/TestClientInputFile.java @@ -0,0 +1,70 @@ +/* + * SonarLint for IntelliJ IDEA + * Copyright (C) 2015 SonarSource + * sonarlint@sonarsource.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.sonarlint.intellij.its; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.sonarsource.sonarlint.core.client.api.common.analysis.ClientInputFile; + +public class TestClientInputFile implements ClientInputFile { + private Path path; + private boolean isTest; + private Charset encoding; + + public TestClientInputFile(final Path path, final boolean isTest, final Charset encoding) { + this.path = path; + this.isTest = isTest; + this.encoding = encoding; + } + + @Override + public String getPath() { + return path.toString(); + } + + @Override + public boolean isTest() { + return isTest; + } + + @Override + public Charset getCharset() { + return encoding; + } + + @Override + public G getClientObject() { + return null; + } + + @Override + public InputStream inputStream() throws IOException { + return Files.newInputStream(path); + } + + @Override + public String contents() throws IOException { + return new String(Files.readAllBytes(path), encoding); + } +}