From 7233e65ccab0ea52ff1d802290c0afbb777b5314 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Burstr=C3=B6m?= Date: Thu, 14 May 2020 14:21:35 +0200 Subject: [PATCH 1/7] improvement: Update .gitignore to avoid files generated by IntelliJ The misc.xml is updated depending on which version of IntelliJ is in use. The compiler.xml is updated based on local settings. The .iml files gets generated by IntelliJ while importing a Gradle project. --- .gitignore | 8 +++++--- .idea/compiler.xml | 37 ------------------------------------- .idea/misc.xml | 5 ----- 3 files changed, 5 insertions(+), 45 deletions(-) delete mode 100644 .idea/compiler.xml delete mode 100644 .idea/misc.xml diff --git a/.gitignore b/.gitignore index 37afb649..3674b13e 100644 --- a/.gitignore +++ b/.gitignore @@ -77,6 +77,8 @@ local.properties # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 # User-specific stuff +.idea/**/misc.xml +.idea/**/compiler.xml .idea/**/workspace.xml .idea/**/tasks.xml .idea/**/usage.statistics.xml @@ -103,9 +105,9 @@ local.properties # When using Gradle or Maven with auto-import, you should exclude module files, # since they will be recreated, and may cause churn. Uncomment if using # auto-import. -# .idea/modules.xml -# .idea/*.iml -# .idea/modules +.idea/modules.xml +.idea/*.iml +.idea/modules # *.iml # *.ipr diff --git a/.idea/compiler.xml b/.idea/compiler.xml deleted file mode 100644 index a0ec8843..00000000 --- a/.idea/compiler.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 25d34a47..00000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file From 24e95f059aca08dbfe7971f0c97aac6d6bc718b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Burstr=C3=B6m?= Date: Thu, 14 May 2020 16:23:46 +0200 Subject: [PATCH 2/7] feat: Create SpotBugs tasks for both Android apps and libs By looping over the variants, it is possible to associate each of them with a given SpotBugs task. Each variant has a compilation task that can be hooked up. --- .../snom/AndroidFunctionalTest.groovy | 20 +++-- .../snom/internal/SpotBugsTaskFactory.java | 74 ++++++++++++------- 2 files changed, 60 insertions(+), 34 deletions(-) diff --git a/src/functionalTest/groovy/com/github/spotbugs/snom/AndroidFunctionalTest.groovy b/src/functionalTest/groovy/com/github/spotbugs/snom/AndroidFunctionalTest.groovy index 48d05f5c..095a60a4 100644 --- a/src/functionalTest/groovy/com/github/spotbugs/snom/AndroidFunctionalTest.groovy +++ b/src/functionalTest/groovy/com/github/spotbugs/snom/AndroidFunctionalTest.groovy @@ -18,7 +18,7 @@ import org.gradle.testkit.runner.BuildResult import org.gradle.testkit.runner.GradleRunner import org.gradle.util.GradleVersion import org.junit.jupiter.api.BeforeEach -import spock.lang.Ignore +import spock.lang.Requires import spock.lang.Specification import static org.gradle.testkit.runner.TaskOutcome.SUCCESS @@ -35,8 +35,8 @@ class AndroidFunctionalTest extends Specification { buildFile = new File(rootDir, 'build.gradle') } - @Ignore("need to install Android SDK") - def "can generate spotbugsMain depending on classes task"() { + @Requires({env['ANDROID_SDK_ROOT']}) + def "can generate spotbugsRelease depending on variant compilation task"() { given: "a Gradle project to build an Android app" GradleRunner runner = GradleRunner.create() @@ -57,7 +57,7 @@ buildscript { """ runner.pluginClasspath.forEach({ file -> buildFile << """ - classpath '${file.absolutePath}' + classpath files('${file.absolutePath}') """ }) buildFile << """ @@ -83,7 +83,7 @@ android { } """ - File sourceDir = rootDir.toPath().resolve("src").resolve("main").resolve("java").toFile() + File sourceDir = new File(rootDir, "src/main/java") sourceDir.mkdirs() File sourceFile = new File(sourceDir, "Foo.java") sourceFile << """ @@ -92,15 +92,19 @@ public class Foo { System.out.println("Hello, SpotBugs!"); } } +""" + File manifestFile = new File(rootDir, "src/main/AndroidManifest.xml") + manifestFile << """ + """ - when: "the spotbugsMain task is executed" + when: "the spotbugsRelease task is executed" BuildResult result = runner - .withArguments(":spotbugsMain") + .withArguments(":spotbugsRelease", '-s') .withGradleVersion(version) .build() then: "gradle runs spotbugsMain successfully" - assertEquals(SUCCESS, result.task(":spotbugsMain").outcome) + assertEquals(SUCCESS, result.task(":spotbugsRelease").outcome) } } diff --git a/src/main/groovy/com/github/spotbugs/snom/internal/SpotBugsTaskFactory.java b/src/main/groovy/com/github/spotbugs/snom/internal/SpotBugsTaskFactory.java index a6d8ade6..692a70c8 100644 --- a/src/main/groovy/com/github/spotbugs/snom/internal/SpotBugsTaskFactory.java +++ b/src/main/groovy/com/github/spotbugs/snom/internal/SpotBugsTaskFactory.java @@ -13,12 +13,19 @@ */ package com.github.spotbugs.snom.internal; -import com.android.build.gradle.tasks.AndroidJavaCompile; +import com.android.build.gradle.AppExtension; +import com.android.build.gradle.BaseExtension; +import com.android.build.gradle.LibraryExtension; +import com.android.build.gradle.api.BaseVariant; import com.github.spotbugs.snom.SpotBugsTask; import org.gradle.api.Action; +import org.gradle.api.DomainObjectSet; +import org.gradle.api.GradleException; +import org.gradle.api.Plugin; import org.gradle.api.Project; import org.gradle.api.plugins.JavaBasePlugin; import org.gradle.api.plugins.JavaPluginConvention; +import org.gradle.api.tasks.compile.JavaCompile; import org.gradle.util.GUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -63,30 +70,45 @@ private void generateForJava(Project project, Action confi private void generateForAndroid( Project project, Action configurationAction) { - project - .getPlugins() - .withId( - "com.android.application", - plugin -> - project - .getTasks() - .withType(AndroidJavaCompile.class) - .all( - task -> { - String name = GUtil.toLowerCamelCase("spotbugs " + task.getVariantName()); - log.debug("Creating SpotBugsTask for {}", task); - project - .getTasks() - .register( - name, - SpotBugsTask.class, - spotbugsTask -> { - spotbugsTask.setSourceDirs(task.getSource()); - spotbugsTask.setClassDirs( - task.getOutputDirectory().getAsFileTree()); - spotbugsTask.setAuxClassPaths(task.getClasspath()); - configurationAction.execute(spotbugsTask); - }); - })); + + @SuppressWarnings("rawtypes") + final Action action = + (Action) + plugin -> { + final BaseExtension baseExtension = + project.getExtensions().getByType(BaseExtension.class); + DomainObjectSet variants; + if (baseExtension instanceof AppExtension) { + variants = ((AppExtension) baseExtension).getApplicationVariants(); + } else if (baseExtension instanceof LibraryExtension) { + variants = ((LibraryExtension) baseExtension).getLibraryVariants(); + } else { + throw new GradleException("Unrecognized Android extension " + baseExtension); + } + variants.all( + (BaseVariant variant) -> { + String spotbugsTaskName = + GUtil.toLowerCamelCase("spotbugs " + variant.getName()); + log.debug("Creating SpotBugsTask for {}", variant.getName()); + project + .getTasks() + .register( + spotbugsTaskName, + SpotBugsTask.class, + spotbugsTask -> { + final JavaCompile javaCompile = + variant.getJavaCompileProvider().get(); + spotbugsTask.setSourceDirs(javaCompile.getSource()); + spotbugsTask.setClassDirs( + project.files(javaCompile.getDestinationDir())); + spotbugsTask.setAuxClassPaths(javaCompile.getClasspath()); + spotbugsTask.dependsOn(javaCompile); + configurationAction.execute(spotbugsTask); + }); + }); + }; + + project.getPlugins().withId("com.android.application", action); + project.getPlugins().withId("com.android.library", action); } } From ce5798900395db0d5ac99bade2bc8e7e0ff553de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Burstr=C3=B6m?= Date: Thu, 14 May 2020 16:42:25 +0200 Subject: [PATCH 3/7] feat: Bump AGP to 3.6.3 and add functional test for it --- build.gradle | 2 +- .../snom/AndroidFunctionalTest.groovy | 77 ++++++++++++++++++- 2 files changed, 76 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index feea5aa6..35aa5b40 100644 --- a/build.gradle +++ b/build.gradle @@ -26,7 +26,7 @@ ext { errorproneVersion = '2.3.4' spotBugsVersion = '4.0.2' slf4jVersion = '1.8.0-beta4' - androidGradlePluginVersion = '3.5.3' + androidGradlePluginVersion = '3.6.3' } dependencies { diff --git a/src/functionalTest/groovy/com/github/spotbugs/snom/AndroidFunctionalTest.groovy b/src/functionalTest/groovy/com/github/spotbugs/snom/AndroidFunctionalTest.groovy index 095a60a4..0d478570 100644 --- a/src/functionalTest/groovy/com/github/spotbugs/snom/AndroidFunctionalTest.groovy +++ b/src/functionalTest/groovy/com/github/spotbugs/snom/AndroidFunctionalTest.groovy @@ -36,7 +36,7 @@ class AndroidFunctionalTest extends Specification { } @Requires({env['ANDROID_SDK_ROOT']}) - def "can generate spotbugsRelease depending on variant compilation task"() { + def "can generate spotbugsRelease depending on variant compilation task with AGP 3.5.3"() { given: "a Gradle project to build an Android app" GradleRunner runner = GradleRunner.create() @@ -104,7 +104,80 @@ public class Foo { .withGradleVersion(version) .build() - then: "gradle runs spotbugsMain successfully" + then: "gradle runs spotbugsRelease successfully" + assertEquals(SUCCESS, result.task(":spotbugsRelease").outcome) + } + + @Requires({env['ANDROID_SDK_ROOT']}) + def "can generate spotbugsRelease depending on variant compilation task with AGP 3.6.3"() { + given: "a Gradle project to build an Android app" + GradleRunner runner = + GradleRunner.create() + .withProjectDir(rootDir) + .withPluginClasspath() + .forwardOutput() + .withGradleVersion(version) + + buildFile << """ +buildscript { + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.6.3' +""" + runner.pluginClasspath.forEach({ file -> + buildFile << """ + classpath files('${file.absolutePath}') +""" + }) + buildFile << """ + } +} + +apply plugin: 'com.android.application' +apply plugin: 'com.github.spotbugs' + +repositories { + google() + jcenter() +} + +android { + compileSdkVersion 29 + buildToolsVersion '29.0.2' + buildTypes { + release { + minifyEnabled false + } + } +} +""" + + File sourceDir = new File(rootDir, "src/main/java") + sourceDir.mkdirs() + File sourceFile = new File(sourceDir, "Foo.java") + sourceFile << """ +public class Foo { + public static void main(String... args) { + System.out.println("Hello, SpotBugs!"); + } +} +""" + File manifestFile = new File(rootDir, "src/main/AndroidManifest.xml") + manifestFile << """ + +""" + + when: "the spotbugsRelease task is executed" + BuildResult result = runner + .withArguments(":spotbugsRelease", '-s') + .withGradleVersion(version) + .build() + + then: "gradle runs spotbugsRelease successfully" assertEquals(SUCCESS, result.task(":spotbugsRelease").outcome) } } From f7f13a59d0e012a8c66ce64602a17b2bdfc93e74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Burstr=C3=B6m?= Date: Thu, 14 May 2020 17:17:50 +0200 Subject: [PATCH 4/7] build: AGP 3.6.3 is compatible with Gradle 5.6.4 and up --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index bd9c506b..7a1cb04e 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - gradle: ['5.6', '6.0', '6.3', '6.4'] + gradle: ['5.6.4', '6.0', '6.3', '6.4'] steps: - uses: actions/checkout@722adc6 with: From 17f57c053dc4a7b70085138f18375061a503003f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Burstr=C3=B6m?= Date: Tue, 2 Jun 2020 08:51:48 +0200 Subject: [PATCH 5/7] feat: Bump AGP to 4.0.0 and add functional test for it --- build.gradle | 2 +- .../snom/AndroidFunctionalTest.groovy | 77 +++++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 35aa5b40..f039c84e 100644 --- a/build.gradle +++ b/build.gradle @@ -26,7 +26,7 @@ ext { errorproneVersion = '2.3.4' spotBugsVersion = '4.0.2' slf4jVersion = '1.8.0-beta4' - androidGradlePluginVersion = '3.6.3' + androidGradlePluginVersion = '4.0.0' } dependencies { diff --git a/src/functionalTest/groovy/com/github/spotbugs/snom/AndroidFunctionalTest.groovy b/src/functionalTest/groovy/com/github/spotbugs/snom/AndroidFunctionalTest.groovy index 0d478570..24ba30cb 100644 --- a/src/functionalTest/groovy/com/github/spotbugs/snom/AndroidFunctionalTest.groovy +++ b/src/functionalTest/groovy/com/github/spotbugs/snom/AndroidFunctionalTest.groovy @@ -22,6 +22,7 @@ import spock.lang.Requires import spock.lang.Specification import static org.gradle.testkit.runner.TaskOutcome.SUCCESS +import static org.junit.Assume.assumeTrue import static org.junit.jupiter.api.Assertions.assertEquals class AndroidFunctionalTest extends Specification { @@ -145,6 +146,82 @@ repositories { jcenter() } +android { + compileSdkVersion 29 + buildToolsVersion '29.0.2' + buildTypes { + release { + minifyEnabled false + } + } +} +""" + + File sourceDir = new File(rootDir, "src/main/java") + sourceDir.mkdirs() + File sourceFile = new File(sourceDir, "Foo.java") + sourceFile << """ +public class Foo { + public static void main(String... args) { + System.out.println("Hello, SpotBugs!"); + } +} +""" + File manifestFile = new File(rootDir, "src/main/AndroidManifest.xml") + manifestFile << """ + +""" + + when: "the spotbugsRelease task is executed" + BuildResult result = runner + .withArguments(":spotbugsRelease", '-s') + .withGradleVersion(version) + .build() + + then: "gradle runs spotbugsRelease successfully" + assertEquals(SUCCESS, result.task(":spotbugsRelease").outcome) + } + + @Requires({env['ANDROID_SDK_ROOT']}) + def "can generate spotbugsRelease depending on variant compilation task with AGP 4.0.0"() { + assumeTrue("AGP 4.0.0 is only supported by Gradle 6.1.1 and up", + GradleVersion.version(version) >= GradleVersion.version("6.1.1")) + + given: "a Gradle project to build an Android app" + GradleRunner runner = + GradleRunner.create() + .withProjectDir(rootDir) + .withPluginClasspath() + .forwardOutput() + .withGradleVersion(version) + + buildFile << """ +buildscript { + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:4.0.0' +""" + runner.pluginClasspath.forEach({ file -> + buildFile << """ + classpath files('${file.absolutePath}') +""" + }) + buildFile << """ + } +} + +apply plugin: 'com.android.application' +apply plugin: 'com.github.spotbugs' + +repositories { + google() + jcenter() +} + android { compileSdkVersion 29 buildToolsVersion '29.0.2' From 50156eee2580281e25154e2c0993ab5b182619a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Burstr=C3=B6m?= Date: Tue, 2 Jun 2020 09:11:38 +0200 Subject: [PATCH 6/7] refactor: Make the Android functional tests much more readable --- .../snom/AndroidFunctionalTest.groovy | 197 +++++------------- 1 file changed, 52 insertions(+), 145 deletions(-) diff --git a/src/functionalTest/groovy/com/github/spotbugs/snom/AndroidFunctionalTest.groovy b/src/functionalTest/groovy/com/github/spotbugs/snom/AndroidFunctionalTest.groovy index 24ba30cb..1a3f5f88 100644 --- a/src/functionalTest/groovy/com/github/spotbugs/snom/AndroidFunctionalTest.groovy +++ b/src/functionalTest/groovy/com/github/spotbugs/snom/AndroidFunctionalTest.groovy @@ -17,6 +17,7 @@ import org.gradle.internal.impldep.com.google.common.io.Files import org.gradle.testkit.runner.BuildResult import org.gradle.testkit.runner.GradleRunner import org.gradle.util.GradleVersion +import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.BeforeEach import spock.lang.Requires import spock.lang.Specification @@ -27,83 +28,28 @@ import static org.junit.jupiter.api.Assertions.assertEquals class AndroidFunctionalTest extends Specification { File rootDir - File buildFile String version = System.getProperty('snom.test.functional.gradle', GradleVersion.current().version) @BeforeEach def setup() { rootDir = Files.createTempDir() - buildFile = new File(rootDir, 'build.gradle') + } + + @AfterEach + void cleanup() { + rootDir.deleteDir() } @Requires({env['ANDROID_SDK_ROOT']}) def "can generate spotbugsRelease depending on variant compilation task with AGP 3.5.3"() { given: "a Gradle project to build an Android app" - GradleRunner runner = - GradleRunner.create() - .withProjectDir(rootDir) - .withPluginClasspath() - .forwardOutput() - .withGradleVersion(version) - - buildFile << """ -buildscript { - repositories { - google() - jcenter() - } - - dependencies { - classpath 'com.android.tools.build:gradle:3.5.3' -""" - runner.pluginClasspath.forEach({ file -> - buildFile << """ - classpath files('${file.absolutePath}') -""" - }) - buildFile << """ - } -} - -apply plugin: 'com.android.application' -apply plugin: 'com.github.spotbugs' - -repositories { - google() - jcenter() -} - -android { - compileSdkVersion 29 - buildToolsVersion '29.0.2' - buildTypes { - release { - minifyEnabled false - } - } -} -""" - - File sourceDir = new File(rootDir, "src/main/java") - sourceDir.mkdirs() - File sourceFile = new File(sourceDir, "Foo.java") - sourceFile << """ -public class Foo { - public static void main(String... args) { - System.out.println("Hello, SpotBugs!"); - } -} -""" - File manifestFile = new File(rootDir, "src/main/AndroidManifest.xml") - manifestFile << """ - -""" + GradleRunner runner = getGradleRunner() + writeBuildFile(runner, '3.5.3') + writeSourceFile() + writeManifestFile() when: "the spotbugsRelease task is executed" - BuildResult result = runner - .withArguments(":spotbugsRelease", '-s') - .withGradleVersion(version) - .build() + BuildResult result = build(runner) then: "gradle runs spotbugsRelease successfully" assertEquals(SUCCESS, result.task(":spotbugsRelease").outcome) @@ -112,71 +58,13 @@ public class Foo { @Requires({env['ANDROID_SDK_ROOT']}) def "can generate spotbugsRelease depending on variant compilation task with AGP 3.6.3"() { given: "a Gradle project to build an Android app" - GradleRunner runner = - GradleRunner.create() - .withProjectDir(rootDir) - .withPluginClasspath() - .forwardOutput() - .withGradleVersion(version) - - buildFile << """ -buildscript { - repositories { - google() - jcenter() - } - - dependencies { - classpath 'com.android.tools.build:gradle:3.6.3' -""" - runner.pluginClasspath.forEach({ file -> - buildFile << """ - classpath files('${file.absolutePath}') -""" - }) - buildFile << """ - } -} - -apply plugin: 'com.android.application' -apply plugin: 'com.github.spotbugs' - -repositories { - google() - jcenter() -} - -android { - compileSdkVersion 29 - buildToolsVersion '29.0.2' - buildTypes { - release { - minifyEnabled false - } - } -} -""" - - File sourceDir = new File(rootDir, "src/main/java") - sourceDir.mkdirs() - File sourceFile = new File(sourceDir, "Foo.java") - sourceFile << """ -public class Foo { - public static void main(String... args) { - System.out.println("Hello, SpotBugs!"); - } -} -""" - File manifestFile = new File(rootDir, "src/main/AndroidManifest.xml") - manifestFile << """ - -""" + GradleRunner runner = getGradleRunner() + writeBuildFile(runner, '3.6.3') + writeSourceFile() + writeManifestFile() when: "the spotbugsRelease task is executed" - BuildResult result = runner - .withArguments(":spotbugsRelease", '-s') - .withGradleVersion(version) - .build() + BuildResult result = build(runner) then: "gradle runs spotbugsRelease successfully" assertEquals(SUCCESS, result.task(":spotbugsRelease").outcome) @@ -188,13 +76,36 @@ public class Foo { GradleVersion.version(version) >= GradleVersion.version("6.1.1")) given: "a Gradle project to build an Android app" + GradleRunner runner = getGradleRunner() + writeBuildFile(runner, '4.0.0') + writeSourceFile() + writeManifestFile() + + when: "the spotbugsRelease task is executed" + BuildResult result = build(runner) + + then: "gradle runs spotbugsRelease successfully" + assertEquals(SUCCESS, result.task(":spotbugsRelease").outcome) + } + + private BuildResult build(GradleRunner runner) { + runner.withArguments(":spotbugsRelease", '-s') + .withGradleVersion(version) + .build() + } + + private GradleRunner getGradleRunner() { GradleRunner runner = GradleRunner.create() - .withProjectDir(rootDir) - .withPluginClasspath() - .forwardOutput() - .withGradleVersion(version) + .withProjectDir(rootDir) + .withPluginClasspath() + .forwardOutput() + .withGradleVersion(version) + runner + } + def writeBuildFile(runner, agpVersion) { + File buildFile = new File(rootDir, 'build.gradle') buildFile << """ buildscript { repositories { @@ -203,7 +114,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:4.0.0' + classpath 'com.android.tools.build:gradle:$agpVersion' """ runner.pluginClasspath.forEach({ file -> buildFile << """ @@ -232,10 +143,11 @@ android { } } """ + } - File sourceDir = new File(rootDir, "src/main/java") - sourceDir.mkdirs() - File sourceFile = new File(sourceDir, "Foo.java") + void writeSourceFile() { + File sourceFile = new File(rootDir, "src/main/java/Foo.java") + sourceFile.parentFile.mkdirs() sourceFile << """ public class Foo { public static void main(String... args) { @@ -243,18 +155,13 @@ public class Foo { } } """ + } + + void writeManifestFile() { File manifestFile = new File(rootDir, "src/main/AndroidManifest.xml") + manifestFile.parentFile.mkdirs() manifestFile << """ """ - - when: "the spotbugsRelease task is executed" - BuildResult result = runner - .withArguments(":spotbugsRelease", '-s') - .withGradleVersion(version) - .build() - - then: "gradle runs spotbugsRelease successfully" - assertEquals(SUCCESS, result.task(":spotbugsRelease").outcome) } } From 16200b2d83daecff7422fdae8ecc8b6ce1da8ef6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Burstr=C3=B6m?= Date: Tue, 2 Jun 2020 09:34:08 +0200 Subject: [PATCH 7/7] feat: Add functional tests for Android libraries as well --- .../snom/AndroidFunctionalTest.groovy | 98 +++++++++++++++++-- 1 file changed, 91 insertions(+), 7 deletions(-) diff --git a/src/functionalTest/groovy/com/github/spotbugs/snom/AndroidFunctionalTest.groovy b/src/functionalTest/groovy/com/github/spotbugs/snom/AndroidFunctionalTest.groovy index 1a3f5f88..ffc32dbb 100644 --- a/src/functionalTest/groovy/com/github/spotbugs/snom/AndroidFunctionalTest.groovy +++ b/src/functionalTest/groovy/com/github/spotbugs/snom/AndroidFunctionalTest.groovy @@ -41,10 +41,10 @@ class AndroidFunctionalTest extends Specification { } @Requires({env['ANDROID_SDK_ROOT']}) - def "can generate spotbugsRelease depending on variant compilation task with AGP 3.5.3"() { + def "can generate spotbugsRelease depending on app variant compilation task with AGP 3.5.3"() { given: "a Gradle project to build an Android app" GradleRunner runner = getGradleRunner() - writeBuildFile(runner, '3.5.3') + writeAppBuildFile(runner, '3.5.3') writeSourceFile() writeManifestFile() @@ -56,10 +56,25 @@ class AndroidFunctionalTest extends Specification { } @Requires({env['ANDROID_SDK_ROOT']}) - def "can generate spotbugsRelease depending on variant compilation task with AGP 3.6.3"() { + def "can generate spotbugsRelease depending on library variant compilation task with AGP 3.5.3"() { + given: "a Gradle project to build an Android library" + GradleRunner runner = getGradleRunner() + writeLibraryBuildFile(runner, '3.5.3') + writeSourceFile() + writeManifestFile() + + when: "the spotbugsRelease task is executed" + BuildResult result = build(runner) + + then: "gradle runs spotbugsRelease successfully" + assertEquals(SUCCESS, result.task(":spotbugsRelease").outcome) + } + + @Requires({env['ANDROID_SDK_ROOT']}) + def "can generate spotbugsRelease depending on app variant compilation task with AGP 3.6.3"() { given: "a Gradle project to build an Android app" GradleRunner runner = getGradleRunner() - writeBuildFile(runner, '3.6.3') + writeAppBuildFile(runner, '3.6.3') writeSourceFile() writeManifestFile() @@ -71,13 +86,46 @@ class AndroidFunctionalTest extends Specification { } @Requires({env['ANDROID_SDK_ROOT']}) - def "can generate spotbugsRelease depending on variant compilation task with AGP 4.0.0"() { + def "can generate spotbugsRelease depending on library variant compilation task with AGP 3.6.3"() { + given: "a Gradle project to build an Android library" + GradleRunner runner = getGradleRunner() + writeLibraryBuildFile(runner, '3.6.3') + writeSourceFile() + writeManifestFile() + + when: "the spotbugsRelease task is executed" + BuildResult result = build(runner) + + then: "gradle runs spotbugsRelease successfully" + assertEquals(SUCCESS, result.task(":spotbugsRelease").outcome) + } + + @Requires({env['ANDROID_SDK_ROOT']}) + def "can generate spotbugsRelease depending on app variant compilation task with AGP 4.0.0"() { assumeTrue("AGP 4.0.0 is only supported by Gradle 6.1.1 and up", GradleVersion.version(version) >= GradleVersion.version("6.1.1")) given: "a Gradle project to build an Android app" GradleRunner runner = getGradleRunner() - writeBuildFile(runner, '4.0.0') + writeAppBuildFile(runner, '4.0.0') + writeSourceFile() + writeManifestFile() + + when: "the spotbugsRelease task is executed" + BuildResult result = build(runner) + + then: "gradle runs spotbugsRelease successfully" + assertEquals(SUCCESS, result.task(":spotbugsRelease").outcome) + } + + @Requires({env['ANDROID_SDK_ROOT']}) + def "can generate spotbugsRelease depending on library variant compilation task with AGP 4.0.0"() { + assumeTrue("AGP 4.0.0 is only supported by Gradle 6.1.1 and up", + GradleVersion.version(version) >= GradleVersion.version("6.1.1")) + + given: "a Gradle project to build an Android library" + GradleRunner runner = getGradleRunner() + writeLibraryBuildFile(runner, '4.0.0') writeSourceFile() writeManifestFile() @@ -104,7 +152,7 @@ class AndroidFunctionalTest extends Specification { runner } - def writeBuildFile(runner, agpVersion) { + def writeAppBuildFile(runner, agpVersion) { File buildFile = new File(rootDir, 'build.gradle') buildFile << """ buildscript { @@ -145,6 +193,42 @@ android { """ } + def writeLibraryBuildFile(runner, agpVersion) { + File buildFile = new File(rootDir, 'build.gradle') + buildFile << """ +buildscript { + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:$agpVersion' +""" + runner.pluginClasspath.forEach({ file -> + buildFile << """ + classpath files('${file.absolutePath}') +""" + }) + buildFile << """ + } +} + +apply plugin: 'com.android.library' +apply plugin: 'com.github.spotbugs' + +repositories { + google() + jcenter() +} + +android { + compileSdkVersion 29 + buildToolsVersion '29.0.2' +} +""" + } + void writeSourceFile() { File sourceFile = new File(rootDir, "src/main/java/Foo.java") sourceFile.parentFile.mkdirs()