/*
* SonarLint for Eclipse ITs
* Copyright (C) 2009-2017 SonarSource SA
* 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 02110-1301, USA.
*/
package org.sonarlint.eclipse.its;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.io.FileUtils;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotEclipseEditor;
import org.junit.ClassRule;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.python.pydev.ui.perspective.PythonPerspectiveFactory;
import org.sonarlint.eclipse.its.bots.JavaPackageExplorerBot;
import org.sonarlint.eclipse.its.bots.PydevPackageExplorerBot;
import org.sonarlint.eclipse.its.bots.SonarLintProjectPropertiesBot;
import org.sonarlint.eclipse.its.utils.JobHelpers;
import org.sonarlint.eclipse.its.utils.SwtBotUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
import static org.junit.Assume.assumeTrue;
public class StandaloneAnalysisTest extends AbstractSonarLintTest {
@ClassRule
public static TemporaryFolder temp = new TemporaryFolder();
@Test
public void shouldAnalyseJava() throws Exception {
SwtBotUtils.openPerspective(bot, JavaUI.ID_PERSPECTIVE);
IProject project = importEclipseProject("java/java-simple", "java-simple");
JobHelpers.waitForJobsToComplete(bot);
new JavaPackageExplorerBot(bot)
.expandAndDoubleClick("java-simple", "src", "hello", "Hello.java");
JobHelpers.waitForJobsToComplete(bot);
List<IMarker> markers = Arrays.asList(project.findMember("src/hello/Hello.java").findMarkers(MARKER_ID, true, IResource.DEPTH_ONE));
assertThat(markers).extracting(markerAttributes(IMarker.LINE_NUMBER, IMarker.MESSAGE)).containsOnly(
tuple(9, "Replace this usage of System.out or System.err by a logger."));
bot.editorByTitle("Hello.java").close();
// Disable auto analysis on open
new JavaPackageExplorerBot(bot)
.openSonarLintProperties("java-simple");
new SonarLintProjectPropertiesBot(bot, "java-simple")
.clickAutoAnalysis()
.ok();
project.deleteMarkers(MARKER_ID, true, IResource.DEPTH_INFINITE);
new JavaPackageExplorerBot(bot)
.expandAndDoubleClick("java-simple", "src", "hello", "Hello.java");
JobHelpers.waitForJobsToComplete(bot);
markers = Arrays.asList(project.findMember("src/hello/Hello.java").findMarkers(MARKER_ID, true, IResource.DEPTH_ONE));
assertThat(markers).isEmpty();
// Disable auto-analysis on save
SWTBotEclipseEditor editor = bot.editorByTitle("Hello.java").toTextEditor();
editor.navigateTo(8, 29);
editor.insertText("2");
editor.save();
JobHelpers.waitForJobsToComplete(bot);
markers = Arrays.asList(project.findMember("src/hello/Hello.java").findMarkers(MARKER_ID, true, IResource.DEPTH_ONE));
assertThat(markers).isEmpty();
// Trigger manual analysis
new JavaPackageExplorerBot(bot)
.triggerManualAnalysis("java-simple", "src", "hello", "Hello.java");
JobHelpers.waitForJobsToComplete(bot);
markers = Arrays.asList(project.findMember("src/hello/Hello.java").findMarkers(MARKER_ID, true, IResource.DEPTH_ONE));
assertThat(markers).extracting(markerAttributes(IMarker.LINE_NUMBER, IMarker.MESSAGE)).containsOnly(
tuple(9, "Replace this usage of System.out or System.err by a logger."));
}
@Test
@Ignore("Tests are not analyzed with SonarJava 4.7.1")
public void shouldAnalyseJavaJunit() throws Exception {
assumeTrue(supportJunit());
SwtBotUtils.openPerspective(bot, JavaUI.ID_PERSPECTIVE);
IProject project = importEclipseProject("java/java-junit", "java-junit");
JobHelpers.waitForJobsToComplete(bot);
new JavaPackageExplorerBot(bot)
.expandAndDoubleClick("java-junit", "src", "hello", "Hello.java");
JobHelpers.waitForJobsToComplete(bot);
List<IMarker> markers = Arrays.asList(project.findMember("src/hello/Hello.java").findMarkers(MARKER_ID, true, IResource.DEPTH_ONE));
assertThat(markers).extracting(markerAttributes(IMarker.LINE_NUMBER, IMarker.MESSAGE)).containsOnly(
tuple(11, "Replace this usage of System.out or System.err by a logger."),
tuple(15, "Remove this unnecessary cast to \"int\".")); // Test that sonar.java.libraries is set
new JavaPackageExplorerBot(bot)
.expandAndDoubleClick("java-junit", "src", "hello", "HelloTest.java");
JobHelpers.waitForJobsToComplete(bot);
List<IMarker> testMarkers = Arrays.asList(project.findMember("src/hello/HelloTest.java").findMarkers(MARKER_ID, true, IResource.DEPTH_ONE));
assertThat(testMarkers).extracting(markerAttributes(IMarker.LINE_NUMBER, IMarker.MESSAGE)).containsOnly(
tuple(10, "Fix or remove this skipped unit test"));
}
@Test
public void shouldAnalyseJava8() throws Exception {
assumeTrue(supportJava8());
SwtBotUtils.openPerspective(bot, JavaUI.ID_PERSPECTIVE);
IProject project = importEclipseProject("java/java8", "java8");
JobHelpers.waitForJobsToComplete(bot);
new JavaPackageExplorerBot(bot)
.expandAndDoubleClick("java8", "src", "hello", "Hello.java");
JobHelpers.waitForJobsToComplete(bot);
List<IMarker> markers = Arrays.asList(project.findMember("src/hello/Hello.java").findMarkers(MARKER_ID, true, IResource.DEPTH_ONE));
assertThat(markers).extracting(markerAttributes(IMarker.LINE_NUMBER, IMarker.MESSAGE)).containsOnly(
tuple(13, "Make this anonymous inner class a lambda")); // Test that sonar.java.source is set
}
// SONARIDE-349
// SONARIDE-350
// SONARIDE-353
@Test
public void shouldAnalyseJavaWithDependentProject() throws Exception {
SwtBotUtils.openPerspective(bot, JavaUI.ID_PERSPECTIVE);
importEclipseProject("java/java-dependent-projects/java-dependent-project", "java-dependent-project");
IProject mainProject = importEclipseProject("java/java-dependent-projects/java-main-project", "java-main-project");
JobHelpers.waitForJobsToComplete(bot);
final IWorkspaceRoot root = workspace.getRoot();
File toBeDeleted = new File(root.getLocation().toFile(), "java-main-project/libs/toBeDeleted.jar");
assertThat(toBeDeleted.delete()).as("Unable to delete JAR to test SONARIDE-350").isTrue();
new JavaPackageExplorerBot(bot)
.expandAndDoubleClick("java-main-project", "src", "use", "UseUtils.java");
JobHelpers.waitForJobsToComplete(bot);
List<IMarker> markers = Arrays.asList(mainProject.findMember("src/use/UseUtils.java").findMarkers(MARKER_ID, true, IResource.DEPTH_ONE));
assertThat(markers).extracting(markerAttributes(IMarker.LINE_NUMBER, IMarker.MESSAGE)).containsOnly(
tuple(9, "Remove this unnecessary cast to \"int\".")); // Test that sonar.java.libraries is set on dependent project
}
@Test
public void shouldAnalysePython() throws Exception {
SwtBotUtils.openPerspective(bot, PythonPerspectiveFactory.PERSPECTIVE_ID);
IProject project = importEclipseProject("python", "python");
bot.shell("Python not configured").activate();
bot.button("Don't ask again").click();
JobHelpers.waitForJobsToComplete(bot);
new PydevPackageExplorerBot(bot)
.expandAndOpen("python", "src", "root", "nested", "exemple.py");
bot.shell("Default Eclipse preferences for PyDev").activate();
bot.button("OK").click();
JobHelpers.waitForJobsToComplete(bot);
List<IMarker> markers = Arrays.asList(project.findMember("src/root/nested/exemple.py").findMarkers(MARKER_ID, true, IResource.DEPTH_ONE));
assertThat(markers).extracting(markerAttributes(IMarker.LINE_NUMBER, IMarker.MESSAGE)).containsOnly(
tuple(9, "Merge this if statement with the enclosing one."),
tuple(10, "Replace print statement by built-in function."),
tuple(9, "Replace \"<>\" by \"!=\"."),
tuple(1, "Remove this commented out code."));
}
@Test
public void shouldAnalyseLinkedFile() throws Exception {
SwtBotUtils.openPerspective(bot, JavaUI.ID_PERSPECTIVE);
IProject project = importEclipseProject("java/java-linked", "java-linked");
JobHelpers.waitForJobsToComplete(bot);
File dotProject = new File(project.getLocation().toFile(), ".project");
String content = FileUtils.readFileToString(dotProject, StandardCharsets.UTF_8);
FileUtils.write(dotProject, content.replace("${PLACEHOLDER}", new File("projects/java/java-linked-target/hello/HelloLinked.java").getAbsolutePath()), StandardCharsets.UTF_8);
project.refreshLocal(IResource.DEPTH_INFINITE, monitor);
new JavaPackageExplorerBot(bot)
.expandAndDoubleClick("java-linked", "src", "hello", "HelloLinked.java");
JobHelpers.waitForJobsToComplete(bot);
List<IMarker> markers = Arrays.asList(project.findMember("src/hello/HelloLinked.java").findMarkers(MARKER_ID, true, IResource.DEPTH_ONE));
assertThat(markers).extracting(markerAttributes(IMarker.LINE_NUMBER, IMarker.MESSAGE)).containsOnly(
tuple(13, "Replace this usage of System.out or System.err by a logger."));
}
@Test
public void shouldAnalyseVirtualProject() throws Exception {
File remoteProjectDir = temp.newFolder();
FileUtils.copyDirectory(new File("projects/java/java-simple"), remoteProjectDir);
SwtBotUtils.openPerspective(bot, JavaUI.ID_PERSPECTIVE);
final IProject rseProject = workspace.getRoot().getProject("Local_java-simple");
workspace.run(new IWorkspaceRunnable() {
@Override
public void run(final IProgressMonitor monitor) throws CoreException {
final IProjectDescription projectDescription = workspace.newProjectDescription(rseProject.getName());
URI uri = remoteProjectDir.toURI();
try {
projectDescription.setLocationURI(new URI("rse", "LOCALHOST", uri.getPath(), null));
} catch (URISyntaxException e) {
throw new IllegalStateException(e);
}
rseProject.create(projectDescription, monitor);
rseProject.open(IResource.NONE, monitor);
}
}, workspace.getRoot(), IWorkspace.AVOID_UPDATE, monitor);
JobHelpers.waitForJobsToComplete(bot);
new JavaPackageExplorerBot(bot)
.expandAndDoubleClick("Local_java-simple", "src", "hello", "Hello.java");
JobHelpers.waitForJobsToComplete(bot);
List<IMarker> markers = Arrays.asList(rseProject.findMember("src/hello/Hello.java").findMarkers(MARKER_ID, true, IResource.DEPTH_ONE));
assertThat(markers).extracting(markerAttributes(IMarker.LINE_NUMBER, IMarker.MESSAGE)).containsOnly(
tuple(9, "Replace this usage of System.out or System.err by a logger."));
}
}