@@ -43,14 +43,18 @@ class PublicApiTest(
43
43
@Test
44
44
fun testApi () {
45
45
val libsDir = File (" ../$rootDir /$moduleName /build/libs" ).absoluteFile.normalize()
46
- val jarFile = getJarPath(libsDir)
46
+ val jarPath = getJarPath(libsDir)
47
47
val kotlinJvmMappingsFiles = listOf (libsDir.resolve(" ../visibilities.json" ))
48
48
val visibilities =
49
49
kotlinJvmMappingsFiles
50
50
.map { readKotlinVisibilities(it) }
51
51
.reduce { m1, m2 -> m1 + m2 }
52
- val api = getBinaryAPI(JarFile (jarFile), visibilities).filterOutNonPublic(nonPublicPackages)
53
- api.dumpAndCompareWith(File (" reference-public-api" ).resolve(" $moduleName .txt" ))
52
+ JarFile (jarPath).use { jarFile ->
53
+ val api = getBinaryAPI(jarFile, visibilities).filterOutNonPublic(nonPublicPackages)
54
+ api.dumpAndCompareWith(File (" reference-public-api" ).resolve(" $moduleName .txt" ))
55
+ // check for atomicfu leaks
56
+ jarFile.checkForAtomicFu()
57
+ }
54
58
}
55
59
56
60
private fun getJarPath (libsDir : File ): File {
@@ -68,3 +72,25 @@ class PublicApiTest(
68
72
error(" No single file matching $regex in $libsDir :\n ${files.joinToString(" \n " )} " )
69
73
}
70
74
}
75
+
76
+ private val ATOMIC_FU_REF = " Lkotlinx/atomicfu/" .toByteArray()
77
+
78
+ private fun JarFile.checkForAtomicFu () {
79
+ val foundClasses = mutableListOf<String >()
80
+ for (e in entries()) {
81
+ if (! e.name.endsWith(" .class" )) continue
82
+ val bytes = getInputStream(e).use { it.readBytes() }
83
+ loop@for (i in 0 until bytes.size - ATOMIC_FU_REF .size) {
84
+ for (j in 0 until ATOMIC_FU_REF .size) {
85
+ if (bytes[i + j] != ATOMIC_FU_REF [j]) continue @loop
86
+ }
87
+ foundClasses + = e.name // report error at the end with all class names
88
+ break @loop
89
+ }
90
+ }
91
+ if (foundClasses.isNotEmpty()) {
92
+ error(" Found references to atomicfu in jar file $name in the following class files: ${
93
+ foundClasses.joinToString(" " ) { " \n\t\t " + it }
94
+ } " )
95
+ }
96
+ }
0 commit comments