/* * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.coroutines.validator import org.junit.* import org.junit.Assert.assertTrue import java.util.jar.* class MavenPublicationValidator { private val ATOMIC_FU_REF = "Lkotlinx/atomicfu/".toByteArray() @Test fun testNoAtomicfuInClasspath() { val result = runCatching { Class.forName("kotlinx.atomicfu.AtomicInt") } assertTrue(result.exceptionOrNull() is ClassNotFoundException) } @Test fun testNoAtomicfuInMppJar() { val clazz = Class.forName("kotlinx.coroutines.Job") JarFile(clazz.protectionDomain.codeSource.location.file).checkForAtomicFu() } @Test fun testNoAtomicfuInAndroidJar() { val clazz = Class.forName("kotlinx.coroutines.android.HandlerDispatcher") JarFile(clazz.protectionDomain.codeSource.location.file).checkForAtomicFu() } private fun JarFile.checkForAtomicFu() { val foundClasses = mutableListOf() 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 } 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 } }") } close() } }