/* * 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 kotlinx.coroutines.* import org.jf.dexlib2.* import org.junit.Test import java.io.* import java.util.stream.* import kotlin.test.* class R8ServiceLoaderOptimizationTest : TestBase() { private val r8Dex = File(System.getProperty("dexPath")!!).asDexFile() private val r8DexNoOptim = File(System.getProperty("noOptimDexPath")!!).asDexFile() @Test fun testNoServiceLoaderCalls() { 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 testAndroidDispatcherIsKept() { val hasAndroidDispatcher = r8DexNoOptim.classes.any { it.type == "Lkotlinx/coroutines/android/AndroidDispatcherFactory;" } assertEquals(true, hasAndroidDispatcher) } @Test @Ignore fun testNoOptimRulesMatch() { 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)