blob: 2d2281bdfe95e9c85f230d3ee9d379d13e7a2d70 [file] [log] [blame]
/*
* Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
package kotlinx.coroutines.android
import org.jf.dexlib2.*
import org.junit.Test
import java.io.*
import java.util.stream.*
import kotlin.test.*
class R8ServiceLoaderOptimizationTest {
private val r8Dex = File(System.getProperty("dexPath")!!).asDexFile()
private val r8DexNoOptim = File(System.getProperty("noOptimDexPath")!!).asDexFile()
@Test
fun noServiceLoaderCalls() {
val serviceLoaderInvocations = r8Dex.types.any {
it.type == "Ljava/util/ServiceLoader;"
}
assertEquals(
false,
serviceLoaderInvocations,
"References to the ServiceLoader class were found in the resulting DEX."
)
}
@Test
fun androidDispatcherIsKept() {
val hasAndroidDispatcher = r8DexNoOptim.classes.any {
it.type == "Lkotlinx/coroutines/android/AndroidDispatcherFactory;"
}
assertEquals(true, hasAndroidDispatcher)
}
@Test
fun noOptimRulesMatch() {
val paths = listOf(
"META-INF/com.android.tools/proguard/coroutines.pro",
"META-INF/proguard/coroutines.pro",
"META-INF/com.android.tools/r8-upto-1.6.0/coroutines.pro"
)
paths.associateWith { path ->
val ruleSet = javaClass.classLoader.getResourceAsStream(path)!!.bufferedReader().lines().filter { line ->
line.isNotBlank() && !line.startsWith("#")
}.collect(Collectors.toSet())
ruleSet
}.asSequence().reduce { acc, entry ->
assertEquals(
acc.value,
entry.value,
"Rule sets between ${acc.key} and ${entry.key} don't match."
)
entry
}
}
}
private fun File.asDexFile() = DexFileFactory.loadDexFile(this, null)