Skip to content

Commit

Permalink
KGP - Fix flaky tests invoking javac through JDK APIs
Browse files Browse the repository at this point in the history
Tests invoking javac APIs were flaky because ClasspathAnalyzerTest
was using Gradle's ProjectBuilder, which appends tools.jar to
the system class loader. Other tests do not do that, and they
invoke javac APIs directly.

In some executions, this causes some javac classes to be loaded
from the system class loader (the one patched by Gradle), while
some of them will be loaded by UrlClassLoader which points to tools.jar
in java.home. Having javac classes from different class loaders causes
java.lang.IllegalAccessError as package private access across class loaders
is not allowed. https://bugs.openjdk.java.net/browse/JDK-8068152 has more
information on this issue.

This change fixes the issue by fully removing usage of ProjectBuilder.

Test: ClasspathAnalyzerTest
  • Loading branch information
gavra0 authored and Space committed Dec 8, 2021
1 parent 73120b9 commit c71e090
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ abstract class StructureTransformLegacyAction : TransformAction<TransformParamet
}
}

private fun transform(input: File, outputs: TransformOutputs) {
internal fun transform(input: File, outputs: TransformOutputs) {
val data = if (input.isDirectory) {
visitDirectory(input)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@
package org.jetbrains.kotlin.gradle.internal.kapt.incremental

import org.gradle.api.artifacts.transform.TransformOutputs
import org.gradle.api.artifacts.transform.TransformParameters
import org.gradle.api.file.FileSystemLocation
import org.gradle.api.provider.Provider
import org.gradle.testfixtures.ProjectBuilder
import org.jetbrains.org.objectweb.asm.ClassWriter
import org.jetbrains.org.objectweb.asm.Opcodes
import org.junit.Assert.*
Expand Down Expand Up @@ -39,7 +35,7 @@ class ClasspathAnalyzerTest {
}
}
val outputs = TransformOutputsMock(tmp.newFolder())
StructureTransformTestAction(classesDir, tmp.newFolder("project")).transform(outputs)
transform(classesDir, outputs)

val data = ClasspathEntryData.ClasspathEntrySerializer.loadFrom(outputs.createdOutputs.single())
assertEquals(setOf("test/A", "test/B"), data.classAbiHash.keys)
Expand Down Expand Up @@ -75,7 +71,7 @@ class ClasspathAnalyzerTest {
}
}
val outputs = TransformOutputsMock(tmp.newFolder())
StructureTransformTestAction(inputJar, tmp.newFolder("project")).transform(outputs)
transform(inputJar, outputs)

val data = ClasspathEntryData.ClasspathEntrySerializer.loadFrom(outputs.createdOutputs.single())
assertEquals(setOf("test/A", "test/B"), data.classAbiHash.keys)
Expand All @@ -101,7 +97,7 @@ class ClasspathAnalyzerTest {
}
}
val outputsA = TransformOutputsMock(tmp.newFolder())
StructureTransformTestAction(jarA, tmp.newFolder("projectA")).transform(outputsA)
transform(jarA, outputsA)

val jarB = tmp.newFile("inputB.jar").also { jar ->
ZipOutputStream(jar.outputStream()).use {
Expand All @@ -115,17 +111,15 @@ class ClasspathAnalyzerTest {
}
}
val outputsB = TransformOutputsMock(tmp.newFolder())
StructureTransformTestAction(jarB, tmp.newFolder("projectB")).transform(outputsB)
transform(jarB, outputsB)

assertArrayEquals(outputsA.createdOutputs.single().readBytes(), outputsB.createdOutputs.single().readBytes())
}

@Test
fun emptyInput() {
val transformAction = StructureTransformTestAction(tmp.newFolder("input"), tmp.newFolder("project"))
val outputs = TransformOutputsMock(tmp.newFolder())

transformAction.transform(outputs)
transform(tmp.newFolder("input"), outputs)

val data = ClasspathEntryData.ClasspathEntrySerializer.loadFrom(outputs.createdOutputs.single())
assertTrue(data.classAbiHash.isEmpty())
Expand All @@ -149,10 +143,8 @@ class ClasspathAnalyzerTest {
it.closeEntry()
}
}
val transformAction = StructureTransformTestAction(inputJar, tmp.newFolder("project"))
val outputs = TransformOutputsMock(tmp.newFolder())

transformAction.transform(outputs)
transform(inputJar, outputs)

val data = ClasspathEntryData.ClasspathEntrySerializer.loadFrom(outputs.createdOutputs.single())
assertEquals(setOf("test/A", "test/B", "test/C"), data.classAbiHash.keys)
Expand All @@ -166,17 +158,6 @@ class ClasspathAnalyzerTest {
}
}

class StructureTransformTestAction(val input: File, val projectDir: File) : StructureTransformAction() {
private val project = ProjectBuilder.builder().withProjectDir(projectDir).build()

override val inputArtifact: Provider<FileSystemLocation> = project.provider { project.objects.fileProperty().fileValue(input).get() }

override fun getParameters(): TransformParameters.None? {
//no need for StructureTransformAction and so for test
return null
}
}

class TransformOutputsMock(val outputDir: File) : TransformOutputs {
val createdOutputs = mutableListOf<File>()

Expand All @@ -192,4 +173,4 @@ class TransformOutputsMock(val outputDir: File) : TransformOutputs {
return newDir
}

}
}

0 comments on commit c71e090

Please sign in to comment.