From e13f21e461e30e15f1f255ff02437b77e28c217c Mon Sep 17 00:00:00 2001 From: Yahor Berdnikau Date: Tue, 16 Mar 2021 11:23:06 +0100 Subject: [PATCH] Add basic DSL based on Gradle TestKit for KGP integration tests. ^KT-45744 In Progress --- .../build.gradle.kts | 1 + .../kotlin/gradle/testbase/KGPBaseTest.kt | 21 ++++ .../gradle/testbase/projectSetupDefaults.kt | 23 ++++ .../kotlin/gradle/testbase/testDsl.kt | 116 ++++++++++++++++++ 4 files changed, 161 insertions(+) create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/KGPBaseTest.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/projectSetupDefaults.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/testDsl.kt diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/build.gradle.kts index d76d07dad7d..b07e23629c6 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/build.gradle.kts +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/build.gradle.kts @@ -39,6 +39,7 @@ dependencies { testImplementation(commonDep("org.jetbrains.intellij.deps", "trove4j")) testImplementation(gradleApi()) + testImplementation(gradleTestKit()) testImplementation("com.google.code.gson:gson:${rootProject.extra["versions.jar.gson"]}") testApiJUnit5(vintageEngine = true) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/KGPBaseTest.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/KGPBaseTest.kt new file mode 100644 index 00000000000..8f8664d8395 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/KGPBaseTest.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.gradle.testbase + +import org.junit.jupiter.api.io.TempDir +import java.nio.file.Path + +/** + * Base class for all Kotlin Gradle plugin integration tests. + */ +abstract class KGPBaseTest { + + companion object { + @TempDir + @JvmStatic + lateinit var workingDir: Path + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/projectSetupDefaults.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/projectSetupDefaults.kt new file mode 100644 index 00000000000..c70092a3162 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/projectSetupDefaults.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.gradle + +import org.intellij.lang.annotations.Language + +@Language("Groovy") +internal val DEFAULT_GROOVY_SETTINGS_FILE = + """ + pluginManagement { + repositories { + mavenLocal() + mavenCentral() + } + + plugins { + id "org.jetbrains.kotlin.jvm" version "${'$'}kotlin_version" + } + } + """.trimIndent() diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/testDsl.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/testDsl.kt new file mode 100644 index 00000000000..908da301f58 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/testDsl.kt @@ -0,0 +1,116 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.gradle.testbase + +import org.gradle.testkit.runner.BuildResult +import org.gradle.testkit.runner.GradleRunner +import org.jetbrains.kotlin.gradle.DEFAULT_GROOVY_SETTINGS_FILE +import kotlin.test.assertTrue +import java.nio.file.* +import java.nio.file.Files.copy +import java.nio.file.Files.createDirectories + +import java.nio.file.attribute.BasicFileAttributes + +/** + * Create new test project. + * + * @param [projectName] test project name in 'src/test/resources/testProject` directory. + */ +fun KGPBaseTest.project( + projectName: String, + test: TestProject.() -> Unit +): TestProject { + val projectPath = setupProjectFromTestResources(projectName, KGPBaseTest.workingDir) + projectPath.addDefaultBuildFiles() + + val gradleRunner = GradleRunner + .create() + .withProjectDir(projectPath.toFile()) + .withTestKitDir(KGPBaseTest.workingDir.testKitDir.toFile()) + + val testProject = TestProject(gradleRunner, projectName) + testProject.test() + return testProject +} + +/** + * Trigger test project build with given [buildArguments] and assert build is successful. + */ +fun TestProject.build( + vararg buildArguments: String, + assertions: BuildResult.() -> Unit = {} +) { + println("<=== Test build: ${this.projectName} ===>") + val buildResult = gradleRunner + .withArguments(*buildArguments, "-Pkotlin_version=1.5.255-SNAPSHOT") + .build() + assertions(buildResult) +} + +/** + * Trigger test project build with given [buildArguments] and assert build is failed. + */ +fun TestProject.buildAndFail( + vararg buildArguments: String, + assertions: BuildResult.() -> Unit = {} +) { + println("<=== Test build: ${this.projectName} ===>") + val buildResult = gradleRunner + .withArguments(*buildArguments, "-Pkotlin_version=1.5.255-SNAPSHOT") + .buildAndFail() + assertions(buildResult) +} + +class TestProject( + val gradleRunner: GradleRunner, + val projectName: String +) + +private val Path.testKitDir get() = resolve("testKitDir") + +private fun setupProjectFromTestResources( + projectName: String, + tempDir: Path +): Path { + val testProjectPath = Paths.get("src", "test", "resources", "testProject", projectName) + assertTrue("Test project exists") { Files.exists(testProjectPath) } + assertTrue("Test project path is a directory") { Files.isDirectory(testProjectPath) } + + return tempDir + .resolve(projectName) + .also { + testProjectPath.copyRecursively(it) + } +} + +private fun Path.addDefaultBuildFiles() { + if (Files.exists(resolve("build.gradle")) && + !Files.exists(resolve("settings.gradle")) + ) { + resolve("settings.gradle").toFile().writeText(DEFAULT_GROOVY_SETTINGS_FILE) + } +} + +private fun Path.copyRecursively(dest: Path) { + Files.walkFileTree(this, object : SimpleFileVisitor() { + override fun preVisitDirectory( + dir: Path, + attrs: BasicFileAttributes + ): FileVisitResult { + createDirectories(dest.resolve(relativize(dir))) + return FileVisitResult.CONTINUE + } + + override fun visitFile( + file: Path, + attrs: BasicFileAttributes + ): FileVisitResult { + copy(file, dest.resolve(relativize(file))) + return FileVisitResult.CONTINUE + } + }) +} \ No newline at end of file