diff --git a/integration-testing/build.gradle b/integration-testing/build.gradle index 6c8d2f326f..04be36fac9 100644 --- a/integration-testing/build.gradle +++ b/integration-testing/build.gradle @@ -18,6 +18,7 @@ java { dependencies { testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version" + testImplementation "org.ow2.asm:asm:$asm_version" } sourceSets { diff --git a/integration-testing/gradle.properties b/integration-testing/gradle.properties index 5e68a9d9e2..7dfc532358 100644 --- a/integration-testing/gradle.properties +++ b/integration-testing/gradle.properties @@ -1,4 +1,5 @@ kotlin_version=1.7.10 coroutines_version=1.6.4-SNAPSHOT +asm_version=9.3 kotlin.code.style=official diff --git a/integration-testing/src/mavenTest/kotlin/MavenPublicationAtomicfuValidator.kt b/integration-testing/src/mavenTest/kotlin/MavenPublicationAtomicfuValidator.kt index dbb1921d80..13bac0157a 100644 --- a/integration-testing/src/mavenTest/kotlin/MavenPublicationAtomicfuValidator.kt +++ b/integration-testing/src/mavenTest/kotlin/MavenPublicationAtomicfuValidator.kt @@ -4,12 +4,17 @@ package kotlinx.coroutines.validator -import org.junit.* -import org.junit.Assert.assertTrue +import org.junit.Test +import org.objectweb.asm.* +import org.objectweb.asm.ClassReader.* +import org.objectweb.asm.ClassWriter.* +import org.objectweb.asm.Opcodes.* import java.util.jar.* +import kotlin.test.* class MavenPublicationAtomicfuValidator { private val ATOMIC_FU_REF = "Lkotlinx/atomicfu/".toByteArray() + private val KOTLIN_METADATA_DESC = "Lkotlin/Metadata;" @Test fun testNoAtomicfuInClasspath() { @@ -34,19 +39,39 @@ class MavenPublicationAtomicfuValidator { for (e in entries()) { if (!e.name.endsWith(".class")) continue val bytes = getInputStream(e).use { it.readBytes() } - loop@for (i in 0 until bytes.size - ATOMIC_FU_REF.size) { - for (j in 0 until ATOMIC_FU_REF.size) { - if (bytes[i + j] != ATOMIC_FU_REF[j]) continue@loop - } + // 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 (for Kotlin 1.8.0). + val outBytes = bytes.eraseMetadata() + if (outBytes.checkBytes()) { foundClasses += e.name // report error at the end with all class names - break@loop } } if (foundClasses.isNotEmpty()) { error("Found references to atomicfu in jar file $name in the following class files: ${ - foundClasses.joinToString("") { "\n\t\t" + it } + foundClasses.joinToString("") { "\n\t\t" + it } }") } close() } + + private fun ByteArray.checkBytes(): Boolean { + loop@for (i in 0 until this.size - ATOMIC_FU_REF.size) { + for (j in 0 until ATOMIC_FU_REF.size) { + if (this[i + j] != ATOMIC_FU_REF[j]) continue@loop + } + return true + } + return false + } + + private fun ByteArray.eraseMetadata(): ByteArray { + val cw = ClassWriter(COMPUTE_MAXS or COMPUTE_FRAMES) + ClassReader(this).accept(object : ClassVisitor(ASM9, cw) { + override fun visitAnnotation(descriptor: String?, visible: Boolean): AnnotationVisitor? { + return if (descriptor == KOTLIN_METADATA_DESC) null else super.visitAnnotation(descriptor, visible) + } + }, SKIP_FRAMES) + return cw.toByteArray() + } } diff --git a/integration-testing/src/mavenTest/kotlin/MavenPublicationVersionValidator.kt b/integration-testing/src/mavenTest/kotlin/MavenPublicationVersionValidator.kt index da87d4cc59..11529d2d0d 100644 --- a/integration-testing/src/mavenTest/kotlin/MavenPublicationVersionValidator.kt +++ b/integration-testing/src/mavenTest/kotlin/MavenPublicationVersionValidator.kt @@ -4,7 +4,6 @@ package kotlinx.coroutines.validator -import org.junit.* import org.junit.Test import java.util.jar.* import kotlin.test.* diff --git a/kotlinx-coroutines-core/jvm/test/internal/SegmentBasedQueue.kt b/kotlinx-coroutines-core/jvm/src/internal/SegmentBasedQueue.kt similarity index 100% rename from kotlinx-coroutines-core/jvm/test/internal/SegmentBasedQueue.kt rename to kotlinx-coroutines-core/jvm/src/internal/SegmentBasedQueue.kt diff --git a/kotlinx-coroutines-core/jvm/test/internal/SegmentListTest.kt b/kotlinx-coroutines-core/jvm/test/internal/SegmentListTest.kt deleted file mode 100644 index ff6a346cda..0000000000 --- a/kotlinx-coroutines-core/jvm/test/internal/SegmentListTest.kt +++ /dev/null @@ -1,41 +0,0 @@ -package kotlinx.coroutines.internal - -import kotlinx.atomicfu.* -import org.junit.Test -import kotlin.test.* - -class SegmentListTest { - @Test - fun testRemoveTail() { - val initialSegment = TestSegment(0, null, 2) - val head = AtomicRefHolder(initialSegment) - val tail = AtomicRefHolder(initialSegment) - val s1 = tail.ref.findSegmentAndMoveForward(1, tail.ref.value, ::createTestSegment).segment - assertFalse(s1.removed) - tail.ref.value.onSlotCleaned() - assertFalse(s1.removed) - head.ref.findSegmentAndMoveForward(2, head.ref.value, ::createTestSegment) - assertFalse(s1.removed) - tail.ref.findSegmentAndMoveForward(2, head.ref.value, ::createTestSegment) - assertTrue(s1.removed) - } - - @Test - fun testClose() { - val initialSegment = TestSegment(0, null, 2) - val head = AtomicRefHolder(initialSegment) - val tail = AtomicRefHolder(initialSegment) - tail.ref.findSegmentAndMoveForward(1, tail.ref.value, ::createTestSegment) - assertEquals(tail.ref.value, tail.ref.value.close()) - assertTrue(head.ref.findSegmentAndMoveForward(2, head.ref.value, ::createTestSegment).isClosed) - } -} - -private class AtomicRefHolder(initialValue: T) { - val ref = atomic(initialValue) -} - -private class TestSegment(id: Long, prev: TestSegment?, pointers: Int) : Segment(id, prev, pointers) { - override val maxSlots: Int get() = 1 -} -private fun createTestSegment(id: Long, prev: TestSegment?) = TestSegment(id, prev, 0) \ No newline at end of file diff --git a/kotlinx-coroutines-core/jvm/test/internal/SegmentQueueTest.kt b/kotlinx-coroutines-core/jvm/test/internal/SegmentQueueTest.kt index fd2d329088..1390403a3b 100644 --- a/kotlinx-coroutines-core/jvm/test/internal/SegmentQueueTest.kt +++ b/kotlinx-coroutines-core/jvm/test/internal/SegmentQueueTest.kt @@ -1,6 +1,7 @@ package kotlinx.coroutines.internal import kotlinx.coroutines.* +import kotlinx.coroutines.internal.* import org.junit.Test import java.util.* import java.util.concurrent.CyclicBarrier @@ -106,4 +107,4 @@ class SegmentQueueTest : TestBase() { }.forEach { it.join() } assertEquals(2, q.numberOfSegments) } -} \ No newline at end of file +}