blob: d554a65ccfa011590f0ae80786b8c0fb71c89874 [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.build.gradle.internal.transforms
import com.android.build.api.transform.Context
import com.android.build.api.transform.QualifiedContent.DefaultContentType.CLASSES
import com.android.build.api.transform.TransformOutputProvider
import com.android.build.gradle.internal.fixtures.FakeConfigurableFileCollection
import com.android.build.gradle.internal.fixtures.FakeFileCollection
import com.android.build.gradle.internal.scope.VariantScope
import com.android.build.gradle.internal.transforms.testdata.Animal
import com.android.build.gradle.internal.transforms.testdata.CarbonForm
import com.android.build.gradle.internal.transforms.testdata.Toy
import com.android.builder.core.VariantTypeImpl
import com.android.builder.dexing.DexingType
import com.android.testutils.TestInputsGenerator
import com.android.testutils.TestUtils
import com.android.testutils.apk.Dex
import com.android.testutils.truth.MoreTruth.assertThat
import com.android.testutils.truth.MoreTruth.assertThatDex
import com.android.testutils.truth.PathSubject.assertThat
import org.gradle.api.file.FileCollection
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
import org.mockito.Mockito
import org.objectweb.asm.Type
import java.nio.file.Path
/**
* Testing scenarios for R8 transform processing class files which outputs DEX.
*/
class R8MainDexListTransformTest {
@get: Rule
val tmp: TemporaryFolder = TemporaryFolder()
private lateinit var context: Context
private lateinit var outputProvider: TransformOutputProvider
private lateinit var outputDir: Path
@Before
fun setUp() {
outputDir = tmp.newFolder().toPath()
outputProvider = TestTransformOutputProvider(outputDir)
context = Mockito.mock(Context::class.java)
}
@Test
fun testMainDexRules() {
val classes = tmp.root.toPath().resolve("classes.jar")
TestInputsGenerator.pathWithClasses(
classes,
listOf(Animal::class.java, CarbonForm::class.java, Toy::class.java)
)
val jarInput = TransformTestHelper.singleJarBuilder(classes.toFile())
.setContentTypes(CLASSES)
.build()
val invocation =
TransformTestHelper
.invocationBuilder()
.addInput(jarInput)
.setContext(this.context)
.setTransformOutputProvider(outputProvider)
.build()
val mainDexRuleFile = tmp.newFile()
mainDexRuleFile.printWriter().use {
it.println("-keep class " + Animal::class.java.name)
}
val mainDexRulesFileCollection = FakeFileCollection(setOf(mainDexRuleFile))
val transform =
createTransform(mainDexRulesFiles = mainDexRulesFileCollection, minSdkVersion = 19)
transform.keep("class **")
transform.transform(invocation)
val mainDex = Dex(outputDir.resolve("main").resolve("classes.dex"))
assertThat(mainDex)
.containsExactlyClassesIn(
listOf(
Type.getDescriptor(CarbonForm::class.java),
Type.getDescriptor(Animal::class.java)
)
)
val secondaryDex = Dex(outputDir.resolve("main").resolve("classes2.dex"))
assertThat(secondaryDex).containsExactlyClassesIn(listOf(Type.getDescriptor(Toy::class.java)))
}
@Test
fun testMonoDex() {
val classes = tmp.root.toPath().resolve("classes.jar")
TestInputsGenerator.pathWithClasses(
classes,
listOf(Animal::class.java, CarbonForm::class.java, Toy::class.java)
)
val jarInput = TransformTestHelper.singleJarBuilder(classes.toFile())
.setContentTypes(CLASSES)
.build()
val invocation =
TransformTestHelper
.invocationBuilder()
.addInput(jarInput)
.setContext(this.context)
.setTransformOutputProvider(outputProvider)
.build()
val mainDexRuleFile = tmp.newFile()
mainDexRuleFile.printWriter().use {
it.println("-keep class " + CarbonForm::class.java.name)
}
val mainDexRulesFileCollection = FakeFileCollection(setOf(mainDexRuleFile))
val transform =
createTransform(
mainDexRulesFiles = mainDexRulesFileCollection,
minSdkVersion = 19,
dexingType = DexingType.MONO_DEX
)
transform.keep("class **")
transform.transform(invocation)
assertThatDex(outputDir.resolve("main/classes.dex").toFile())
.containsExactlyClassesIn(
listOf(
Type.getDescriptor(CarbonForm::class.java),
Type.getDescriptor(Animal::class.java),
Type.getDescriptor(Toy::class.java)
)
)
assertThat(outputDir.resolve("main/classes2.dex")).doesNotExist()
}
private fun createTransform(
mainDexRulesFiles: FileCollection = FakeFileCollection(),
minSdkVersion: Int = 21,
dexingType: DexingType = DexingType.LEGACY_MULTIDEX
): R8Transform {
return R8Transform(
bootClasspath = lazy { listOf(TestUtils.getPlatformFile("android.jar")) },
minSdkVersion = minSdkVersion,
isDebuggable = true,
java8Support = VariantScope.Java8LangSupport.UNUSED,
disableTreeShaking = false,
disableMinification = true,
mainDexListFiles = FakeFileCollection(),
mainDexRulesFiles = mainDexRulesFiles,
inputProguardMapping = FakeFileCollection(),
outputProguardMapping = tmp.newFile(),
proguardConfigurationFiles = FakeConfigurableFileCollection(),
variantType = VariantTypeImpl.BASE_APK,
includeFeaturesInScopes = false,
messageReceiver = NoOpMessageReceiver(),
dexingType = dexingType,
useFullR8 = false
)
}
}