All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.gradle.testing.internal.KotlinTestsRegistry.kt Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version
/*
 * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
 * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
 */

package org.jetbrains.kotlin.gradle.testing.internal

import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.plugins.BasePlugin
import org.gradle.api.plugins.JavaBasePlugin
import org.gradle.api.tasks.TaskProvider
import org.gradle.api.tasks.testing.AbstractTestTask
import org.gradle.language.base.plugins.LifecycleBasePlugin
import org.jetbrains.kotlin.gradle.logging.kotlinInfo
import org.jetbrains.kotlin.gradle.plugin.internal.KotlinTestReportCompatibilityHelper
import org.jetbrains.kotlin.gradle.plugin.variantImplementationFactory
import org.jetbrains.kotlin.gradle.tasks.dependsOn
import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask
import org.jetbrains.kotlin.gradle.tasks.registerTask
import org.jetbrains.kotlin.gradle.tasks.locateTask
import org.jetbrains.kotlin.gradle.utils.readSystemPropertyAtConfigurationTime
import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly

/**
 * Internal service for creating aggregated test tasks and registering all test tasks.
 * See [KotlinTestReport] for more details about aggregated test tasks.
 */
class KotlinTestsRegistry(val project: Project, val allTestsTaskName: String = "allTests") {
    val allTestsTask: TaskProvider
        get() = doGetOrCreateAggregatedTestTask(
            name = allTestsTaskName,
            description = "Runs the tests for all targets and create aggregated report"
        ).also {
            project.tasks.named(LifecycleBasePlugin.CHECK_TASK_NAME).dependsOn(it)
        }

    fun registerTestTask(
        taskHolder: TaskProvider,
        aggregate: TaskProvider = allTestsTask
    ) {
        project.tasks.named(LifecycleBasePlugin.CHECK_TASK_NAME).dependsOn(taskHolder)
        project.cleanAllTestTask.configure { it.dependsOn(cleanTaskName(taskHolder.name)) }
        val testReportService = TestReportService.registerIfAbsent(project)
        aggregate.configure {
            it.dependsOn(taskHolder.name)
            it.registerTestTask(taskHolder.get())
        }
        taskHolder.configure { task ->
            task.usesService(testReportService)
            task.outputs.upToDateWhen {
                val hasFailedPreviously = testReportService.get().hasTestTaskFailedPreviously(it.path)
                if (hasFailedPreviously) {
                    task.logger.kotlinInfo("Marking $it as not up-to-date because the task has failed previously")
                }
                !hasFailedPreviously
            }
        }

        taskHolder.configure { task ->
            ijListenTestTask(task)
        }
    }

    fun getOrCreateAggregatedTestTask(
        name: String,
        description: String,
        parent: TaskProvider? = allTestsTask
    ): TaskProvider {
        if (name == parent?.name) return parent

        return doGetOrCreateAggregatedTestTask(name, description, parent)
    }

    private fun doGetOrCreateAggregatedTestTask(
        name: String,
        description: String,
        parent: TaskProvider? = null,
        configure: (TaskProvider) -> Unit = {}
    ): TaskProvider {
        val existed = project.locateTask(name)
        if (existed != null) return existed

        val reportName = name
        val testReportService = TestReportService.registerIfAbsent(project)
        val aggregate: TaskProvider = project.registerTask(name) { aggregate ->
            aggregate.description = description
            aggregate.group = JavaBasePlugin.VERIFICATION_GROUP

            val compatibilityHelper = project
                .variantImplementationFactory()
                .getInstance(project.objects)

            compatibilityHelper.setDestinationDirectory(aggregate, project.testReportsDir.resolve(reportName))

            val isIdeaActive = project.readSystemPropertyAtConfigurationTime("idea.active").isPresent

            if (isIdeaActive) {
                aggregate.extensions.extraProperties.set("idea.internal.test", true)
            }
            aggregate.htmlReportFile.value(compatibilityHelper.getDestinationDirectory(aggregate).file("index.html")).disallowChanges()
            aggregate.testReportServiceProvider.value(testReportService).finalizeValueOnRead()
            aggregate.testReportCompatibilityHelper.value(compatibilityHelper).finalizeValueOnRead()

            project.gradle.taskGraph.whenReady { graph ->
                aggregate.maybeOverrideReporting(graph)
            }
        }

        parent?.configure {
            it.addChild(aggregate)
            it.dependsOn(aggregate)
        }

        configure(aggregate)

        return aggregate
    }

    private fun cleanTaskName(taskName: String): String {
        check(taskName.isNotEmpty())
        return "clean" + taskName.capitalizeAsciiOnly()
    }

    private val Project.cleanAllTestTask: TaskProvider<*>
        get() {
            val taskName = cleanTaskName(allTestsTask.name)
            return project.locateOrRegisterTask(taskName) { cleanAllTest ->
                cleanAllTest.group = BasePlugin.BUILD_GROUP
                cleanAllTest.description = "Deletes all the test results."
            }.also { cleanAllTest ->
                tasks.named(LifecycleBasePlugin.CLEAN_TASK_NAME).dependsOn(cleanAllTest)
            }
        }

    companion object {
        const val PROJECT_EXTENSION_NAME = "kotlinTestRegistry"
    }
}

internal val Project.kotlinTestRegistry: KotlinTestsRegistry
    get() = extensions.getByName(KotlinTestsRegistry.PROJECT_EXTENSION_NAME) as KotlinTestsRegistry




© 2015 - 2024 Weber Informatics LLC | Privacy Policy