1 /* 2 * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. 3 */ 4 5 package kotlinx.coroutines.validator 6 7 import org.junit.* 8 import org.junit.Assert.assertTrue 9 import java.util.jar.* 10 11 class MavenPublicationValidator { 12 private val ATOMIC_FU_REF = "Lkotlinx/atomicfu/".toByteArray() 13 14 @Test testNoAtomicfuInClasspathnull15 fun testNoAtomicfuInClasspath() { 16 val result = runCatching { Class.forName("kotlinx.atomicfu.AtomicInt") } 17 assertTrue(result.exceptionOrNull() is ClassNotFoundException) 18 } 19 20 @Test testNoAtomicfuInMppJarnull21 fun testNoAtomicfuInMppJar() { 22 val clazz = Class.forName("kotlinx.coroutines.Job") 23 JarFile(clazz.protectionDomain.codeSource.location.file).checkForAtomicFu() 24 } 25 26 @Test testNoAtomicfuInAndroidJarnull27 fun testNoAtomicfuInAndroidJar() { 28 val clazz = Class.forName("kotlinx.coroutines.android.HandlerDispatcher") 29 JarFile(clazz.protectionDomain.codeSource.location.file).checkForAtomicFu() 30 } 31 checkForAtomicFunull32 private fun JarFile.checkForAtomicFu() { 33 val foundClasses = mutableListOf<String>() 34 for (e in entries()) { 35 if (!e.name.endsWith(".class")) continue 36 val bytes = getInputStream(e).use { it.readBytes() } 37 loop@for (i in 0 until bytes.size - ATOMIC_FU_REF.size) { 38 for (j in 0 until ATOMIC_FU_REF.size) { 39 if (bytes[i + j] != ATOMIC_FU_REF[j]) continue@loop 40 } 41 foundClasses += e.name // report error at the end with all class names 42 break@loop 43 } 44 } 45 if (foundClasses.isNotEmpty()) { 46 error("Found references to atomicfu in jar file $name in the following class files: ${ 47 foundClasses.joinToString("") { "\n\t\t" + it } 48 }") 49 } 50 close() 51 } 52 } 53