diff --git a/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/JarContentTest.kt b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/JarContentTest.kt index 0c2fc6127c8..79ba56b5795 100644 --- a/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/JarContentTest.kt +++ b/libraries/kotlinx-metadata/jvm/test/kotlinx/metadata/test/JarContentTest.kt @@ -7,63 +7,54 @@ package kotlinx.metadata.test import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmNameResolver import org.jetbrains.org.objectweb.asm.ClassReader +import org.jetbrains.org.objectweb.asm.ClassReader.SKIP_DEBUG import org.jetbrains.org.objectweb.asm.ClassReader.SKIP_FRAMES import org.jetbrains.org.objectweb.asm.ClassVisitor import org.jetbrains.org.objectweb.asm.MethodVisitor -import org.jetbrains.org.objectweb.asm.Opcodes.ASM4 -import org.junit.Assert.assertFalse -import org.junit.Assert.assertNull +import org.jetbrains.org.objectweb.asm.Opcodes.API_VERSION +import org.junit.Assert.* import org.junit.Test import java.io.File -import java.nio.file.Path -import java.nio.file.Paths import java.util.zip.ZipFile import kotlin.text.Charsets.UTF_8 class JarContentTest { @Test fun testJarContents() { - // println("Patterns: $PREDEFINED_STRINGS") - LIBS_PATH.toFile().walk().filter { it.name.endsWith(JAR_EXT) }.forEach(::checkJarContents) + val jars = File("build/libs").walk().filter { it.name.endsWith(".jar") }.toList() + assertTrue(jars.isNotEmpty()) + jars.forEach(::checkClassesHasNoSpecificStringConstants) } - private fun checkJarContents(jar: File) { + private fun checkClassesHasNoSpecificStringConstants(jar: File) { val zipFile = ZipFile(jar, UTF_8) - zipFile.entries().asSequence().filter { it.name.endsWith(CLASS_EXT) }.forEach { - val loadedConstants = mutableListOf() - val classReader = ClassReader(zipFile.getInputStream(it)) - classReader.accept(object : ClassVisitor(ASM4) { - override fun visitMethod(p0: Int, p1: String?, p2: String?, p3: String?, p4: Array?): MethodVisitor { - return object : MethodVisitor(ASM4) { - override fun visitLdcInsn(cst: Any?) { - if (cst != null) loadedConstants.add(cst) + for (entry in zipFile.entries()) { + if (!entry.name.endsWith(".class")) continue + + val loadedConstants = mutableListOf() + zipFile.getInputStream(entry).use { stream -> + ClassReader(stream).accept(object : ClassVisitor(API_VERSION) { + override fun visitMethod( + access: Int, name: String?, descriptor: String?, signature: String?, exceptions: Array? + ): MethodVisitor = object : MethodVisitor(API_VERSION) { + override fun visitLdcInsn(value: Any?) { + if (value is String && value.isNotEmpty()) loadedConstants.add(value) } } - } - }, SKIP_FRAMES) + }, SKIP_DEBUG or SKIP_FRAMES) + } for (constant in loadedConstants) { - if (constant !is String || constant.isNullOrEmpty()) { - continue - } - // println("checking: $constant") // Explicitly checking types that are programmatically built don't appear as string constants. - assertNull("$constant found at ${it.name}", findPattern(constant)) + assertNull("$constant found at ${entry.name}", PREDEFINED_STRINGS.find { it in constant }) + // Implicitly checking none of string constants starts with "kotlin/" prefix, just in case. - assertFalse("$constant found at ${it.name}", constant.startsWith("kotlin/")) + assertFalse("$constant found at ${entry.name}", constant.startsWith("kotlin/")) } } } - private fun findPattern(constant: String): String? { - return PREDEFINED_STRINGS.find { it in constant } - } - companion object { - const val JAR_EXT = ".jar" - const val CLASS_EXT = ".class" - val LIBS_PATH: Path = Paths.get("build", "libs") - private val INTERNAL_COMPANIONS = listOf("Char", "Byte", "Short", "Int", "Float", "Long", "Double", "String", "Enum") .map { "kotlin/jvm/internal/${it}CompanionObject" }