diff options
Diffstat (limited to 'integration-tests/src/test/kotlin/com/google/devtools/ksp/test/PlaygroundIT.kt')
-rw-r--r-- | integration-tests/src/test/kotlin/com/google/devtools/ksp/test/PlaygroundIT.kt | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/PlaygroundIT.kt b/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/PlaygroundIT.kt new file mode 100644 index 00000000..eeaaf502 --- /dev/null +++ b/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/PlaygroundIT.kt @@ -0,0 +1,210 @@ +package com.google.devtools.ksp.test + +import org.gradle.testkit.runner.BuildResult +import org.gradle.testkit.runner.GradleRunner +import org.gradle.testkit.runner.TaskOutcome +import org.junit.Assert +import org.junit.Assume +import org.junit.Ignore +import org.junit.Rule +import org.junit.Test +import java.io.File +import java.util.jar.* + +class PlaygroundIT { + @Rule + @JvmField + val project: TemporaryTestProject = TemporaryTestProject("playground") + + private fun GradleRunner.buildAndCheck(vararg args: String, extraCheck: (BuildResult) -> Unit = {}) = + buildAndCheckOutcome(*args, outcome = TaskOutcome.SUCCESS, extraCheck = extraCheck) + + private fun GradleRunner.buildAndCheckOutcome( + vararg args: String, + outcome: TaskOutcome, + extraCheck: (BuildResult) -> Unit = {} + ) { + val result = this.withArguments(*args).build() + + Assert.assertEquals(outcome, result.task(":workload:build")?.outcome) + + val artifact = File(project.root, "workload/build/libs/workload-1.0-SNAPSHOT.jar") + Assert.assertTrue(artifact.exists()) + + JarFile(artifact).use { jarFile -> + Assert.assertTrue(jarFile.getEntry("TestProcessor.log").size > 0) + Assert.assertTrue(jarFile.getEntry("hello/HELLO.class").size > 0) + Assert.assertTrue(jarFile.getEntry("g/G.class").size > 0) + Assert.assertTrue(jarFile.getEntry("com/example/AClassBuilder.class").size > 0) + } + + extraCheck(result) + } + + @Test + fun testPlayground() { + // FIXME: `clean` fails to delete files on windows. + Assume.assumeFalse(System.getProperty("os.name").startsWith("Windows", ignoreCase = true)) + val gradleRunner = GradleRunner.create().withProjectDir(project.root) + gradleRunner.buildAndCheck("clean", "build") + gradleRunner.buildAndCheck("clean", "build") + } + + // TODO: add another plugin and see if it is blocked. + // Or use a project that depends on a builtin plugin like all-open and see if the build fails + @Test + fun testBlockOtherCompilerPlugins() { + // FIXME: `clean` fails to delete files on windows. + Assume.assumeFalse(System.getProperty("os.name").startsWith("Windows", ignoreCase = true)) + val gradleRunner = GradleRunner.create().withProjectDir(project.root) + + File(project.root, "workload/build.gradle.kts") + .appendText("\nksp {\n blockOtherCompilerPlugins = false\n}\n") + gradleRunner.buildAndCheck("clean", "build") + gradleRunner.buildAndCheck("clean", "build") + project.restore("workload/build.gradle.kts") + } + + @Test + fun testAllowSourcesFromOtherPlugins() { + fun checkGBuilder() { + val artifact = File(project.root, "workload/build/libs/workload-1.0-SNAPSHOT.jar") + + JarFile(artifact).use { jarFile -> + Assert.assertTrue(jarFile.getEntry("g/GBuilder.class").size > 0) + } + } + + val gradleRunner = GradleRunner.create().withProjectDir(project.root) + + File(project.root, "workload/build.gradle.kts") + .appendText("\nksp {\n allowSourcesFromOtherPlugins = true\n}\n") + gradleRunner.buildAndCheck("clean", "build") { checkGBuilder() } + gradleRunner.buildAndCheckOutcome("build", "--info", outcome = TaskOutcome.UP_TO_DATE) { + Assert.assertEquals(TaskOutcome.UP_TO_DATE, it.task(":workload:kspKotlin")?.outcome) + checkGBuilder() + } + project.restore("workload/build.gradle.kts") + } + + /** Regression test for https://github.com/google/ksp/issues/518. */ + @Test + fun testBuildWithConfigureOnDemand() { + val gradleRunner = GradleRunner.create().withProjectDir(project.root) + gradleRunner.buildAndCheck("--configure-on-demand", ":workload:build") + } + + @Test + fun testBuildCache() { + val gradleRunner = GradleRunner.create().withProjectDir(project.root) + // The first build can be FROM_CACHE or SUCCESS, and we only care about the second build. + gradleRunner.buildAndCheck("--build-cache", ":workload:clean", "build") + gradleRunner.buildAndCheck("--build-cache", ":workload:clean", "build") { + Assert.assertEquals(TaskOutcome.FROM_CACHE, it.task(":workload:kspKotlin")?.outcome) + } + } + + @Test + fun testAllWarningsAsErrors() { + File(project.root, "workload/build.gradle.kts") + .appendText("\nksp {\n allWarningsAsErrors = true\n}\n") + val gradleRunner = GradleRunner.create().withProjectDir(project.root) + gradleRunner.withArguments("build").buildAndFail().let { result -> + Assert.assertTrue(result.output.contains("This is a harmless warning.")) + } + } + + // Compiler's test infra report this kind of error before KSP, so it is not testable there. + @Test + fun testNoFunctionName() { + val gradleRunner = GradleRunner.create().withProjectDir(project.root) + + fun buildAndFileAndCheck() { + gradleRunner.withArguments("build").buildAndFail().let { result -> + Assert.assertTrue(result.output.contains("Function declaration must have a name")) + } + } + + File(project.root, "workload/src/main/java/com/example/A.kt").appendText("\n{}\n") + buildAndFileAndCheck() + project.restore("workload/src/main/java/com/example/A.kt") + + File(project.root, "workload/src/main/java/com/example/A.kt").appendText("\nfun() = {0}\n") + buildAndFileAndCheck() + project.restore("workload/src/main/java/com/example/A.kt") + } + + @Test + fun testRewriteFile() { + File( + project.root, + "test-processor/src/main/resources/META-INF/services/" + + "com.google.devtools.ksp.processing.SymbolProcessorProvider" + ).writeText("RewriteProcessorProvider") + val gradleRunner = GradleRunner.create().withProjectDir(project.root) + gradleRunner.withArguments("build").buildAndFail().let { result -> + Assert.assertTrue(result.output.contains("kotlin.io.FileAlreadyExistsException")) + } + } + + // Disabled for now: ERROR: K2 does not support plugins yet, so please remove -Xuse-k2 flag + // Test -Xuse-fir for compilation; KSP still uses FE1.0 + @Ignore + @Test + fun testFirPreview() { + val gradleProperties = File(project.root, "gradle.properties") + gradleProperties.appendText("\nkotlin.useK2=true") + val gradleRunner = GradleRunner.create().withProjectDir(project.root) + gradleRunner.buildAndCheck("clean", "build") { result -> + Assert.assertTrue(result.output.contains("This build uses experimental K2 compiler")) + Assert.assertTrue(result.output.contains("-Xuse-k2")) + } + project.restore(gradleProperties.path) + } + + @Test + fun testVersions() { + val kotlinCompile = "org.jetbrains.kotlin.gradle.tasks.KotlinCompile" + val buildFile = File(project.root, "workload/build.gradle.kts") + buildFile.appendText("\ntasks.withType<$kotlinCompile> {") + buildFile.appendText("\n kotlinOptions.apiVersion = \"1.5\"") + buildFile.appendText("\n kotlinOptions.languageVersion = \"1.5\"") + buildFile.appendText("\n}") + + val kotlinVersion = System.getProperty("kotlinVersion").split('-').first() + val gradleRunner = GradleRunner.create().withProjectDir(project.root) + gradleRunner.buildAndCheck("clean", "build") { result -> + Assert.assertTrue(result.output.contains("language version: 1.5")) + Assert.assertTrue(result.output.contains("api version: 1.5")) + Assert.assertTrue(result.output.contains("compiler version: $kotlinVersion")) + } + project.restore(buildFile.path) + } + + @Test + fun testExcludeProcessor() { + val gradleRunner = GradleRunner.create().withProjectDir(project.root) + + File(project.root, "workload/build.gradle.kts") + .appendText("\nksp {\n excludeProcessor(\"TestProcessorProvider\")\n") + File(project.root, "workload/build.gradle.kts") + .appendText("\n excludeProcessor(\"NotMatchingAnything\")\n}\n") + gradleRunner.withArguments("build").buildAndFail().let { + Assert.assertEquals(TaskOutcome.SUCCESS, it.task(":workload:kspKotlin")?.outcome) + Assert.assertEquals(TaskOutcome.FAILED, it.task(":workload:compileKotlin")?.outcome) + Assert.assertTrue("Unresolved reference: AClassBuilder" in it.output) + } + gradleRunner.withArguments("build").buildAndFail().let { + Assert.assertEquals(TaskOutcome.UP_TO_DATE, it.task(":workload:kspKotlin")?.outcome) + Assert.assertEquals(TaskOutcome.FAILED, it.task(":workload:compileKotlin")?.outcome) + Assert.assertTrue("Unresolved reference: AClassBuilder" in it.output) + } + + project.restore("workload/build.gradle.kts") + File(project.root, "workload/build.gradle.kts") + .appendText("\nksp {\n excludeProcessor(\"DoNotMatch\")\n}\n") + gradleRunner.buildAndCheck("build") + + project.restore("workload/build.gradle.kts") + } +} |