-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduced integration tests for JVM and MPP projects
- Loading branch information
1 parent
2b86fbf
commit ae77f31
Showing
20 changed files
with
474 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
buildscript { | ||
val atomicfu_version = rootProject.properties["atomicfu_version"] | ||
|
||
repositories { | ||
mavenLocal() | ||
} | ||
|
||
dependencies { | ||
classpath("org.jetbrains.kotlinx:atomicfu-gradle-plugin:$atomicfu_version") | ||
} | ||
} | ||
|
||
plugins { | ||
kotlin("jvm") version "1.9.10" // todo get kotlin_version from gradle.properties | ||
} | ||
|
||
apply(plugin = "kotlinx-atomicfu") | ||
|
||
repositories { | ||
mavenLocal() | ||
mavenCentral() | ||
maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev") | ||
} | ||
|
||
dependencies { | ||
implementation(kotlin("stdlib")) | ||
implementation(kotlin("test-junit")) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
kotlin_version=1.9.0 | ||
atomicfu_version=0.22.0-SNAPSHOT |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
rootProject.name = "jvm-sample" |
19 changes: 19 additions & 0 deletions
19
integration-testing/examples/jvm-sample/src/main/kotlin/Sample.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/* | ||
* Copyright 2017-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. | ||
*/ | ||
|
||
import kotlinx.atomicfu.* | ||
import kotlin.test.assertEquals | ||
import kotlin.test.assertTrue | ||
|
||
class IntArithmetic { | ||
private val _x = atomic(0) | ||
val x get() = _x.value | ||
|
||
fun doWork(finalValue: Int) { | ||
assertEquals(0, x) | ||
assertEquals(0, _x.getAndSet(3)) | ||
assertEquals(3, x) | ||
assertTrue(_x.compareAndSet(3, finalValue)) | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
integration-testing/examples/jvm-sample/src/test/kotlin/SampleTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/* | ||
* Copyright 2017-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. | ||
*/ | ||
|
||
import kotlin.test.* | ||
|
||
class ArithmeticTest { | ||
@Test | ||
fun testInt() { | ||
val a = IntArithmetic() | ||
a.doWork(1234) | ||
assertEquals(1234, a.x) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/* | ||
* Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. | ||
*/ | ||
|
||
buildscript { | ||
val atomicfu_version = rootProject.properties["atomicfu_version"] | ||
|
||
repositories { | ||
mavenLocal() | ||
mavenCentral() | ||
} | ||
|
||
dependencies { | ||
classpath("org.jetbrains.kotlinx:atomicfu-gradle-plugin:$atomicfu_version") | ||
} | ||
} | ||
|
||
plugins { | ||
kotlin("multiplatform") version "1.9.10" // todo get kotlin_version from gradle.proeprties | ||
} | ||
|
||
apply(plugin = "kotlinx-atomicfu") | ||
|
||
repositories { | ||
mavenLocal() | ||
mavenCentral() | ||
} | ||
|
||
kotlin { | ||
jvm() | ||
macosX64("native") | ||
|
||
sourceSets { | ||
val commonMain by getting | ||
val commonTest by getting { | ||
dependencies { | ||
implementation(kotlin("test")) | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
kotlin_version=1.9.0 | ||
atomicfu_version=0.22.0-SNAPSHOT |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
pluginManagement { | ||
repositories { | ||
mavenLocal() | ||
mavenCentral() | ||
gradlePluginPortal() | ||
} | ||
} | ||
|
||
rootProject.name = "mpp-sample" |
14 changes: 14 additions & 0 deletions
14
integration-testing/examples/mpp-sample/src/commonMain/kotlin/IntArithmetic.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import kotlinx.atomicfu.* | ||
|
||
class IntArithmetic { | ||
private val _x = atomic(0) | ||
val x get() = _x.value | ||
|
||
fun doWork(finalValue: Int) { | ||
check(x == 0) | ||
_x.getAndSet(3) | ||
check(x == 3) | ||
_x.compareAndSet(3, finalValue) | ||
check(x == finalValue) | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
integration-testing/examples/mpp-sample/src/commonTest/kotlin/IntArithmeticTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/* | ||
* Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. | ||
*/ | ||
|
||
import kotlin.test.* | ||
|
||
class IntArithmeticTest { | ||
|
||
@Test | ||
fun testInt() { | ||
val a = IntArithmetic() | ||
a.doWork(1234) | ||
assertEquals(1234, a.x) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
kotlin_version=1.9.0 | ||
atomicfu_version=0.22.0-SNAPSHOT | ||
|
||
asm_version=9.3 | ||
kotlin.code.style=official | ||
kotlin.mpp.stability.nowarn=true |
28 changes: 28 additions & 0 deletions
28
...ation-testing/src/test/kotlin/kotlinx.atomicfu.gradle.plugin.test/cases/JvmProjectTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/* | ||
* Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. | ||
*/ | ||
|
||
package kotlinx.atomicfu.gradle.plugin.test.cases | ||
|
||
import kotlinx.atomicfu.gradle.plugin.test.framework.checker.* | ||
import kotlinx.atomicfu.gradle.plugin.test.framework.runner.* | ||
import kotlin.test.Test | ||
|
||
class JvmProjectTest { | ||
|
||
private val jvmSample: GradleBuild = createGradleBuildFromSources("jvm-sample") | ||
|
||
@Test | ||
fun testJvmWithEnabledIrTransformation() { | ||
jvmSample.enableJvmIrTransformation = true | ||
jvmSample.checkJvmCompileOnlyDependencies() | ||
jvmSample.buildAndCheckBytecode() | ||
} | ||
|
||
@Test | ||
fun testJvmWithDisabledIrTransformation() { | ||
jvmSample.enableJvmIrTransformation = false | ||
jvmSample.checkJvmCompileOnlyDependencies() | ||
jvmSample.buildAndCheckBytecode() | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
...ation-testing/src/test/kotlin/kotlinx.atomicfu.gradle.plugin.test/cases/MppProjectTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/* | ||
* Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. | ||
*/ | ||
|
||
package test | ||
|
||
import kotlinx.atomicfu.gradle.plugin.test.framework.checker.* | ||
import kotlinx.atomicfu.gradle.plugin.test.framework.runner.* | ||
import kotlin.test.Test | ||
|
||
class MppProjectTest { | ||
private val mppSample: GradleBuild = createGradleBuildFromSources("mpp-sample") | ||
|
||
@Test | ||
fun testMppJvm1() { | ||
mppSample.enableJvmIrTransformation = true | ||
mppSample.checkMppJvmCompileOnlyDependencies() | ||
mppSample.buildAndCheckBytecode() | ||
} | ||
|
||
@Test | ||
fun testMppJvm2() { | ||
mppSample.enableJvmIrTransformation = false | ||
mppSample.checkMppJvmCompileOnlyDependencies() | ||
mppSample.buildAndCheckBytecode() | ||
} | ||
} |
68 changes: 68 additions & 0 deletions
68
.../src/test/kotlin/kotlinx.atomicfu.gradle.plugin.test/framework/checker/ArtifactChecker.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
/* | ||
* Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. | ||
*/ | ||
|
||
package kotlinx.atomicfu.gradle.plugin.test.framework.checker | ||
|
||
import kotlinx.atomicfu.gradle.plugin.test.framework.runner.GradleBuild | ||
import kotlinx.atomicfu.gradle.plugin.test.framework.runner.build | ||
import org.objectweb.asm.* | ||
import java.io.File | ||
import kotlin.test.assertFalse | ||
|
||
internal abstract class ArtifactChecker(val targetDir: File) { | ||
|
||
private val ATOMIC_FU_REF = "Lkotlinx/atomicfu/".toByteArray() | ||
protected val KOTLIN_METADATA_DESC = "Lkotlin/Metadata;" | ||
|
||
protected val projectName = targetDir.name.substringBeforeLast("-") | ||
|
||
val buildDir | ||
get() = targetDir.resolve("build").also { | ||
require(it.exists() && it.isDirectory) { "Could not find `build/` directory in the target directory of the project $projectName: ${targetDir.path}" } | ||
} | ||
|
||
abstract fun checkReferences() | ||
|
||
protected fun ByteArray.findAtomicfuRef(): Boolean { | ||
loop@for (i in 0 until this.size - ATOMIC_FU_REF.size) { | ||
for (j in ATOMIC_FU_REF.indices) { | ||
if (this[i + j] != ATOMIC_FU_REF[j]) continue@loop | ||
} | ||
return true | ||
} | ||
return false | ||
} | ||
} | ||
|
||
private class BytecodeChecker(targetDir: File) : ArtifactChecker(targetDir) { | ||
|
||
override fun checkReferences() { | ||
val atomicfuDir = buildDir.resolve("classes/atomicfu/") | ||
(if (atomicfuDir.exists() && atomicfuDir.isDirectory) atomicfuDir else buildDir).let { | ||
it.walkBottomUp().filter { it.isFile && it.name.endsWith(".class") }.forEach { clazz -> | ||
assertFalse(clazz.readBytes().eraseMetadata().findAtomicfuRef(), "Found kotlinx/atomicfu in class file ${clazz.path}") | ||
} | ||
} | ||
} | ||
|
||
// The atomicfu compiler plugin does not remove atomic properties from metadata, | ||
// so for now we check that there are no ATOMIC_FU_REF left in the class bytecode excluding metadata. | ||
// This may be reverted after the fix in the compiler plugin transformer (See #254). | ||
private fun ByteArray.eraseMetadata(): ByteArray { | ||
val cw = ClassWriter(ClassWriter.COMPUTE_MAXS or ClassWriter.COMPUTE_FRAMES) | ||
ClassReader(this).accept(object : ClassVisitor(Opcodes.ASM9, cw) { | ||
override fun visitAnnotation(descriptor: String?, visible: Boolean): AnnotationVisitor? { | ||
return if (descriptor == KOTLIN_METADATA_DESC) null else super.visitAnnotation(descriptor, visible) | ||
} | ||
}, ClassReader.SKIP_FRAMES) | ||
return cw.toByteArray() | ||
} | ||
} | ||
|
||
internal fun GradleBuild.buildAndCheckBytecode() { | ||
val buildResult = build() | ||
require(buildResult.isSuccessful) { "Build of the project $projectName failed:\n ${buildResult.output}" } | ||
BytecodeChecker(this.targetDir).checkReferences() | ||
} | ||
|
51 changes: 51 additions & 0 deletions
51
.../test/kotlin/kotlinx.atomicfu.gradle.plugin.test/framework/checker/DependenciesChecker.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/* | ||
* Copyright 2016-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. | ||
*/ | ||
|
||
package kotlinx.atomicfu.gradle.plugin.test.framework.checker | ||
|
||
import kotlinx.atomicfu.gradle.plugin.test.framework.runner.BuildResult | ||
import kotlinx.atomicfu.gradle.plugin.test.framework.runner.GradleBuild | ||
import kotlinx.atomicfu.gradle.plugin.test.framework.runner.atomicfuVersion | ||
import kotlinx.atomicfu.gradle.plugin.test.framework.runner.dependencies | ||
|
||
private const val COMPILE_CLASSPATH = "compileClasspath" | ||
private const val RUNTIME_CLASSPATH = "runtimeClasspath" | ||
private val jvmAtomicfuDependency = "org.jetbrains.kotlinx:atomicfu-jvm:$atomicfuVersion" | ||
private val commonAtomicfuDependency = "org.jetbrains.kotlinx:atomicfu:$atomicfuVersion" | ||
|
||
private class DependenciesChecker( | ||
private val buildResult: BuildResult, | ||
private val dependencies: List<String> | ||
) { | ||
fun checkCompileOnly(compileConfigurations: List<String>, runtimeConfigurations: List<String>) { | ||
val compileClasspath = buildResult.getDependencies(compileConfigurations) | ||
val runtimeClasspath = buildResult.getDependencies(runtimeConfigurations) | ||
for (dep in dependencies) { | ||
check(compileClasspath.contains(dep)) { "Expected compileOnly dependency $dep was not found in the compileClasspath: $compileClasspath" } | ||
check(!runtimeClasspath.contains(dep)) { "Dependency $dep should be compileOnly, but it was found in the runtimeClasspath: $runtimeClasspath" } | ||
} | ||
} | ||
|
||
fun checkImplementation(runtimeConfigurations: List<String>) { | ||
val runtimeClasspath = buildResult.getDependencies(runtimeConfigurations) | ||
for (dep in dependencies) { | ||
check(runtimeClasspath.contains(dep)) { "Expected implementation dependency $dep was not found in the runtimeClasspath: $runtimeClasspath" } | ||
} | ||
} | ||
} | ||
|
||
// Checks that a simple non-mpp JVM project does not have atomicfu-jvm dependency in runtime classpath | ||
internal fun GradleBuild.checkJvmCompileOnlyDependencies() { | ||
val checker = DependenciesChecker(dependencies(), listOf(jvmAtomicfuDependency)) | ||
checker.checkCompileOnly(listOf(COMPILE_CLASSPATH), listOf(RUNTIME_CLASSPATH)) | ||
} | ||
|
||
// For MPP project with a JVM target and enabled atomicfu transformation checks that atomicfu-jvm is a compileOnly dependency | ||
internal fun GradleBuild.checkMppJvmCompileOnlyDependencies() { | ||
val checker = DependenciesChecker(dependencies(), listOf(jvmAtomicfuDependency)) | ||
checker.checkCompileOnly( | ||
compileConfigurations = listOf("jvmCompileClasspath"), | ||
runtimeConfigurations = listOf("jvmRuntimeClasspath") | ||
) | ||
} |
Oops, something went wrong.