blob: 8ef93bcb02724fd63937965469d0a587c02decb6 [file] [log] [blame]
/*
* Copyright 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 androidx.build.testConfiguration
import androidx.build.dependencyTracker.ProjectSubset
import androidx.build.renameApkForTesting
import com.android.build.api.variant.BuiltArtifacts
import com.android.build.api.variant.BuiltArtifactsLoader
import org.gradle.api.DefaultTask
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
import java.io.File
/**
* Writes three configuration files to test combinations of media client & service in
* <a href=https://source.android.com/devices/tech/test_infra/tradefed/testing/through-suite/android-test-structure>AndroidTest.xml</a>
* format that gets zipped alongside the APKs to be tested. The combinations are of previous and
* tip-of-tree versions client and service. We want to test every possible pairing that includes
* tip-of-tree.
*
* This config gets ingested by Tradefed.
*/
abstract class GenerateMediaTestConfigurationTask : DefaultTask() {
@get:InputFiles
abstract val clientToTFolder: DirectoryProperty
@get:Internal
abstract val clientToTLoader: Property<BuiltArtifactsLoader>
@get:InputFiles
abstract val clientPreviousFolder: DirectoryProperty
@get:Internal
abstract val clientPreviousLoader: Property<BuiltArtifactsLoader>
@get:InputFiles
abstract val serviceToTFolder: DirectoryProperty
@get:Internal
abstract val serviceToTLoader: Property<BuiltArtifactsLoader>
@get:InputFiles
abstract val servicePreviousFolder: DirectoryProperty
@get:Internal
abstract val servicePreviousLoader: Property<BuiltArtifactsLoader>
@get:Input
abstract val affectedModuleDetectorSubset: Property<ProjectSubset>
@get:Input
abstract val clientToTPath: Property<String>
@get:Input
abstract val clientPreviousPath: Property<String>
@get:Input
abstract val serviceToTPath: Property<String>
@get:Input
abstract val servicePreviousPath: Property<String>
@get:Input
abstract val minSdk: Property<Int>
@get:Input
abstract val testRunner: Property<String>
@get:OutputFile
abstract val clientPreviousServiceToT: RegularFileProperty
@get:OutputFile
abstract val clientToTServicePrevious: RegularFileProperty
@get:OutputFile
abstract val clientToTServiceToT: RegularFileProperty
@TaskAction
fun generateAndroidTestZip() {
val clientToTApk = resolveApk(clientToTFolder, clientToTLoader)
val clientPreviousApk = resolveApk(clientPreviousFolder, clientPreviousLoader)
val serviceToTApk = resolveApk(serviceToTFolder, serviceToTLoader)
val servicePreviousApk = resolveApk(
servicePreviousFolder, servicePreviousLoader
)
writeConfigFileContent(
clientToTApk, serviceToTApk, clientToTPath.get(),
serviceToTPath.get(), clientToTServiceToT, false, false
)
writeConfigFileContent(
clientToTApk, servicePreviousApk, clientToTPath.get(),
servicePreviousPath.get(), clientToTServicePrevious, false, true
)
writeConfigFileContent(
clientPreviousApk, serviceToTApk, clientPreviousPath.get(),
serviceToTPath.get(), clientPreviousServiceToT, true, false
)
}
private fun resolveApk(
apkFolder: DirectoryProperty,
apkLoader: Property<BuiltArtifactsLoader>
): BuiltArtifacts {
return apkLoader.get().load(apkFolder.get())
?: throw RuntimeException("Cannot load required APK for task: $name")
}
private fun resolveName(apk: BuiltArtifacts, path: String): String {
return apk.elements.single().outputFile.substringAfterLast("/")
.renameApkForTesting(path, false)
}
private fun writeConfigFileContent(
clientApk: BuiltArtifacts,
serviceApk: BuiltArtifacts,
clientPath: String,
servicePath: String,
outputFile: RegularFileProperty,
isClientPrevious: Boolean,
isServicePrevious: Boolean
) {
val configBuilder = MediaConfigBuilder()
configBuilder.clientApkName(resolveName(clientApk, clientPath))
.clientApplicationId(clientApk.applicationId)
.serviceApkName(resolveName(serviceApk, servicePath))
.serviceApplicationId(serviceApk.applicationId)
.minSdk(minSdk.get().toString())
.testRunner(testRunner.get())
.isClientPrevious(isClientPrevious)
.isServicePrevious(isServicePrevious)
when (affectedModuleDetectorSubset.get()) {
ProjectSubset.CHANGED_PROJECTS, ProjectSubset.ALL_AFFECTED_PROJECTS -> {
configBuilder.isPostsubmit(true)
}
ProjectSubset.DEPENDENT_PROJECTS -> {
configBuilder.isPostsubmit(false)
}
else -> {
throw IllegalStateException(
"$name should not be running if the AffectedModuleDetector is returning " +
"${affectedModuleDetectorSubset.get()} for this project."
)
}
}
val resolvedOutputFile: File = outputFile.asFile.get()
if (!resolvedOutputFile.exists()) {
if (!resolvedOutputFile.createNewFile()) {
throw RuntimeException(
"Failed to create test configuration file: $outputFile"
)
}
}
resolvedOutputFile.writeText(configBuilder.build())
}
}