[Gradle] Make KotlinTest, KotlinTestReport partially cc-compatible

This commit is contained in:
Alexander Likhachev
2021-01-27 10:18:08 +03:00
parent c7421e2bea
commit 432c6486d5
5 changed files with 96 additions and 57 deletions
@@ -29,11 +29,14 @@ import javax.inject.Inject
open class KotlinJsTest open class KotlinJsTest
@Inject @Inject
constructor( constructor(
@Internal override var compilation: KotlinJsCompilation @Transient
@Internal
override var compilation: KotlinJsCompilation
) : ) :
KotlinTest(), KotlinTest(),
RequiresNpmDependencies { RequiresNpmDependencies {
private val nodeJs get() = NodeJsRootPlugin.apply(project.rootProject) private val nodeJs= NodeJsRootPlugin.apply(project.rootProject)
private val npmProject = compilation.npmProject
private val projectPath = project.path private val projectPath = project.path
@@ -69,22 +72,30 @@ constructor(
var debug: Boolean = false var debug: Boolean = false
@Suppress("unused") @Suppress("unused")
val runtimeClasspath: FileCollection @get:InputFiles
@InputFiles get() = compilation.runtimeDependencyFiles val runtimeClasspath: FileCollection by lazy {
compilation.runtimeDependencyFiles
}
@Suppress("unused") @Suppress("unused")
internal val compilationOutputs: FileCollection @get:InputFiles
@InputFiles get() = compilation.output.allOutputs internal val compilationOutputs: FileCollection by lazy {
compilation.output.allOutputs
}
@Suppress("unused") @Suppress("unused")
val compilationId: String @get:Input
@Input get() = compilation.let { val compilationId: String by lazy {
compilation.let {
val target = it.target val target = it.target
target.project.path + "@" + target.name + ":" + it.compilationName target.project.path + "@" + target.name + ":" + it.compilationName
} }
}
val nodeModulesToLoad: List<String> @get:Internal
@Internal get() = listOf("./" + compilation.npmProject.main) val nodeModulesToLoad: List<String> by lazy {
listOf("./" + compilation.npmProject.main)
}
override val nodeModulesRequired: Boolean override val nodeModulesRequired: Boolean
@Internal get() = testFramework!!.nodeModulesRequired @Internal get() = testFramework!!.nodeModulesRequired
@@ -115,7 +126,7 @@ constructor(
fun useKarma() = useKarma {} fun useKarma() = useKarma {}
fun useKarma(body: KotlinKarma.() -> Unit) = use( fun useKarma(body: KotlinKarma.() -> Unit) = use(
KotlinKarma(compilation, services, path), KotlinKarma(compilation, { services }, path),
body body
) )
fun useKarma(fn: Closure<*>) { fun useKarma(fn: Closure<*>) {
@@ -142,7 +153,7 @@ constructor(
override fun createTestExecutionSpec(): TCServiceMessagesTestExecutionSpec { override fun createTestExecutionSpec(): TCServiceMessagesTestExecutionSpec {
val forkOptions = DefaultProcessForkOptions(fileResolver) val forkOptions = DefaultProcessForkOptions(fileResolver)
forkOptions.workingDir = compilation.npmProject.dir forkOptions.workingDir = npmProject.dir
forkOptions.executable = nodeJs.requireConfigured().nodeExecutable forkOptions.executable = nodeJs.requireConfigured().nodeExecutable
val nodeJsArgs = mutableListOf<String>() val nodeJsArgs = mutableListOf<String>()
@@ -36,9 +36,15 @@ import org.jetbrains.kotlin.gradle.utils.property
import org.slf4j.Logger import org.slf4j.Logger
import java.io.File import java.io.File
class KotlinKarma(override val compilation: KotlinJsCompilation, private val services: ServiceRegistry, private val basePath: String) : class KotlinKarma(
@Transient override val compilation: KotlinJsCompilation,
private val services: () -> ServiceRegistry,
private val basePath: String
) :
KotlinJsTestFramework { KotlinJsTestFramework {
@Transient
private val project: Project = compilation.target.project private val project: Project = compilation.target.project
private val npmProject = compilation.npmProject
private val nodeJs = NodeJsRootPlugin.apply(project.rootProject) private val nodeJs = NodeJsRootPlugin.apply(project.rootProject)
private val versions = nodeJs.versions private val versions = nodeJs.versions
@@ -49,9 +55,11 @@ class KotlinKarma(override val compilation: KotlinJsCompilation, private val ser
private val envJsCollector = mutableMapOf<String, String>() private val envJsCollector = mutableMapOf<String, String>()
private val confJsWriters = mutableListOf<(Appendable) -> Unit>() private val confJsWriters = mutableListOf<(Appendable) -> Unit>()
private var sourceMaps = false private var sourceMaps = false
private val defaultConfigDirectory = project.projectDir.resolve("karma.config.d")
private var configDirectory: File by property { private var configDirectory: File by property {
project.projectDir.resolve("karma.config.d") defaultConfigDirectory
} }
private val isTeamCity = project.hasProperty(TC_PROJECT_PROPERTY)
override val requiredNpmDependencies: Set<RequiredKotlinJsDependency> override val requiredNpmDependencies: Set<RequiredKotlinJsDependency>
get() = requiredDependencies + webpackConfig.getRequiredDependencies(versions) get() = requiredDependencies + webpackConfig.getRequiredDependencies(versions)
@@ -277,8 +285,6 @@ class KotlinKarma(override val compilation: KotlinJsCompilation, private val ser
file: String, file: String,
debug: Boolean debug: Boolean
): File { ): File {
val npmProject = compilation.npmProject
val adapterJs = npmProject.dir.resolve("adapter-browser.js") val adapterJs = npmProject.dir.resolve("adapter-browser.js")
adapterJs.printWriter().use { writer -> adapterJs.printWriter().use { writer ->
val karmaRunner = npmProject.require("kotlin-test-js-runner/kotlin-test-karma-runner.js") val karmaRunner = npmProject.require("kotlin-test-js-runner/kotlin-test-karma-runner.js")
@@ -301,8 +307,6 @@ class KotlinKarma(override val compilation: KotlinJsCompilation, private val ser
nodeJsArgs: MutableList<String>, nodeJsArgs: MutableList<String>,
debug: Boolean debug: Boolean
): TCServiceMessagesTestExecutionSpec { ): TCServiceMessagesTestExecutionSpec {
val npmProject = compilation.npmProject
val file = task.nodeModulesToLoad val file = task.nodeModulesToLoad
.map { npmProject.require(it) } .map { npmProject.require(it) }
.single() .single()
@@ -341,7 +345,7 @@ class KotlinKarma(override val compilation: KotlinJsCompilation, private val ser
prependSuiteName = true, prependSuiteName = true,
stackTraceParser = ::parseNodeJsStackTraceAsJvm, stackTraceParser = ::parseNodeJsStackTraceAsJvm,
ignoreOutOfRootNodes = true, ignoreOutOfRootNodes = true,
escapeTCMessagesInLog = project.hasProperty(TC_PROJECT_PROPERTY) escapeTCMessagesInLog = isTeamCity
) )
config.basePath = npmProject.nodeModulesDir.absolutePath config.basePath = npmProject.nodeModulesDir.absolutePath
@@ -407,7 +411,7 @@ class KotlinKarma(override val compilation: KotlinJsCompilation, private val ser
lateinit var progressLogger: ProgressLogger lateinit var progressLogger: ProgressLogger
override fun wrapExecute(body: () -> Unit) { override fun wrapExecute(body: () -> Unit) {
services.operation("Running and building tests with karma and webpack") { services().operation("Running and building tests with karma and webpack") {
progressLogger = this progressLogger = this
body() body()
} }
@@ -21,11 +21,14 @@ import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTestFramework
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinTestRunnerCliArgs import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinTestRunnerCliArgs
import java.io.File import java.io.File
class KotlinMocha(override val compilation: KotlinJsCompilation, private val basePath: String) : class KotlinMocha(@Transient override val compilation: KotlinJsCompilation, private val basePath: String) :
KotlinJsTestFramework { KotlinJsTestFramework {
@Transient
private val project: Project = compilation.target.project private val project: Project = compilation.target.project
private val npmProject = compilation.npmProject
private val nodeJs = NodeJsRootPlugin.apply(project.rootProject) private val nodeJs = NodeJsRootPlugin.apply(project.rootProject)
private val versions = nodeJs.versions private val versions = nodeJs.versions
private val isTeamCity = project.hasProperty(TC_PROJECT_PROPERTY)
override val settingsState: String override val settingsState: String
get() = "mocha" get() = "mocha"
@@ -54,11 +57,9 @@ class KotlinMocha(override val compilation: KotlinJsCompilation, private val bas
prependSuiteName = true, prependSuiteName = true,
stackTraceParser = ::parseNodeJsStackTraceAsJvm, stackTraceParser = ::parseNodeJsStackTraceAsJvm,
ignoreOutOfRootNodes = true, ignoreOutOfRootNodes = true,
escapeTCMessagesInLog = project.hasProperty(TC_PROJECT_PROPERTY) escapeTCMessagesInLog = isTeamCity
) )
val npmProject = compilation.npmProject
val cliArgs = KotlinTestRunnerCliArgs( val cliArgs = KotlinTestRunnerCliArgs(
include = task.includePatterns, include = task.includePatterns,
exclude = task.excludePatterns exclude = task.excludePatterns
@@ -105,8 +106,6 @@ class KotlinMocha(override val compilation: KotlinJsCompilation, private val bas
private fun createAdapterJs( private fun createAdapterJs(
file: String file: String
): File { ): File {
val npmProject = compilation.npmProject
val adapterJs = npmProject.dir.resolve(ADAPTER_NODEJS) val adapterJs = npmProject.dir.resolve(ADAPTER_NODEJS)
adapterJs.printWriter().use { writer -> adapterJs.printWriter().use { writer ->
val adapter = npmProject.require("kotlin-test-js-runner/kotlin-test-nodejs-runner.js") val adapter = npmProject.require("kotlin-test-js-runner/kotlin-test-nodejs-runner.js")
@@ -58,11 +58,15 @@ abstract class KotlinTest : AbstractTestTask() {
runListeners.add(listener) runListeners.add(listener)
} }
private val ignoreTcsmOverflow by lazy {
PropertiesProvider(project).ignoreTcsmOverflow
}
override fun createTestExecuter() = TCServiceMessagesTestExecutor( override fun createTestExecuter() = TCServiceMessagesTestExecutor(
execHandleFactory, execHandleFactory,
buildOperationExecutor, buildOperationExecutor,
runListeners, runListeners,
PropertiesProvider(project).ignoreTcsmOverflow, ignoreTcsmOverflow,
ignoreRunFailures ignoreRunFailures
) )
} }
@@ -41,18 +41,24 @@ import java.net.URI
* event if child tasks will be executed. * event if child tasks will be executed.
*/ */
open class KotlinTestReport : TestReport() { open class KotlinTestReport : TestReport() {
@Transient
@Internal @Internal
val testTasks = mutableListOf<AbstractTestTask>() val testTasks = mutableListOf<AbstractTestTask>()
@Transient
private var parent: KotlinTestReport? = null private var parent: KotlinTestReport? = null
// TODO: used in task action when the task is aggregate report, non compatible with configuration cache
@Internal @Internal
val children = mutableListOf<TaskProvider<KotlinTestReport>>() val children = mutableListOf<TaskProvider<KotlinTestReport>>()
@Transient
private val projectProperties = PropertiesProvider(project) private val projectProperties = PropertiesProvider(project)
val overrideReporting: Boolean @get:Input
@Input get() = projectProperties.individualTaskReports == null val overrideReporting: Boolean by lazy {
projectProperties.individualTaskReports == null
}
@Input @Input
var checkFailedTests: Boolean = false var checkFailedTests: Boolean = false
@@ -60,28 +66,14 @@ open class KotlinTestReport : TestReport() {
@Input @Input
var ignoreFailures: Boolean = false var ignoreFailures: Boolean = false
private var hasOwnFailedTests = false private val hasOwnFailedTests
get() = failedTestsListener.hasOwnFailedTests ?: false
private val hasFailedTests: Boolean private val hasFailedTests: Boolean
get() = hasOwnFailedTests || children.any { it.get().hasFailedTests } get() = hasOwnFailedTests || children.any { it.get().hasFailedTests }
private val ownSuppressedRunningFailures = mutableListOf<Pair<KotlinTest, Error>>() private val suppressedRunningFailureListeners: MutableSet<SuppressedTestRunningFailureListener> = mutableSetOf()
private val failedTestsListener = object : TestListener { private val failedTestsListener = FailedTestListener()
override fun beforeTest(testDescriptor: TestDescriptor) {
}
override fun afterSuite(suite: TestDescriptor, result: TestResult) {
}
override fun beforeSuite(suite: TestDescriptor) {
}
override fun afterTest(testDescriptor: TestDescriptor, result: TestResult) {
if (result.failedTestCount > 0) {
hasOwnFailedTests = true
}
}
}
fun addChild(childProvider: TaskProvider<KotlinTestReport>) { fun addChild(childProvider: TaskProvider<KotlinTestReport>) {
val child = childProvider.get() val child = childProvider.get()
@@ -108,11 +100,11 @@ open class KotlinTestReport : TestReport() {
testTasks.add(task) testTasks.add(task)
task.addTestListener(failedTestsListener) task.addTestListener(failedTestsListener)
if (task is KotlinTest) task.addRunListener(object : KotlinTestRunnerListener { if (task is KotlinTest) {
override fun runningFailure(failure: Error) { val listener = SuppressedTestRunningFailureListener(task.path)
ownSuppressedRunningFailures.add(task to failure) task.addRunListener(listener)
} suppressedRunningFailureListeners.add(listener)
}) }
reportOn(task) reportOn(task)
addToParents(task) addToParents(task)
@@ -163,11 +155,11 @@ open class KotlinTestReport : TestReport() {
} }
private fun checkSuppressedRunningFailures() { private fun checkSuppressedRunningFailures() {
val allSuppressedRunningFailures = mutableListOf<Pair<KotlinTest, Error>>() val allSuppressedRunningFailures = mutableListOf<Pair<String, Error>>()
fun visitSuppressedRunningFailures(report: KotlinTestReport) { fun visitSuppressedRunningFailures(report: KotlinTestReport) {
report.ownSuppressedRunningFailures.forEach { report.suppressedRunningFailureListeners.filter { it.failure != null }.forEach {
allSuppressedRunningFailures.add(it) allSuppressedRunningFailures.add(it.taskPath to it.failure!!)
} }
report.children.forEach { report.children.forEach {
@@ -181,8 +173,8 @@ open class KotlinTestReport : TestReport() {
val allErrors = mutableListOf<Error>() val allErrors = mutableListOf<Error>()
val msg = buildString { val msg = buildString {
appendln("Failed to execute all tests:") appendln("Failed to execute all tests:")
allSuppressedRunningFailures.groupBy { it.first }.forEach { test, errors -> allSuppressedRunningFailures.groupBy { it.first }.forEach { path, errors ->
append(test.path) append(path)
append(": ") append(": ")
var first = true var first = true
errors.forEach { (_, error) -> errors.forEach { (_, error) ->
@@ -251,4 +243,33 @@ open class KotlinTestReport : TestReport() {
task.reports.junitXml.isEnabled = false task.reports.junitXml.isEnabled = false
} }
private class SuppressedTestRunningFailureListener(val taskPath: String) : KotlinTestRunnerListener {
@Transient
var failure: Error? = null
override fun runningFailure(failure: Error) {
this.failure = failure
}
}
private class FailedTestListener : TestListener {
@Transient
var hasOwnFailedTests: Boolean? = false
override fun beforeTest(testDescriptor: TestDescriptor) {
}
override fun afterSuite(suite: TestDescriptor, result: TestResult) {
}
override fun beforeSuite(suite: TestDescriptor) {
}
override fun afterTest(testDescriptor: TestDescriptor, result: TestResult) {
if (result.failedTestCount > 0) {
hasOwnFailedTests = true
}
}
}
} }