blob: 86e3b1dedfdbdc3da752a89e9c2b41564c613f34 [file] [log] [blame]
/*
* Copyright (C) 2020 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.integration.application
import com.android.SdkConstants.AAR_FORMAT_VERSION_PROPERTY
import com.android.SdkConstants.AAR_METADATA_VERSION_PROPERTY
import com.android.SdkConstants.MIN_COMPILE_SDK_PROPERTY
import com.android.build.gradle.integration.common.fixture.GradleTestProject
import com.android.build.gradle.integration.common.fixture.app.HelloWorldLibraryApp
import com.android.build.gradle.integration.common.utils.TestFileUtils
import com.android.build.gradle.internal.tasks.AarMetadataTask
import com.android.build.gradle.internal.tasks.CheckAarMetadataTask
import com.android.utils.FileUtils
import com.android.zipflinger.BytesSource
import com.android.zipflinger.ZipArchive
import com.google.common.base.Throwables
import com.google.common.truth.Truth.assertThat
import org.junit.Assert
import org.junit.Rule
import org.junit.Test
import java.io.File
import java.lang.StringBuilder
import java.nio.file.Files
import java.util.zip.Deflater
/** Tests for [CheckAarMetadataTask]. */
class CheckAarMetadataTaskTest {
@JvmField
@Rule
val project = GradleTestProject.builder().fromTestApp(HelloWorldLibraryApp.create()).create()
@Test
fun testBasic() {
// Test that app builds successfully when compatible minCompileSdkVersion set library.
project.getSubproject("lib").buildFile.appendText(
"android.defaultConfig.aarMetadata.minCompileSdk 28"
)
project.executor().run(":app:assembleDebug")
}
@Test
fun testMinCompileSdkVersion_librarySubModule() {
// Add resource requiring API level 28 to library
FileUtils.join(
project.getSubproject("lib").projectDir,
"src",
"main",
"res",
"values",
"values.xml"
).also {
it.parentFile.mkdirs()
}.writeText(
"""
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Foo">
<item name="dialogCornerRadius">?android:attr/dialogCornerRadius</item>
</style>
</resources>
""".trimIndent()
)
// Set app's compileSdkVersion to 24.
project.getSubproject("app").buildFile
TestFileUtils.searchRegexAndReplace(
project.getSubproject("app").buildFile,
"compileSdkVersion \\d+",
"compileSdkVersion 24"
)
// First test that the build fails when minCompileSdkVersion isn't set.
try {
project.executor().run(":app:assembleDebug")
Assert.fail("Expected build failure")
} catch (e: Exception) {
assertThat(Throwables.getRootCause(e).message)
.contains("Android resource linking failed")
}
// Then test that setting minCompileSdkVersion results in a better error message.
project.getSubproject("lib").buildFile.appendText(
"android.defaultConfig.aarMetadata.minCompileSdk 28"
)
try {
project.executor().run(":app:assembleDebug")
Assert.fail("Expected build failure")
} catch (e: Exception) {
assertThat(Throwables.getRootCause(e).message)
.contains("greater than this module's compileSdkVersion (android-24)")
}
}
@Test
fun testMinCompileSdkVersion_aarFileDependency() {
// Add resource requiring API level 28 to library
FileUtils.join(
project.getSubproject("lib").projectDir,
"src",
"main",
"res",
"values",
"values.xml"
).also {
it.parentFile.mkdirs()
}.writeText(
"""
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Foo">
<item name="dialogCornerRadius">?android:attr/dialogCornerRadius</item>
</style>
</resources>
""".trimIndent()
)
project.getSubproject("lib").buildFile.appendText(
"android.defaultConfig.aarMetadata.minCompileSdk 28"
)
project.executor().run(":lib:assembleDebug")
// Copy lib's .aar build output to the app's libs directory
FileUtils.copyFile(
project.getSubproject("lib").getOutputFile("aar", "lib-debug.aar"),
File(
File(project.getSubproject("app").projectDir, "libs").also { it.mkdirs() },
"library.aar"
)
)
// Set app's compileSdkVersion to 24.
project.getSubproject("app").buildFile
TestFileUtils.searchRegexAndReplace(
project.getSubproject("app").buildFile,
"compileSdkVersion \\d+",
"compileSdkVersion 24"
)
// Replace app's dependency on the library module with a dependency on the AAR file
TestFileUtils.searchAndReplace(
project.getSubproject("app").buildFile,
"project(':lib')",
"files('libs/library.aar')"
)
// Test that build fails with desired error message.
try {
project.executor().run(":app:assembleDebug")
Assert.fail("Expected build failure")
} catch (e: Exception) {
assertThat(Throwables.getRootCause(e).message)
.contains("greater than this module's compileSdkVersion (android-24)")
}
}
@Test
fun testMissingAarFormatVersion() {
addAarWithPossiblyInvalidAarMetadataToAppProject(
aarFormatVersion = null,
aarMetadataVersion = AarMetadataTask.AAR_METADATA_VERSION
)
// Test that build fails with desired error message.
try {
project.executor().run(":app:assembleDebug")
Assert.fail("Expected build failure")
} catch (e: Exception) {
assertThat(Throwables.getRootCause(e).message)
.contains("not specify an $AAR_FORMAT_VERSION_PROPERTY value")
}
}
@Test
fun testIncompatibleAarFormatVersion() {
addAarWithPossiblyInvalidAarMetadataToAppProject(
aarFormatVersion = "99999",
aarMetadataVersion = AarMetadataTask.AAR_METADATA_VERSION
)
// Test that build fails with desired error message.
try {
project.executor().run(":app:assembleDebug")
Assert.fail("Expected build failure")
} catch (e: Exception) {
assertThat(Throwables.getRootCause(e).message)
.contains("Please upgrade to a newer version of the Android Gradle Plugin.")
}
}
@Test
fun testInvalidAarFormatVersion() {
addAarWithPossiblyInvalidAarMetadataToAppProject(
aarFormatVersion = "invalid",
aarMetadataVersion = AarMetadataTask.AAR_METADATA_VERSION
)
// Test that build fails with desired error message.
try {
project.executor().run(":app:assembleDebug")
Assert.fail("Expected build failure")
} catch (e: Exception) {
assertThat(Throwables.getRootCause(e).message)
.contains("has an invalid $AAR_FORMAT_VERSION_PROPERTY value.")
}
}
@Test
fun testMissingAarMetadataVersion() {
addAarWithPossiblyInvalidAarMetadataToAppProject(
aarFormatVersion = AarMetadataTask.AAR_FORMAT_VERSION,
aarMetadataVersion = null
)
// Test that build fails with desired error message.
try {
project.executor().run(":app:assembleDebug")
Assert.fail("Expected build failure")
} catch (e: Exception) {
assertThat(Throwables.getRootCause(e).message)
.contains("not specify an $AAR_METADATA_VERSION_PROPERTY value")
}
}
@Test
fun testIncompatibleAarMetadataVersion() {
addAarWithPossiblyInvalidAarMetadataToAppProject(
aarFormatVersion = AarMetadataTask.AAR_FORMAT_VERSION,
aarMetadataVersion = "99999"
)
// Test that build fails with desired error message.
try {
project.executor().run(":app:assembleDebug")
Assert.fail("Expected build failure")
} catch (e: Exception) {
assertThat(Throwables.getRootCause(e).message)
.contains("Please upgrade to a newer version of the Android Gradle Plugin.")
}
}
@Test
fun testInvalidAarMetadataVersion() {
addAarWithPossiblyInvalidAarMetadataToAppProject(
aarFormatVersion = AarMetadataTask.AAR_FORMAT_VERSION,
aarMetadataVersion = "invalid"
)
// Test that build fails with desired error message.
try {
project.executor().run(":app:assembleDebug")
Assert.fail("Expected build failure")
} catch (e: Exception) {
assertThat(Throwables.getRootCause(e).message)
.contains("has an invalid $AAR_METADATA_VERSION_PROPERTY value.")
}
}
@Test
fun testInvalidMinCompileSdk() {
addAarWithPossiblyInvalidAarMetadataToAppProject(
aarFormatVersion = AarMetadataTask.AAR_FORMAT_VERSION,
aarMetadataVersion = AarMetadataTask.AAR_METADATA_VERSION,
minCompileSdk = "invalid"
)
// Test that build fails with desired error message.
try {
project.executor().run(":app:assembleDebug")
Assert.fail("Expected build failure")
} catch (e: Exception) {
assertThat(Throwables.getRootCause(e).message)
.contains("has an invalid $MIN_COMPILE_SDK_PROPERTY value.")
}
}
private fun addAarWithPossiblyInvalidAarMetadataToAppProject(
aarFormatVersion: String?,
aarMetadataVersion: String?,
minCompileSdk: String? = null
) {
project.executor().run(":lib:assembleDebug")
// Copy lib's .aar build output to the app's libs directory
val aarFile = project.getSubproject("app").projectDir.toPath().resolve("libs/library.aar")
Files.createDirectories(aarFile.parent)
FileUtils.copyFile(
project.getSubproject("lib").getOutputFile("aar", "lib-debug.aar"),
aarFile.toFile()
)
// Manually write (possibly invalid) AAR metadata entry
ZipArchive(aarFile).use { aar ->
aar.delete(AarMetadataTask.AAR_METADATA_ENTRY_PATH)
val sb = StringBuilder()
aarFormatVersion?.let { sb.appendln("$AAR_FORMAT_VERSION_PROPERTY=$it") }
aarMetadataVersion?.let { sb.appendln("$AAR_METADATA_VERSION_PROPERTY=$it") }
minCompileSdk?.let { sb.appendln("$MIN_COMPILE_SDK_PROPERTY=$it") }
aar.add(
BytesSource(
sb.toString().toByteArray(),
AarMetadataTask.AAR_METADATA_ENTRY_PATH,
Deflater.NO_COMPRESSION
)
)
}
// Replace app's dependency on the library module with a dependency on the AAR file
TestFileUtils.searchAndReplace(
project.getSubproject("app").buildFile,
"project(':lib')",
"files('libs/library.aar')"
)
}
}