Skip to content

Commit

Permalink
SONARGRADL-111 Avoid nested paths in sonar.sources/sonar.tests (#192)
Browse files Browse the repository at this point in the history
  • Loading branch information
leonardo-pilastri-sonarsource authored Sep 27, 2023
1 parent 8b77bb4 commit b454493
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 11 deletions.
6 changes: 2 additions & 4 deletions src/main/java/org/sonarqube/gradle/AndroidUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,7 @@
import org.gradle.util.GradleVersion;

import static com.android.builder.model.Version.ANDROID_GRADLE_PLUGIN_VERSION;
import static org.sonarqube.gradle.SonarPropertyComputer.SONAR_SOURCES_PROP;
import static org.sonarqube.gradle.SonarPropertyComputer.SONAR_TESTS_PROP;
import static org.sonarqube.gradle.SonarUtils.appendProps;
import static org.sonarqube.gradle.SonarUtils.appendSourcesProp;
import static org.sonarqube.gradle.SonarUtils.nonEmptyOrNull;
import static org.sonarqube.gradle.SonarUtils.setMainClasspathProps;
import static org.sonarqube.gradle.SonarUtils.setTestClasspathProps;
Expand Down Expand Up @@ -329,7 +327,7 @@ private static void populateSonarQubeProps(Map<String, Object> properties, List<
ArrayList::addAll);
List<File> sourcesOrTests = nonEmptyOrNull(srcDirs.stream().filter(File::exists).collect(Collectors.toList()));
if (sourcesOrTests != null) {
appendProps(properties, isTest ? SONAR_TESTS_PROP : SONAR_SOURCES_PROP, sourcesOrTests);
appendSourcesProp(properties, sourcesOrTests, isTest);
}

JavaCompile javaCompile = getJavaCompiler(variant);
Expand Down
10 changes: 5 additions & 5 deletions src/main/java/org/sonarqube/gradle/SonarPropertyComputer.java
Original file line number Diff line number Diff line change
Expand Up @@ -235,12 +235,12 @@ private static void configureForJava(final Project project, final Map<String, Ob
private static void configureForKotlin(Project project, Map<String, Object> properties, Object kotlinProjectExtension) {
Collection<File> sourceDirectories = getKotlinSourceFiles(kotlinProjectExtension, MAIN_SOURCE_SET_SUFFIX);
if (sourceDirectories != null) {
SonarUtils.appendProps(properties, SONAR_SOURCES_PROP, sourceDirectories);
SonarUtils.appendSourcesProp(properties, sourceDirectories, false);
}

Collection<File> testDirectories = getKotlinSourceFiles(kotlinProjectExtension, TEST_SOURCE_SET_SUFFIX);
if (testDirectories != null) {
SonarUtils.appendProps(properties, SONAR_TESTS_PROP, testDirectories);
SonarUtils.appendSourcesProp(properties, testDirectories, true);
}

if (sourceDirectories != null || testDirectories != null) {
Expand Down Expand Up @@ -322,13 +322,13 @@ private static void configureSourceDirsAndJavaClasspath(Project project, Map<Str
SourceSet main = javaPluginConvention.getSourceSets().getAt("main");
Collection<File> sourceDirectories = getJavaSourceFiles(main);
if (sourceDirectories != null) {
SonarUtils.appendProps(properties, SONAR_SOURCES_PROP, sourceDirectories);
SonarUtils.appendSourcesProp(properties, sourceDirectories, false);
}

SourceSet test = javaPluginConvention.getSourceSets().getAt("test");
Collection<File> testDirectories = getJavaSourceFiles(test);
if (testDirectories != null) {
SonarUtils.appendProps(properties, SONAR_TESTS_PROP, testDirectories);
SonarUtils.appendSourcesProp(properties, testDirectories, true);
}

if (sourceDirectories != null || testDirectories != null) {
Expand Down Expand Up @@ -487,7 +487,7 @@ private static void addKotlinBuildScriptsToSources(Project project, Map<String,
buildScripts.add(settingsFile);
}
if (!buildScripts.isEmpty()) {
SonarUtils.appendProps(properties, SONAR_SOURCES_PROP, buildScripts);
SonarUtils.appendSourcesProp(properties, buildScripts, false);
}
}

Expand Down
18 changes: 18 additions & 0 deletions src/main/java/org/sonarqube/gradle/SonarUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,24 @@ static void appendProps(Map<String, Object> properties, String key, Iterable<?>
.forEach(((Collection<Object>) properties.get(key))::add);
}

static void appendSourcesProp(Map<String, Object> properties, Iterable<File> filesToAppend, boolean testSources) {
List<File> filteredList = filterOutSubFiles(filesToAppend);
appendProps(properties, testSources ? SonarPropertyComputer.SONAR_TESTS_PROP : SonarPropertyComputer.SONAR_SOURCES_PROP, filteredList);
}

static List<File> filterOutSubFiles(Iterable<File> files) {
return StreamSupport.stream(files.spliterator(), false)
.filter(file -> {
for (File other : files) {
if (!file.equals(other) && file.getAbsolutePath().startsWith(other.getAbsolutePath())) {
return false;
}
}
return true;
})
.collect(Collectors.toList());
}

static void appendProp(Map<String, Object> properties, String key, Object valueToAppend) {
properties.putIfAbsent(key, new LinkedHashSet<String>());
((Collection<Object>) properties.get(key)).add(valueToAppend);
Expand Down
16 changes: 15 additions & 1 deletion src/test/groovy/org/sonarqube/gradle/AndroidUtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,13 @@
import com.android.build.gradle.internal.lint.AndroidLintTask;
import com.android.builder.model.ApiVersion;
import com.android.builder.model.BuildType;
import com.android.builder.model.SourceProvider;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;
import org.gradle.api.DomainObjectSet;
import org.gradle.api.NamedDomainObjectContainer;
Expand All @@ -47,7 +50,7 @@
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

Expand Down Expand Up @@ -120,12 +123,23 @@ void configureForAndroid_androidPropertiesAreSetForAndroidProject_whenVariantDet
when(baseVariant.getMergedFlavor()).thenReturn(mergedFlavor);
when(baseVariant.getName()).thenReturn("myVariant");

// Set up a sourceSet with a file to test the presence of sonar.sources
SourceProvider javaSource = mock(SourceProvider.class);
File file = mock(File.class);
when(file.exists()).thenReturn(true);
when(file.getAbsolutePath()).thenReturn("src/main/java/manifest.xml");
when(javaSource.getManifestFile()).thenReturn(file);
when(baseVariant.getSourceSets()).thenReturn(List.of(javaSource));

Map<String, Object> resultProperties = new HashMap<>();
AndroidUtils.configureForAndroid(project, "myVariant", resultProperties);

assertEquals(true, resultProperties.get("sonar.android.detected"));
assertEquals(30, resultProperties.get("sonar.android.minsdkversion.min"));
assertEquals(30, resultProperties.get("sonar.android.minsdkversion.max"));
Set<File> sources = (Set<File>) resultProperties.get("sonar.sources");
assertEquals(1, sources.size());
assertTrue(sources.contains(file));
}

}
38 changes: 37 additions & 1 deletion src/test/groovy/org/sonarqube/gradle/SonarQubePluginTest.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ import org.gradle.api.logging.LogLevel
import org.gradle.api.plugins.GroovyPlugin
import org.gradle.api.plugins.JavaBasePlugin
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.SourceSetContainer
import org.gradle.initialization.GradlePropertiesController
import org.gradle.internal.impldep.org.apache.commons.lang.SystemUtils
import org.gradle.testfixtures.ProjectBuilder
Expand Down Expand Up @@ -730,6 +733,7 @@ class SonarQubePluginTest extends Specification {
}
def JVM_SOURCE_FILE_JAVA = normalizePathString("src/test/projects/kotlin-multiplatform-project/src/jvmMain/java/me/user/application/Sample.java")
def JVM_SOURCE_FILE_JAVA_TEST = normalizePathString("src/test/projects/kotlin-multiplatform-project/src/jvmTest/java/me/user/application/SampleTest.java")
def JVM_SOURCE_FILE_KOTLIN = normalizePathString("src/test/projects/kotlin-multiplatform-project/src/jvmMain/kotlin/me.user.application/Sample.kt")
def JVM_SOURCE_FILE_JS = normalizePathString("src/test/projects/kotlin-multiplatform-project/src/jsMain/kotlin/Sample.js")
Expand All @@ -750,6 +754,9 @@ class SonarQubePluginTest extends Specification {
def sonarSources = properties["sonar.sources"].split(",")
assertThat(normalizePathArray(sonarSources))
.containsExactlyInAnyOrder(JVM_SOURCE_FILE_KOTLIN, JVM_SOURCE_FILE_JAVA, JVM_SOURCE_FILE_JS)
def sonarTestSources = properties["sonar.tests"].split(",")
assertThat(normalizePathArray(sonarTestSources))
.containsExactlyInAnyOrder(JVM_SOURCE_FILE_JAVA_TEST)
properties["sonar.java.binaries"] == null
properties["sonar.java.libraries"] == null
Expand Down Expand Up @@ -871,11 +878,12 @@ class SonarQubePluginTest extends Specification {
private void setupKotlinMultiplatformExtension(Project project) {
def jvMainSourceSet = mockKotlinSourceSet("jvmMain", Set.of(new File(JVM_SOURCE_FILE_JAVA), new File(JVM_SOURCE_FILE_KOTLIN)))
def jvTestSourceSet = mockKotlinSourceSet("jvmTest", Set.of(new File(JVM_SOURCE_FILE_JAVA_TEST)))
def jsMainSourceSet = mockKotlinSourceSet("jsMain", Set.of(new File(JVM_SOURCE_FILE_JS)))
def kotlinSourceSetContainer = mock(NamedDomainObjectContainer<KotlinSourceSet>.class)
// return a new stream on each invocation
when(kotlinSourceSetContainer.stream()).then(invocation -> Arrays.stream(jvMainSourceSet, jsMainSourceSet))
when(kotlinSourceSetContainer.stream()).then(invocation -> Arrays.stream(jvMainSourceSet, jvTestSourceSet, jsMainSourceSet))
def multiplatformExtension = mock(KotlinMultiplatformExtension.class)
when(multiplatformExtension.getSourceSets()).thenReturn(kotlinSourceSetContainer)
Expand Down Expand Up @@ -946,4 +954,32 @@ class SonarQubePluginTest extends Specification {
return Paths.get(pathString).normalize().toAbsolutePath();
}
def "avoid nested paths inside sonar.sources"() {
def dir = new File("src/test/projects/java-nested-sources")
def project = ProjectBuilder.builder()
.withName("java-nested-sources")
.withProjectDir(dir)
.build()
project.pluginManager.apply(JavaPlugin)
JavaPluginExtension javaExtension = project.getExtensions().getByType(JavaPluginExtension.class)
SourceSetContainer sourceSets = javaExtension.getSourceSets();
SourceSet mainSourceSet = sourceSets.getByName("main");
mainSourceSet.getJava().srcDir("src/main/java/pck");
mainSourceSet.getJava().srcDir("src/main/java/pck2");
project.pluginManager.apply(SonarQubePlugin)
when:
def properties = project.tasks.sonar.properties.get()
def sources = properties["sonar.sources"].split(",")
def srcMainJavaPath = normalizePathString((dir as String) + "/src/main/java")
def buildFilePath = normalizePathString((dir as String) + "/build.gradle.kts")
then:
assert sources.size() == 2
assert normalizePathArray(sources).contains(buildFilePath)
assert normalizePathArray(sources).contains(srcMainJavaPath)
}
}
4 changes: 4 additions & 0 deletions src/test/projects/java-nested-sources/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
plugins {
java
id("org.sonarqube") version "4.3.1.3277"
}
Empty file.
Empty file.

0 comments on commit b454493

Please sign in to comment.