blob: 1ec437fe31b35cabcfe3e6f4106a6fde6dae6560 [file] [log] [blame]
import org.gradle.work.DisableCachingByDefault
import static androidx.baselineprofile.gradle.utils.UtilsKt.camelCase
// To trigger the baseline profile generation using the different modules the test will call
// the base generation task `generateBaselineProfile`. The `AssertEqualsAndCleanUpTask` asserts
// that the final output is the expected one and if there are no failures cleans up the
// generated baseline-prof.txt.
@DisableCachingByDefault(because = "Integration test task")
abstract class AssertEqualsAndCleanUpTask extends DefaultTask {
@InputFile
@PathSensitive(PathSensitivity.NONE)
abstract RegularFileProperty getExpectedFile()
// This property is passed as path and not as a file because it might not exist
@Input
abstract Property<String> getActualFilePath()
@TaskAction
void exec() {
File expectedFile = getExpectedFile().get().asFile
File actualFile = new File(actualFilePath.get())
if (!expectedFile.exists() && actualFile.exists()) {
throw new GradleException("No profile was expected in ${actualFile.absolutePath}.")
}
if (expectedFile.exists() && !actualFile.exists()) {
throw new GradleException("A profile was expected in ${actualFile.absolutePath}.")
}
if (!actualFile.exists()) {
throw new GradleException(
"A profile was expected in ${actualFile.absolutePath}."
)
}
def expectedIter = expectedFile.text.lines().iterator()
def actualIter = actualFile.text.lines().iterator()
def lineCounter = 0
def diff = new ArrayList<String>()
while (expectedIter.hasNext() || actualIter.hasNext()) {
def expected = expectedIter.hasNext() ? expectedIter.next() : ""
def actual = actualIter.hasNext() ? actualIter.next() : ""
if (expected != actual) {
diff.add("Line: $lineCounter, Expected: `$expected`, Actual: `$actual`")
}
lineCounter++
}
if (!diff.isEmpty()) {
logger.error("Actual generated profile differs from expected one: \n\t"
+ diff.join("\n\t"))
throw new GradleException("Actual generated profile differs from expected one.")
}
// This deletes the actual file since it's a test artifact
actualFile.delete()
}
}
// For each variant we expect `expected-baseline-prof.txt` and `baseline-prof.txt` to be
// present and have the same content.
def testTaskProviders = []
def registerAssertTask(
ArrayList<TaskProvider<Task>> testTaskProviders,
String variantName,
String taskName,
String expectedFilename,
String filename
) {
def expectedBaselineProfileSubDir = "generated/baselineProfiles"
def expectedFile = project
.layout
.projectDirectory
.file("src/$variantName/$expectedBaselineProfileSubDir/${expectedFilename}.txt")
// If there is no expected file then skip testing this variant.
if (!expectedFile.asFile.exists()) {
return
}
def taskProvider = project.tasks.register(
camelCase("test", variantName, "${taskName}Generation"),
AssertEqualsAndCleanUpTask
) {
it.expectedFile.set(expectedFile)
it.actualFilePath.set(project
.layout
.projectDirectory
.file("src/$variantName/$expectedBaselineProfileSubDir/${filename}.txt")
.getAsFile()
.absolutePath)
// Depend on the main profile generation task
it.dependsOn(tasks.named(camelCase("generate", variantName, "baselineProfile")))
}
testTaskProviders.add(taskProvider)
}
// An assert task is defined per variant
androidComponents {
onVariants(selector().all()) { variant ->
registerAssertTask(
testTaskProviders,
variant.name,
"baselineProfile",
"expected-baseline-prof",
"baseline-prof"
)
registerAssertTask(
testTaskProviders,
variant.name,
"startupProfile",
"expected-startup-prof",
"startup-prof"
)
}
}
// Ensures that calling `testBaselineProfileGeneration` runs all the test tasks
afterEvaluate {
tasks.register("testBaselineProfileGeneration").configure {
it.dependsOn(testTaskProviders)
}
}