From 3bf1fb06f3bdc17ab06af82b8c7ecb21da838556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Papp=20=28TWiStErRob=29?= Date: Wed, 25 Jan 2023 09:53:32 +0000 Subject: [PATCH 01/13] Suppress usage of SecurityManager, it was deprecated in Java 17 (see https://openjdk.org/jeps/411), but blocking System::exit has no other means yet. https://bugs.openjdk.org/browse/JDK-8199704 will implement it hopefully before removing the classes. --- .../net/twisterrob/gradle/vcs/SVNPlugin.kt | 49 ++++++++++++------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/plugin/versioning/src/main/kotlin/net/twisterrob/gradle/vcs/SVNPlugin.kt b/plugin/versioning/src/main/kotlin/net/twisterrob/gradle/vcs/SVNPlugin.kt index b4cb74306..c9168672e 100644 --- a/plugin/versioning/src/main/kotlin/net/twisterrob/gradle/vcs/SVNPlugin.kt +++ b/plugin/versioning/src/main/kotlin/net/twisterrob/gradle/vcs/SVNPlugin.kt @@ -62,33 +62,48 @@ open class SVNPluginExtension( // key method/closure - used as: def out = doSvnMain( 'your', 'svn', 'args', 'go', 'here' ); @Suppress("unused") - private fun cli(vararg svnArgs: String): String { - System.setSecurityManager(NonExitingSecurityManager) // stop SVN.main from doing a System.exit call - val baos = ByteArrayOutputStream() - val oldSystemOut = System.out - System.setOut(PrintStream(baos)) - try { - SVN.main(svnArgs) - System.out.flush() - return baos.toString() - } finally { - System.setOut(oldSystemOut) - System.setSecurityManager(null) + private fun cli(vararg svnArgs: String): String = + captureSystemOut { + preventExit { SVN.main(svnArgs) } } - } companion object { internal const val NAME: String = "svn" + + @Suppress("DEPRECATION") // TODEL if there's a replacement in https://bugs.openjdk.org/browse/JDK-8199704. + private inline fun preventExit(block: () -> T): T { + val oldSecurityManager = System.getSecurityManager() + System.setSecurityManager(NonExitingSecurityManager) // stop SVN.main from doing a System.exit call + try { + return block() + } finally { + System.setSecurityManager(oldSecurityManager) + } + } + + private inline fun captureSystemOut(block: () -> Unit): String { + val baos = ByteArrayOutputStream() + val oldSystemOut = System.out + System.setOut(PrintStream(baos)) + try { + block() + System.out.flush() + return baos.toString() + } finally { + System.setOut(oldSystemOut) + } + } } - private object NonExitingSecurityManager : SecurityManager() { + private object NonExitingSecurityManager : @Suppress("DEPRECATION") SecurityManager() { override fun checkPermission(perm: Permission) { - // do nothing + // Do nothing, allow it. } - override fun checkExit(status: Int): Nothing = - throw SecurityException() + override fun checkExit(status: Int) { + throw SecurityException() // Prevent it. + } } } From 3f8c4fa717a45a3d2418aa4f20028fb0f8511397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Papp=20=28TWiStErRob=29?= Date: Wed, 25 Jan 2023 10:07:02 +0000 Subject: [PATCH 02/13] Use the better (safere) overload of Runtime.exec() --- .../twisterrob/gradle/quality/development/DevelopmentTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quality/src/test/kotlin/net/twisterrob/gradle/quality/development/DevelopmentTest.kt b/quality/src/test/kotlin/net/twisterrob/gradle/quality/development/DevelopmentTest.kt index 0cc316fec..8d693ca70 100644 --- a/quality/src/test/kotlin/net/twisterrob/gradle/quality/development/DevelopmentTest.kt +++ b/quality/src/test/kotlin/net/twisterrob/gradle/quality/development/DevelopmentTest.kt @@ -85,5 +85,5 @@ class DevelopmentTest : BaseIntgTest() { private fun openHtml(html: File) { assertThat(html, anExistingFile()) - Runtime.getRuntime().exec("""cmd /k "start "" "${html.toURI()}""""") + Runtime.getRuntime().exec(arrayOf("cmd", "/k", "start", "", html.toURI().toString())) } From 968a5bfd8e4d99ea20ce814768b61e753680e107 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Papp=20=28TWiStErRob=29?= Date: Wed, 25 Jan 2023 13:55:38 +0000 Subject: [PATCH 03/13] Use Robolectric 4.9.2 for testing --- .../twisterrob/gradle/android/AndroidBuildPluginIntgTest.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugin/building/src/test/kotlin/net/twisterrob/gradle/android/AndroidBuildPluginIntgTest.kt b/plugin/building/src/test/kotlin/net/twisterrob/gradle/android/AndroidBuildPluginIntgTest.kt index cacceed93..df9af97c9 100644 --- a/plugin/building/src/test/kotlin/net/twisterrob/gradle/android/AndroidBuildPluginIntgTest.kt +++ b/plugin/building/src/test/kotlin/net/twisterrob/gradle/android/AndroidBuildPluginIntgTest.kt @@ -336,7 +336,7 @@ class AndroidBuildPluginIntgTest : BaseAndroidIntgTest() { apply plugin: 'net.twisterrob.kotlin' dependencies { testImplementation 'junit:junit:4.13.1' - testImplementation 'org.robolectric:robolectric:4.4' + testImplementation 'org.robolectric:robolectric:4.9.2' testImplementation 'androidx.test:core:1.3.0' } android.testOptions.unitTests.includeAndroidResources = true @@ -400,7 +400,7 @@ class AndroidBuildPluginIntgTest : BaseAndroidIntgTest() { apply plugin: 'net.twisterrob.kotlin' dependencies { testImplementation 'junit:junit:4.13.1' - testImplementation 'org.robolectric:robolectric:4.4' + testImplementation 'org.robolectric:robolectric:4.9.2' testImplementation 'androidx.test:core:1.3.0' } android.testOptions.unitTests.includeAndroidResources = true @@ -470,7 +470,7 @@ class AndroidBuildPluginIntgTest : BaseAndroidIntgTest() { apply plugin: 'net.twisterrob.kotlin' dependencies { testImplementation 'junit:junit:4.13.1' - testImplementation 'org.robolectric:robolectric:4.4' + testImplementation 'org.robolectric:robolectric:4.9.2' } android.testOptions.unitTests.includeAndroidResources = true tasks.withType(Test).configureEach { From 8b19cab417d357614413502ae2369862b764d017 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Papp=20=28TWiStErRob=29?= Date: Thu, 26 Jan 2023 10:59:08 +0000 Subject: [PATCH 04/13] Set JAVA_HOME per test --- .github/workflows/CI.yml | 26 ++---- build.gradle.kts | 1 + gradle.properties | 9 +- test/build.gradle.kts | 1 + .../gradle/test/GradleRunnerRule.kt | 6 ++ .../gradle/test/GradleRunnerRuleExtension.kt | 2 + .../net/twisterrob/gradle/test/setJavaHome.kt | 87 +++++++++++++++++++ 7 files changed, 110 insertions(+), 22 deletions(-) create mode 100644 test/src/main/kotlin/net/twisterrob/gradle/test/setJavaHome.kt diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index aa207604d..0304b4738 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -33,10 +33,10 @@ jobs: timeout-minutes: 20 needs: validate steps: - - name: Set up JDK 11. + - name: Set up JDK 19. uses: actions/setup-java@v3 with: - java-version: 11 + java-version: 19 distribution: zulu - name: Set up Android SDK. @@ -175,22 +175,11 @@ jobs: steps: - run: echo "Running in response to a ${{ github.event_name }} event, building ${{ github.event.compare }} changes." - - name: Set up JDK(s). - run: | - echo "JAVA8_HOME=$JAVA_HOME_8_X64" | tee --append $GITHUB_ENV - echo "JAVA11_HOME=$JAVA_HOME_11_X64" | tee --append $GITHUB_ENV - case ${{ matrix.gradle-java }} in - 8) - echo "JAVA_HOME=$JAVA_HOME_8_X64" | tee --append $GITHUB_ENV - ;; - 11) - echo "JAVA_HOME=$JAVA_HOME_11_X64" | tee --append $GITHUB_ENV - ;; - *) - echo "Unrecognized matrix.gradle-java=${{ matrix.gradle-java }}." - exit 1 - ;; - esac + - name: Set up JDK 19. + uses: actions/setup-java@v3 + with: + java-version: 19 + distribution: zulu - name: Set up Android SDK. uses: android-actions/setup-android@v2 @@ -304,6 +293,7 @@ jobs: -Pnet.twisterrob.test.android.pluginVersion=${{ matrix.agp }} -Pnet.twisterrob.test.kotlin.pluginVersion=${{ matrix.kotlin }} -Pnet.twisterrob.gradle.runner.gradleVersion=${{ matrix.gradle }} + -Pnet.twisterrob.test.gradle.javaHomeEnv=JAVA_HOME_${{ matrix.gradle-java }}_X64 - name: Upload "${{ env.JOB_NAME }} Test Results XMLs" artifact. if: success() || failure() diff --git a/build.gradle.kts b/build.gradle.kts index 8e1b0d692..e255aaab6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -88,6 +88,7 @@ subprojects { // for GradleRunnerRule to use a different Gradle version for tests "net.twisterrob.gradle.runner.gradleVersion", // for tests to decide dynamically + "net.twisterrob.test.gradle.javaHomeEnv", "net.twisterrob.test.android.pluginVersion", "net.twisterrob.test.kotlin.pluginVersion", "net.twisterrob.test.android.compileSdkVersion", diff --git a/gradle.properties b/gradle.properties index abd935ab6..b82db60f2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -22,13 +22,14 @@ projectVersion=0.15-SNAPSHOT net.twisterrob.test.android.compileSdkVersion=android-30 # Default test substitutions (overridden by .github/workflows/ci.yml with -P) -# 3.1.4, 3.2.1, 3.3.3, 3.4.3, 3.5.4, 3.6.4, 4.0.2, 4.1.3, 4.2.2, 7.0.4, 7.1.3, 7.2.2, 7.3.1 +# AGP: 3.1.4, 3.2.1, 3.3.3, 3.4.3, 3.5.4, 3.6.4, 4.0.2, 4.1.3, 4.2.2, 7.0.4, 7.1.3, 7.2.2, 7.3.1 net.twisterrob.test.android.pluginVersion=7.3.1 -# 3.1.4-7.2.2 -> 1.4.32; 7.3.0- -> 1.6.21 +# AGP 3.1.4-7.2.2 -> 1.4.32; AGP 7.3.0- -> 1.6.21 net.twisterrob.test.kotlin.pluginVersion=1.6.21 -# 4.9, 4.10.3; 5.4.1, 5.6.4, 6.1.1, 6.5.1, 6.7.1, 6.9.2; 7.0.2, 7.2, 7.3.3, 7.4.2, 7.5.1 +# Gradle: 4.9, 4.10.3; 5.4.1, 5.6.4, 6.1.1, 6.5.1, 6.7.1, 6.9.2; 7.0.2, 7.2, 7.3.3, 7.4.2, 7.5.1 net.twisterrob.gradle.runner.gradleVersion=7.6 - +# AGP 3.1.4-4.2.2 -> Java 8; AGP 7.0.0-7.4.0 -> Java 11; AGP 8.0.0- -> Java 17 +net.twisterrob.test.gradle.javaHomeEnv=JAVA11_HOME # Build configuration defaults. diff --git a/test/build.gradle.kts b/test/build.gradle.kts index f65879ce4..c27e89918 100644 --- a/test/build.gradle.kts +++ b/test/build.gradle.kts @@ -20,6 +20,7 @@ dependencies { compileOnly(libs.junit.legacy) compileOnly(libs.junit.api) + compileOnly(libs.mockito.kotlin) compileOnly(libs.annotations.jsr305) compileOnly(libs.annotations.jetbrains) diff --git a/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRule.kt b/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRule.kt index 12a5aeafb..8fbf95268 100644 --- a/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRule.kt +++ b/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRule.kt @@ -71,6 +71,12 @@ open class GradleRunnerRule : TestRule { field = value } + var javaHome = File(System.getProperty("java.home")) + set(value) { + setJavaHome(value) + field = value + } + @Suppress("MemberVisibilityCanBePrivate") // API lateinit var buildFile: File private set diff --git a/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRuleExtension.kt b/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRuleExtension.kt index c7e43bfe0..004794eef 100644 --- a/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRuleExtension.kt +++ b/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRuleExtension.kt @@ -5,6 +5,7 @@ import org.junit.jupiter.api.extension.AfterEachCallback import org.junit.jupiter.api.extension.BeforeEachCallback import org.junit.jupiter.api.extension.ExtensionContext import org.junit.jupiter.api.extension.TestInstancePostProcessor +import java.io.File open class GradleRunnerRuleExtension : TestInstancePostProcessor, BeforeEachCallback, AfterEachCallback { @@ -15,6 +16,7 @@ open class GradleRunnerRuleExtension : TestInstancePostProcessor, BeforeEachCall override fun setUp() { super.setUp() file(readInitGradle(), "init.gradle.kts") + javaHome = File(System.getenv(System.getProperty("net.twisterrob.test.gradle.javaHomeEnv"))) } private fun strictWarningMode(): Array = diff --git a/test/src/main/kotlin/net/twisterrob/gradle/test/setJavaHome.kt b/test/src/main/kotlin/net/twisterrob/gradle/test/setJavaHome.kt new file mode 100644 index 000000000..2e337ca25 --- /dev/null +++ b/test/src/main/kotlin/net/twisterrob/gradle/test/setJavaHome.kt @@ -0,0 +1,87 @@ +package net.twisterrob.gradle.test + +import org.gradle.internal.Factory +import org.gradle.internal.service.DefaultServiceRegistry +import org.gradle.tooling.BuildLauncher +import org.gradle.tooling.GradleConnector +import org.gradle.tooling.ProjectConnection +import org.gradle.tooling.internal.consumer.ConnectorServices +import org.gradle.tooling.internal.consumer.DefaultGradleConnector +import org.mockito.kotlin.doAnswer +import org.mockito.kotlin.spy +import org.mockito.kotlin.whenever +import java.io.File + +/** + * Tried to do it by setting JAVA_HOME, but that didn't work, because that would be interpreted by `gradlew`, which doesn't play when running tests using Gradle Test Kit. + * ``` + * runner.withEnvironment(mapOf("JAVA_HOME" to System.getenv("JAVA_HOME").toString())) + * ``` + * Found a method to set the Java Home in the Gradle Test Kit, but that's not publicly delegated. + * Using reflection to intercept a local variable is the only way to set the Java Home. + * + * @see org.gradle.testkit.runner.internal.ToolingApiGradleExecutor.run + * @see org.gradle.tooling.internal.consumer.DefaultBuildLauncher.setJavaHome + */ +internal fun setJavaHome(javaHome: File) { + BuildLauncherInterceptor { + setJavaHome(javaHome) + }.configure() +} + +private class BuildLauncherInterceptor(private val configuration: BuildLauncher.() -> BuildLauncher) { + + fun configure() { + // Need to call launcher.* on a local variable in ToolingApiGradleExecutor.run. + // - launcher is created by connection.newBuild() implemented by DefaultProjectConnection + // - connection is created by gradleConnector.connect() implemented by DefaultGradleConnector + // - gradleConnector is created by GradleConnector.newConnector() delegate to ConnectorServices.createConnector() + // - createConnector uses ConnectorServiceRegistry for dependency injection + // This last one is static, so we can intercept the registry to intercept the launcher. + singletonRegistry = intercept(singletonRegistry) + } + + private fun intercept(registry: DefaultServiceRegistry): DefaultServiceRegistry = + // Tried spying on ConnectorServices\$ConnectorServiceRegistry.createConnectorFactory directly, but it didn't work. + spy(registry).apply { + doAnswer { @Suppress("UNCHECKED_CAST") intercept(it.callRealMethod() as Factory) } + .whenever(this) + .getFactory(DefaultGradleConnector::class.java) + } + + private fun intercept(factory: Factory): Factory = + spy(factory).apply { + doAnswer { intercept(it.callRealMethod() as GradleConnector) } + .whenever(this) + .create() + } + + private fun intercept(connector: GradleConnector): GradleConnector = + spy(connector).apply { + doAnswer { intercept(it.callRealMethod() as ProjectConnection) } + .whenever(this) + .connect() + } + + private fun intercept(connection: ProjectConnection): ProjectConnection = + spy(connection).apply { + doAnswer { intercept(it.callRealMethod() as BuildLauncher) } + .whenever(this) + .newBuild() + } + + private fun intercept(launcher: BuildLauncher): BuildLauncher = + launcher.run(configuration) +} + +private var singletonRegistry: DefaultServiceRegistry + get() = ConnectorServices::class.java + .getDeclaredField("singletonRegistry") + .apply { isAccessible = true } + .get(null) as DefaultServiceRegistry + set(value) { + ConnectorServices::class.java + .getDeclaredField("singletonRegistry") + .apply { isAccessible = true } + .set(null, value) + } From 5d4c096f77efbe6bd85bdfe36dde1df4e097bf3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Papp=20=28TWiStErRob=29?= Date: Thu, 26 Jan 2023 11:09:06 +0000 Subject: [PATCH 05/13] Open up some modules so tests still pass. --- common/build.gradle.kts | 6 ++++++ compat/gradle/build.gradle.kts | 6 ++++++ test/internal/build.gradle.kts | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/common/build.gradle.kts b/common/build.gradle.kts index f2a021614..b3b25afeb 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -37,3 +37,9 @@ tasks.named("compileTestGroovy") { dependsOn(kotlinTask) classpath += files(kotlinTask.map { it.destinationDirectory }) } + +tasks.named("test") { + // TODEL Java 16 vs Gradle 7+ https://github.com/gradle/gradle/issues/18647 + // Example test: TaskCreationConfigurationTest.`registering a task preConfigures, but does not create it` + jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED") +} diff --git a/compat/gradle/build.gradle.kts b/compat/gradle/build.gradle.kts index 38b97ef4f..cbf327d9f 100644 --- a/compat/gradle/build.gradle.kts +++ b/compat/gradle/build.gradle.kts @@ -11,3 +11,9 @@ dependencies { testImplementation(projects.test.internal) } + +tasks.named("test") { + // TODEL Java 16 vs Gradle 7+ https://github.com/gradle/gradle/issues/18647 + // Example test: TaskExtensionsKtTest.`task provider was launched without qualification` + jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED") +} diff --git a/test/internal/build.gradle.kts b/test/internal/build.gradle.kts index 281de3f2f..e7d1dce19 100644 --- a/test/internal/build.gradle.kts +++ b/test/internal/build.gradle.kts @@ -33,3 +33,9 @@ dependencies { testRuntimeOnly(libs.android.lint.gradle) { isTransitive = false } testRuntimeOnly(libs.android.lint.checks) { isTransitive = false } } + +tasks.named("test") { + // TODEL Java 16 vs AssertionFailedError https://github.com/ota4j-team/opentest4j/issues/70 + // Example test: WithRootCauseKtTest.`registering a task preConfigures, but does not create it` + jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED") +} From c1a36fc3d9815235f49a7d4c6c705f5b0f751e21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Papp=20=28TWiStErRob=29?= Date: Thu, 26 Jan 2023 11:16:16 +0000 Subject: [PATCH 06/13] Rename nagging.init.gradle.kts --- .../net/twisterrob/gradle/test/GradleRunnerRuleExtension.kt | 6 +++--- .../test/{init.gradle.kts => nagging.init.gradle.kts} | 0 2 files changed, 3 insertions(+), 3 deletions(-) rename test/src/main/resources/net/twisterrob/gradle/test/{init.gradle.kts => nagging.init.gradle.kts} (100%) diff --git a/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRuleExtension.kt b/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRuleExtension.kt index 004794eef..79e29f37e 100644 --- a/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRuleExtension.kt +++ b/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRuleExtension.kt @@ -11,11 +11,11 @@ open class GradleRunnerRuleExtension : TestInstancePostProcessor, BeforeEachCall private val rule = object : GradleRunnerRule() { override val extraArgs: Array - get() = super.extraArgs + arrayOf("--init-script=init.gradle.kts") + strictWarningMode() + get() = super.extraArgs + arrayOf("--init-script=nagging.init.gradle.kts") + strictWarningMode() override fun setUp() { super.setUp() - file(readInitGradle(), "init.gradle.kts") + file(readInitGradle(), "nagging.init.gradle.kts") javaHome = File(System.getenv(System.getProperty("net.twisterrob.test.gradle.javaHomeEnv"))) } @@ -28,7 +28,7 @@ open class GradleRunnerRuleExtension : TestInstancePostProcessor, BeforeEachCall } private fun readInitGradle(): String { - val initGradle = GradleRunnerRuleExtension::class.java.getResourceAsStream("init.gradle.kts") + val initGradle = GradleRunnerRuleExtension::class.java.getResourceAsStream("nagging.init.gradle.kts") ?: error("Cannot find init.gradle.kts on classpath of ${GradleRunnerRuleExtension::class}") return initGradle.use { it.reader().readText() } } diff --git a/test/src/main/resources/net/twisterrob/gradle/test/init.gradle.kts b/test/src/main/resources/net/twisterrob/gradle/test/nagging.init.gradle.kts similarity index 100% rename from test/src/main/resources/net/twisterrob/gradle/test/init.gradle.kts rename to test/src/main/resources/net/twisterrob/gradle/test/nagging.init.gradle.kts From 4d2562e031067f0022b1a89245f8179d4de3325c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Papp=20=28TWiStErRob=29?= Date: Thu, 26 Jan 2023 11:28:55 +0000 Subject: [PATCH 07/13] Add diagnostic to inside the test rather than outside. --- .../gradle/test/GradleRunnerRule.kt | 4 +-- .../gradle/test/GradleRunnerRuleExtension.kt | 13 ++++++---- .../gradle/test/runtime.init.gradle.kts | 25 +++++++++++++++++++ 3 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 test/src/main/resources/net/twisterrob/gradle/test/runtime.init.gradle.kts diff --git a/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRule.kt b/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRule.kt index 8fbf95268..27097ae07 100644 --- a/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRule.kt +++ b/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRule.kt @@ -164,8 +164,8 @@ open class GradleRunnerRule : TestRule { @Suppress("ForbiddenMethodCall") // TODO abstract logging. println( @Suppress("MultilineRawStringIndentation") """ - ${gradleVersion} worker #${gradleTestWorkerId} at ${testKitDir?.absolutePath}. - Java: ${java} from ${javaHome}. + Test Java: ${java} from ${javaHome}. + Requesting ${gradleVersion} in worker #${gradleTestWorkerId} at ${testKitDir?.absolutePath}. Gradle properties: ```properties ${propertiesContentForLogging().prependIndent("\t\t\t\t")} diff --git a/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRuleExtension.kt b/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRuleExtension.kt index 79e29f37e..8f262008f 100644 --- a/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRuleExtension.kt +++ b/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRuleExtension.kt @@ -10,12 +10,15 @@ import java.io.File open class GradleRunnerRuleExtension : TestInstancePostProcessor, BeforeEachCallback, AfterEachCallback { private val rule = object : GradleRunnerRule() { + private val initScripts: MutableList = mutableListOf() + override val extraArgs: Array - get() = super.extraArgs + arrayOf("--init-script=nagging.init.gradle.kts") + strictWarningMode() + get() = super.extraArgs + initScripts.map { "--init-script=${it}" } + strictWarningMode() override fun setUp() { super.setUp() - file(readInitGradle(), "nagging.init.gradle.kts") + file(readResource("nagging.init.gradle.kts"), "nagging.init.gradle.kts".also { initScripts.add(it) }) + file(readResource("runtime.init.gradle.kts"), "runtime.init.gradle.kts".also { initScripts.add(it) }) javaHome = File(System.getenv(System.getProperty("net.twisterrob.test.gradle.javaHomeEnv"))) } @@ -27,9 +30,9 @@ open class GradleRunnerRuleExtension : TestInstancePostProcessor, BeforeEachCall emptyArray() // "fail" was not a valid option for --warning-mode before Gradle 5.6. } - private fun readInitGradle(): String { - val initGradle = GradleRunnerRuleExtension::class.java.getResourceAsStream("nagging.init.gradle.kts") - ?: error("Cannot find init.gradle.kts on classpath of ${GradleRunnerRuleExtension::class}") + private fun readResource(name: String): String { + val initGradle = GradleRunnerRuleExtension::class.java.getResourceAsStream(name) + ?: error("Cannot find ${name} on classpath of ${GradleRunnerRuleExtension::class}") return initGradle.use { it.reader().readText() } } } diff --git a/test/src/main/resources/net/twisterrob/gradle/test/runtime.init.gradle.kts b/test/src/main/resources/net/twisterrob/gradle/test/runtime.init.gradle.kts new file mode 100644 index 000000000..a6a2d29d2 --- /dev/null +++ b/test/src/main/resources/net/twisterrob/gradle/test/runtime.init.gradle.kts @@ -0,0 +1,25 @@ +rootProject { + val gradleTasks = gradle.startParameter.taskNames + val gradleBuildFile = this.buildFile + val gradleVersion = gradle.gradleVersion + val gradleTestWorkerId = System.getProperty("org.gradle.test.worker") + val gradleHome = gradle.gradleUserHomeDir + val gradleDir = gradle.gradleHomeDir + val javaVendor = System.getProperty("java.vendor") + val javaVersion = System.getProperty("java.version") + val javaVersionDate = System.getProperty("java.version.date") + val javaRuntimeName = System.getProperty("java.runtime.name") + val javaRuntimeVersion = System.getProperty("java.runtime.version") + val javaHome = System.getProperty("java.home") + val javaHomeEnv = System.getenv("JAVA_HOME") + @Suppress("NullableToStringCall") // Debug info, null is OK. + val java = "${javaVendor} ${javaRuntimeName} ${javaVersion} (${javaRuntimeVersion} ${javaVersionDate})" + + println( // Using println rather than logger.lifecycle() to make sure it outputs even with --quiet. + """ + Gradle ${gradleVersion} worker #${gradleTestWorkerId} at ${gradleHome.absolutePath} with ${gradleDir?.absolutePath}. + Gradle Java: ${java} from ${javaHome}${if (javaHome != javaHomeEnv) " (JAVA_HOME = ${javaHomeEnv})" else ""}. + Running `gradle ${gradleTasks.joinToString(" ")}` on ${gradleBuildFile.absolutePath}. + """.trimIndent() + ) +} From 23482d5cc64f7eaebccb2b3bdcffcdb8609d8027 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Papp=20=28TWiStErRob=29?= Date: Thu, 26 Jan 2023 12:38:36 +0000 Subject: [PATCH 08/13] Fix timeout --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 0304b4738..51412dd11 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -703,7 +703,7 @@ jobs: # The dependency job might be skipped, we don't need to run this job then. if: success() || failure() # Should finish under 2 minutes on success, so give it a big buffer in case failures take more time. - timeout-minutes: 5 + timeout-minutes: 10 steps: # Below many steps simulate the following missing feature from download-artifact: From f8ba72056a0f26abbceb03a4c73c51ecd4c7bd19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Papp=20=28TWiStErRob=29?= Date: Thu, 26 Jan 2023 14:16:34 +0000 Subject: [PATCH 09/13] init scripts are applied too many times if there are multiple tests in the test class --- .../gradle/test/GradleRunnerRuleExtension.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRuleExtension.kt b/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRuleExtension.kt index 8f262008f..02e8616be 100644 --- a/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRuleExtension.kt +++ b/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRuleExtension.kt @@ -10,15 +10,17 @@ import java.io.File open class GradleRunnerRuleExtension : TestInstancePostProcessor, BeforeEachCallback, AfterEachCallback { private val rule = object : GradleRunnerRule() { - private val initScripts: MutableList = mutableListOf() override val extraArgs: Array - get() = super.extraArgs + initScripts.map { "--init-script=${it}" } + strictWarningMode() + get() = super.extraArgs + strictWarningMode() + arrayOf( + "--init-script=nagging.init.gradle.kts", + "--init-script=runtime.init.gradle.kts", + ) override fun setUp() { super.setUp() - file(readResource("nagging.init.gradle.kts"), "nagging.init.gradle.kts".also { initScripts.add(it) }) - file(readResource("runtime.init.gradle.kts"), "runtime.init.gradle.kts".also { initScripts.add(it) }) + file(readResource("nagging.init.gradle.kts"), "nagging.init.gradle.kts") + file(readResource("runtime.init.gradle.kts"), "runtime.init.gradle.kts") javaHome = File(System.getenv(System.getProperty("net.twisterrob.test.gradle.javaHomeEnv"))) } From 6cc6a748cf482e0a36043ec2218660cad291f6e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Papp=20=28TWiStErRob=29?= Date: Thu, 26 Jan 2023 14:27:08 +0000 Subject: [PATCH 10/13] Open more --- plugin/release/build.gradle.kts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugin/release/build.gradle.kts b/plugin/release/build.gradle.kts index 600a14e51..d1392577f 100644 --- a/plugin/release/build.gradle.kts +++ b/plugin/release/build.gradle.kts @@ -31,3 +31,9 @@ disableGradlePluginValidation() // net.twisterrob.gradle.android.BuildDateKt.getBuiltDate needs the manifest. // The manifest is generated centrally by root build.gradle.kts addJarToClasspathOfPlugin() + +tasks.named("test") { + // TODEL throws initializationError, probably because Java 8 is used for bytecode, but running on Java 19. + // Example test: AndroidReleasePluginIntgTest (but only on CI!) + jvmArgs("--add-opens=java.base/java.util=ALL-UNNAMED") +} From 72fa2da9e6487d5136841baeb71326adffa17d46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Papp=20=28TWiStErRob=29?= Date: Thu, 26 Jan 2023 14:46:36 +0000 Subject: [PATCH 11/13] Simplify --- .github/workflows/CI.yml | 25 ++++++++++++++++--- gradle.properties | 2 +- .../gradle/test/GradleRunnerRuleExtension.kt | 3 +-- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 51412dd11..b00229916 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -33,10 +33,10 @@ jobs: timeout-minutes: 20 needs: validate steps: - - name: Set up JDK 19. + - name: Set up JDK 17. uses: actions/setup-java@v3 with: - java-version: 19 + java-version: 17 distribution: zulu - name: Set up Android SDK. @@ -175,10 +175,10 @@ jobs: steps: - run: echo "Running in response to a ${{ github.event_name }} event, building ${{ github.event.compare }} changes." - - name: Set up JDK 19. + - name: Set up JDK 17. uses: actions/setup-java@v3 with: - java-version: 19 + java-version: 17 distribution: zulu - name: Set up Android SDK. @@ -215,6 +215,23 @@ jobs: echo sdkmanager --install "platforms;android-30" sdkmanager --install "platforms;android-30" + - name: Set up JDK(s). + run: | + echo "JAVA8_HOME=$JAVA_HOME_8_X64" | tee --append $GITHUB_ENV + echo "JAVA11_HOME=$JAVA_HOME_11_X64" | tee --append $GITHUB_ENV + case ${{ matrix.gradle-java }} in + 8) + echo "JAVA_HOME=$JAVA_HOME_8_X64" | tee --append $GITHUB_ENV + ;; + 11) + echo "JAVA_HOME=$JAVA_HOME_11_X64" | tee --append $GITHUB_ENV + ;; + *) + echo "Unrecognized matrix.gradle-java=${{ matrix.gradle-java }}." + exit 1 + ;; + esac + - name: Checkout ${{ github.ref }} branch in ${{ github.repository }} repository. uses: actions/checkout@v3 diff --git a/gradle.properties b/gradle.properties index b82db60f2..a20d536d7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -24,7 +24,7 @@ net.twisterrob.test.android.compileSdkVersion=android-30 # Default test substitutions (overridden by .github/workflows/ci.yml with -P) # AGP: 3.1.4, 3.2.1, 3.3.3, 3.4.3, 3.5.4, 3.6.4, 4.0.2, 4.1.3, 4.2.2, 7.0.4, 7.1.3, 7.2.2, 7.3.1 net.twisterrob.test.android.pluginVersion=7.3.1 -# AGP 3.1.4-7.2.2 -> 1.4.32; AGP 7.3.0- -> 1.6.21 +# Kotlin: AGP 3.1.4-7.2.2 -> Kotlin 1.4.32; AGP 7.3.0- -> Kotlin 1.6.21 net.twisterrob.test.kotlin.pluginVersion=1.6.21 # Gradle: 4.9, 4.10.3; 5.4.1, 5.6.4, 6.1.1, 6.5.1, 6.7.1, 6.9.2; 7.0.2, 7.2, 7.3.3, 7.4.2, 7.5.1 net.twisterrob.gradle.runner.gradleVersion=7.6 diff --git a/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRuleExtension.kt b/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRuleExtension.kt index 02e8616be..575f3276b 100644 --- a/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRuleExtension.kt +++ b/test/src/main/kotlin/net/twisterrob/gradle/test/GradleRunnerRuleExtension.kt @@ -5,7 +5,6 @@ import org.junit.jupiter.api.extension.AfterEachCallback import org.junit.jupiter.api.extension.BeforeEachCallback import org.junit.jupiter.api.extension.ExtensionContext import org.junit.jupiter.api.extension.TestInstancePostProcessor -import java.io.File open class GradleRunnerRuleExtension : TestInstancePostProcessor, BeforeEachCallback, AfterEachCallback { @@ -21,7 +20,7 @@ open class GradleRunnerRuleExtension : TestInstancePostProcessor, BeforeEachCall super.setUp() file(readResource("nagging.init.gradle.kts"), "nagging.init.gradle.kts") file(readResource("runtime.init.gradle.kts"), "runtime.init.gradle.kts") - javaHome = File(System.getenv(System.getProperty("net.twisterrob.test.gradle.javaHomeEnv"))) + //javaHome = File(System.getenv(System.getProperty("net.twisterrob.test.gradle.javaHomeEnv"))) } private fun strictWarningMode(): Array = From da6512287579218faeaf39521bf2057c9f1f0f27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Papp=20=28TWiStErRob=29?= Date: Thu, 26 Jan 2023 15:08:33 +0000 Subject: [PATCH 12/13] Only add opens when compatible. --- common/build.gradle.kts | 8 +++++--- compat/gradle/build.gradle.kts | 8 +++++--- plugin/release/build.gradle.kts | 8 +++++--- test/internal/build.gradle.kts | 8 +++++--- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/common/build.gradle.kts b/common/build.gradle.kts index b3b25afeb..5320acd62 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -39,7 +39,9 @@ tasks.named("compileTestGroovy") { } tasks.named("test") { - // TODEL Java 16 vs Gradle 7+ https://github.com/gradle/gradle/issues/18647 - // Example test: TaskCreationConfigurationTest.`registering a task preConfigures, but does not create it` - jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED") + if (javaVersion.isJava9Compatible) { + // TODEL Java 16 vs Gradle 7+ https://github.com/gradle/gradle/issues/18647 + // Example test: TaskCreationConfigurationTest.`registering a task preConfigures, but does not create it` + jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED") + } } diff --git a/compat/gradle/build.gradle.kts b/compat/gradle/build.gradle.kts index cbf327d9f..a673cf4e2 100644 --- a/compat/gradle/build.gradle.kts +++ b/compat/gradle/build.gradle.kts @@ -13,7 +13,9 @@ dependencies { } tasks.named("test") { - // TODEL Java 16 vs Gradle 7+ https://github.com/gradle/gradle/issues/18647 - // Example test: TaskExtensionsKtTest.`task provider was launched without qualification` - jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED") + if (javaVersion.isJava9Compatible) { + // TODEL Java 16 vs Gradle 7+ https://github.com/gradle/gradle/issues/18647 + // Example test: TaskExtensionsKtTest.`task provider was launched without qualification` + jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED") + } } diff --git a/plugin/release/build.gradle.kts b/plugin/release/build.gradle.kts index d1392577f..ac4fb3d4e 100644 --- a/plugin/release/build.gradle.kts +++ b/plugin/release/build.gradle.kts @@ -33,7 +33,9 @@ disableGradlePluginValidation() addJarToClasspathOfPlugin() tasks.named("test") { - // TODEL throws initializationError, probably because Java 8 is used for bytecode, but running on Java 19. - // Example test: AndroidReleasePluginIntgTest (but only on CI!) - jvmArgs("--add-opens=java.base/java.util=ALL-UNNAMED") + if (javaVersion.isJava9Compatible) { + // TODEL throws initializationError, probably because Java 8 is used for bytecode, but running on Java 19. + // Example test: AndroidReleasePluginIntgTest (but only on CI!) + jvmArgs("--add-opens=java.base/java.util=ALL-UNNAMED") + } } diff --git a/test/internal/build.gradle.kts b/test/internal/build.gradle.kts index e7d1dce19..e6e3853f2 100644 --- a/test/internal/build.gradle.kts +++ b/test/internal/build.gradle.kts @@ -35,7 +35,9 @@ dependencies { } tasks.named("test") { - // TODEL Java 16 vs AssertionFailedError https://github.com/ota4j-team/opentest4j/issues/70 - // Example test: WithRootCauseKtTest.`registering a task preConfigures, but does not create it` - jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED") + if (javaVersion.isJava9Compatible) { + // TODEL Java 16 vs AssertionFailedError https://github.com/ota4j-team/opentest4j/issues/70 + // Example test: WithRootCauseKtTest.`registering a task preConfigures, but does not create it` + jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED") + } } From 109dc79236118026edbe7b7901a8a10c3c4e553c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Papp=20=28TWiStErRob=29?= Date: Thu, 26 Jan 2023 15:08:41 +0000 Subject: [PATCH 13/13] Fails slow on CI --- .github/workflows/CI.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index b00229916..199c56ec4 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -305,6 +305,7 @@ jobs: --no-daemon --no-build-cache --stacktrace + --continue ${{ matrix.test-task }} -Pnet.twisterrob.gradle.build.verboseReports=true -Pnet.twisterrob.test.android.pluginVersion=${{ matrix.agp }}