1 /* <lambda>null2 * 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.android 6 7 import org.jf.dexlib2.* 8 import org.junit.Test 9 import java.io.* 10 import java.util.stream.* 11 import kotlin.test.* 12 13 class R8ServiceLoaderOptimizationTest { 14 private val r8Dex = File(System.getProperty("dexPath")!!).asDexFile() 15 private val r8DexNoOptim = File(System.getProperty("noOptimDexPath")!!).asDexFile() 16 17 @Test 18 fun noServiceLoaderCalls() { 19 val serviceLoaderInvocations = r8Dex.types.any { 20 it.type == "Ljava/util/ServiceLoader;" 21 } 22 assertEquals( 23 false, 24 serviceLoaderInvocations, 25 "References to the ServiceLoader class were found in the resulting DEX." 26 ) 27 } 28 29 @Test 30 fun androidDispatcherIsKept() { 31 val hasAndroidDispatcher = r8DexNoOptim.classes.any { 32 it.type == "Lkotlinx/coroutines/android/AndroidDispatcherFactory;" 33 } 34 35 assertEquals(true, hasAndroidDispatcher) 36 } 37 38 @Test 39 fun noOptimRulesMatch() { 40 val paths = listOf( 41 "META-INF/com.android.tools/proguard/coroutines.pro", 42 "META-INF/proguard/coroutines.pro", 43 "META-INF/com.android.tools/r8-upto-1.6.0/coroutines.pro" 44 ) 45 paths.associateWith { path -> 46 val ruleSet = javaClass.classLoader.getResourceAsStream(path)!!.bufferedReader().lines().filter { line -> 47 line.isNotBlank() && !line.startsWith("#") 48 }.collect(Collectors.toSet()) 49 ruleSet 50 }.asSequence().reduce { acc, entry -> 51 assertEquals( 52 acc.value, 53 entry.value, 54 "Rule sets between ${acc.key} and ${entry.key} don't match." 55 ) 56 entry 57 } 58 } 59 } 60 asDexFilenull61private fun File.asDexFile() = DexFileFactory.loadDexFile(this, null) 62