Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set :poko-tests JVM toolchain version via CI #311

Merged
merged 9 commits into from
Feb 29, 2024
40 changes: 28 additions & 12 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,7 @@ jobs:
uses: actions/setup-java@v4
with:
distribution: zulu
java-version: |
8
11
17
21
java-version: 21

- name: Set up Gradle
uses: gradle/actions/setup-gradle@v3
Expand All @@ -36,20 +32,42 @@ jobs:
path: ~/.m2/repository/dev/drewhamilton/poko/
if-no-files-found: error

build-sample:
test-with-jdk:
runs-on: ubuntu-latest
needs: build
strategy:
matrix:
ci_java_version: [ 8, 11, 17, 21 ]
poko_tests_jvm_toolchain_version: [ 8, 11, 17 ]
steps:
- name: Check out the repo
uses: actions/checkout@v4

- name: Install JDK ${{ matrix.poko_tests_jvm_toolchain_version }}
uses: actions/setup-java@v4
with:
distribution: zulu
java-version: |
${{ matrix.poko_tests_jvm_toolchain_version }}
21

- name: Set up Gradle
uses: gradle/actions/setup-gradle@v3

- name: Test
run: ./gradlew :poko-tests:jvmTest :poko-tests:jvmK2Test --stacktrace
env:
poko_tests_jvm_toolchain_version: ${{ matrix.poko_tests_jvm_toolchain_version }}

build-sample:
runs-on: ubuntu-latest
needs: build
steps:
- name: Check out the repo
uses: actions/checkout@v4
- name: Install JDK ${{ matrix.ci_java_version }}
- name: Install JDK
uses: actions/setup-java@v4
with:
distribution: zulu
java-version: ${{ matrix.ci_java_version }}
java-version: 21
- name: Download MavenLocal
uses: actions/download-artifact@v4
with:
Expand All @@ -61,8 +79,6 @@ jobs:

- name: Build sample
run: cd sample && ./gradlew build --stacktrace
env:
ci_java_version: ${{ matrix.ci_java_version }}

env:
GRADLE_OPTS: >-
Expand Down
26 changes: 3 additions & 23 deletions poko-tests/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,28 +1,13 @@
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
import org.jetbrains.kotlin.gradle.plugin.NATIVE_COMPILER_PLUGIN_CLASSPATH_CONFIGURATION_NAME
import org.jetbrains.kotlin.gradle.plugin.PLUGIN_CLASSPATH_CONFIGURATION_NAME
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget

plugins {
alias(libs.plugins.kotlin.multiplatform)
}

fun KotlinMultiplatformExtension.jvm(
version: Int,
baseName: String = "jvm",
): KotlinJvmTarget {
return jvm(baseName.replace("jvm", "jvm$version")) {
compilations.configureEach {
jvmToolchain(version)
}

// Dummy value required to disambiguate these targets' configurations.
// See https://kotlinlang.org/docs/multiplatform-set-up-targets.html#distinguish-several-targets-for-one-platform
attributes.attribute(Attribute.of("com.example.JvmTarget", Int::class.javaObjectType), version)
}
}
val jvmToolchainVersion: Int? = System.getenv()["poko_tests_jvm_toolchain_version"]?.toInt()

fun <T : KotlinTarget> T.applyK2(): T {
compilations.configureEach {
Expand All @@ -37,13 +22,8 @@ fun <T : KotlinTarget> T.applyK2(): T {
}

kotlin {
jvm(8)
jvm(8, "jvmK2").applyK2()
jvm(11)
jvm(11, "jvmK2").applyK2()
jvm(17)
jvm(17, "jvmK2").applyK2()
// Build JDK which should be latest:
jvmToolchainVersion?.let { jvmToolchain(it) }

jvm()
jvm("jvmK2").applyK2()

Expand Down
1 change: 0 additions & 1 deletion poko-tests/performance/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,4 @@ dependencies {
tasks.named("test") {
dependsOn(":poko-tests:compileProductionExecutableKotlinJs")
dependsOn(":poko-tests:compileKotlinJvm")
dependsOn(":poko-tests:compileKotlinJvm11")
}
17 changes: 15 additions & 2 deletions poko-tests/performance/src/test/kotlin/JvmPerformanceTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import assertk.all
import assertk.assertThat
import assertk.assertions.contains
import assertk.assertions.doesNotContain
import org.junit.AssumptionViolatedException
import org.junit.Test
import org.objectweb.asm.ClassReader

class JvmPerformanceTest {
@Test fun `int property does not emit hashCode method invocation`() {
Expand All @@ -24,11 +26,22 @@ class JvmPerformanceTest {
}

@Test fun `toString uses invokedynamic on modern JDKs`() {
val classfile = jvmOutput("performance/IntAndLong.class", version = 11)
val bytecode = bytecodeToText(classfile.readBytes())
val classfile = jvmOutput("performance/IntAndLong.class")
val classReader = ClassReader(classfile.readBytes())
// Java 9 == class file major version 53:
classReader.assumeMinimumClassVersion(53)
val bytecode = classReader.toText()
assertThat(bytecode).all {
contains("INVOKEDYNAMIC makeConcatWithConstants")
doesNotContain("StringBuilder")
}
}

private fun ClassReader.assumeMinimumClassVersion(version: Int) {
// Class file major version is a two-byte integer at offset 6:
val actualClassVersion = readShort(6)
if (actualClassVersion < version) {
throw AssumptionViolatedException("This test only works class version $version+")
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a canonical way to do this within the assertk framework? It seemed like maybe I'd need a custom FailureContext but that's all internal.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}
}
}
6 changes: 5 additions & 1 deletion poko-tests/performance/src/test/kotlin/asm.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ import org.objectweb.asm.util.Textifier
import org.objectweb.asm.util.TraceClassVisitor

fun bytecodeToText(bytecode: ByteArray): String {
return ClassReader(bytecode).toText()
}

fun ClassReader.toText(): String {
val textifier = Textifier()
ClassReader(bytecode).accept(TraceClassVisitor(null, textifier, null), 0)
accept(TraceClassVisitor(null, textifier, null), 0)

val writer = StringWriter()
textifier.print(PrintWriter(writer))
Expand Down
5 changes: 1 addition & 4 deletions poko-tests/performance/src/test/kotlin/sources.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import java.io.File

fun jvmOutput(relativePath: String, version: Int = -1): File {
val number = if (version == -1) "" else "$version"
return File("../build/classes/kotlin/jvm$number/main", relativePath)
}
fun jvmOutput(relativePath: String) = File("../build/classes/kotlin/jvm/main", relativePath)
fun jsOutput() = File("../build/compileSync/js/main/productionExecutable/kotlin/Poko-poko-tests.js")