From 6bbc57794273e4f59ff92580b28da041a19d131a Mon Sep 17 00:00:00 2001 From: Alexander Likhachev Date: Thu, 1 Dec 2022 19:14:44 +0100 Subject: [PATCH] [Gradle] Introduce MppTestReportHelper to handle differences in internal Gradle testing API #KT-54634 Fixed --- .../testing/TCServiceMessagesClient.kt | 29 ++++---- .../testing/TCServiceMessagesTestExecutor.kt | 14 ++-- .../gradle/plugin/KotlinPluginWrapper.kt | 5 ++ .../plugin/internal/MppTestReportHelper.kt | 66 +++++++++++++++++++ .../targets/js/testing/JSServiceMessages.kt | 11 ++-- .../targets/js/testing/karma/KotlinKarma.kt | 6 +- .../gradle/targets/jvm/tasks/KotlinJvmTest.kt | 26 ++++---- .../kotlin/gradle/tasks/KotlinTest.kt | 9 ++- .../gradle/testing/KotlinTestFailure.kt | 5 +- .../kotlin/gradle/plugin/PluginWrappers.kt | 2 + .../plugin/internal/MppTestReportHelperG70.kt | 43 ++++++++++++ .../kotlin/gradle/plugin/PluginWrappers.kt | 5 +- .../plugin/internal/MppTestReportHelperG71.kt | 43 ++++++++++++ .../kotlin/gradle/plugin/PluginWrappers.kt | 7 +- .../plugin/internal/MppTestReportHelperG75.kt | 43 ++++++++++++ .../kotlin/gradle/plugin/PluginWrappers.kt | 2 + .../plugin/internal/MppTestReportHelperG6.kt | 43 ++++++++++++ .../tcsmc/TCServiceMessagesClientTest.kt | 13 +++- 18 files changed, 326 insertions(+), 46 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/MppTestReportHelper.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/gradle70/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/MppTestReportHelperG70.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/gradle71/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/MppTestReportHelperG71.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/gradle75/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/MppTestReportHelperG75.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/MppTestReportHelperG6.kt diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesClient.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesClient.kt index f893a3af03d..7e3effcf278 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesClient.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesClient.kt @@ -15,6 +15,7 @@ import org.gradle.api.tasks.testing.TestResult.ResultType.* import org.gradle.internal.operations.OperationIdentifier import org.gradle.process.internal.ExecHandle import org.jetbrains.kotlin.gradle.internal.LogType +import org.jetbrains.kotlin.gradle.plugin.internal.MppTestReportHelper import org.jetbrains.kotlin.gradle.logging.kotlinDebug import org.jetbrains.kotlin.gradle.testing.KotlinTestFailure import org.jetbrains.kotlin.gradle.utils.LegacyTestDescriptorInternal @@ -35,7 +36,8 @@ data class TCServiceMessagesClientSettings( internal open class TCServiceMessagesClient( private val results: TestResultProcessor, val settings: TCServiceMessagesClientSettings, - val log: Logger + val log: Logger, + val testReporter: MppTestReportHelper, ) : ServiceMessageParserCallback { lateinit var rootOperationId: OperationIdentifier var afterMessage = false @@ -155,7 +157,8 @@ internal open class TCServiceMessagesClient( } private fun TestNode.failure( - message: TestFailed + message: TestFailed, + isAssertionFailure: Boolean = true, ) { hasFailures = true @@ -173,18 +176,16 @@ internal open class TCServiceMessagesClient( val parsedStackTrace = settings.stackTraceParser(stacktrace) val failMessage = parsedStackTrace?.message ?: message.failureMessage - results.failure( - descriptor.id, - KotlinTestFailure( - failMessage?.let { extractExceptionClassName(it) } - ?: "Unknown", - failMessage, - stacktrace, - patchStackTrace(this, parsedStackTrace?.stackTrace), - message.expected, - message.actual - ) + val exceptionClassName = failMessage?.let { extractExceptionClassName(it) } ?: "Unknown" + val rawFailure = KotlinTestFailure( + exceptionClassName, + failMessage, + stacktrace, + patchStackTrace(this, parsedStackTrace?.stackTrace), + message.expected, + message.actual, ) + testReporter.reportFailure(results, descriptor.id, rawFailure, isAssertionFailure) } private fun extractExceptionClassName(message: String): String = @@ -527,7 +528,7 @@ internal open class TCServiceMessagesClient( if (currentLeaf is TestNode) { currentTest = currentLeaf output.append(currentLeaf.allOutput) - currentLeaf.failure(TestFailed(currentLeaf.cleanName, null as Throwable?)) + currentLeaf.failure(TestFailed(currentLeaf.cleanName, null as Throwable?), false) } close(ts, currentLeaf.localId) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesTestExecutor.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesTestExecutor.kt index 560acb9ddd6..1335ea4660d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesTestExecutor.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesTestExecutor.kt @@ -13,6 +13,7 @@ import org.gradle.process.ExecResult import org.gradle.process.ProcessForkOptions import org.gradle.process.internal.ExecHandle import org.gradle.process.internal.ExecHandleFactory +import org.jetbrains.kotlin.gradle.plugin.internal.MppTestReportHelper import org.slf4j.Logger import org.slf4j.LoggerFactory import java.io.OutputStream @@ -24,8 +25,12 @@ open class TCServiceMessagesTestExecutionSpec( val clientSettings: TCServiceMessagesClientSettings, val dryRunArgs: List? = null, ) : TestExecutionSpec { - internal open fun createClient(testResultProcessor: TestResultProcessor, log: Logger): TCServiceMessagesClient = - TCServiceMessagesClient(testResultProcessor, clientSettings, log) + internal open fun createClient( + testResultProcessor: TestResultProcessor, + log: Logger, + testReporter: MppTestReportHelper, + ): TCServiceMessagesClient = + TCServiceMessagesClient(testResultProcessor, clientSettings, log, testReporter) internal open fun wrapExecute(body: () -> Unit) = body() internal open fun showSuppressedOutput() = Unit @@ -38,7 +43,8 @@ class TCServiceMessagesTestExecutor( val buildOperationExecutor: BuildOperationExecutor, val runListeners: MutableList, val ignoreTcsmOverflow: Boolean, - val ignoreRunFailures: Boolean + val ignoreRunFailures: Boolean, + val testReporter: MppTestReportHelper, ) : TestExecuter { private lateinit var execHandle: ExecHandle var outputReaderThread: Thread? = null @@ -48,7 +54,7 @@ class TCServiceMessagesTestExecutor( spec.wrapExecute { val rootOperation = buildOperationExecutor.currentOperation.parentId!! - val client = spec.createClient(testResultProcessor, log) + val client = spec.createClient(testResultProcessor, log, testReporter) if (spec.dryRunArgs != null) { val exec = execHandleFactory.newExec() diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt index 68e8875b3b7..96032410f2c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt @@ -146,6 +146,11 @@ abstract class DefaultKotlinBasePlugin : KotlinBasePlugin { ConfigurationTimePropertiesAccessor.ConfigurationTimePropertiesAccessorVariantFactory::class, DefaultConfigurationTimePropertiesAccessorVariantFactory() ) + + factories.putIfAbsent( + MppTestReportHelper.MppTestReportHelperVariantFactory::class, + DefaultMppTestReportHelperVariantFactory() + ) } protected fun setupAttributeMatchingStrategy( diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/MppTestReportHelper.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/MppTestReportHelper.kt new file mode 100644 index 00000000000..6f13a84ebc8 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/MppTestReportHelper.kt @@ -0,0 +1,66 @@ +/* + * Copyright 2010-2022 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.plugin.internal + +import org.gradle.api.internal.tasks.testing.TestDescriptorInternal +import org.gradle.api.internal.tasks.testing.TestResultProcessor +import org.gradle.api.internal.tasks.testing.TestStartEvent +import org.gradle.api.tasks.testing.TestFailure +import org.jetbrains.kotlin.gradle.plugin.VariantImplementationFactories +import org.jetbrains.kotlin.gradle.testing.KotlinTestFailure + +/** + * Handles differences in internal Gradle testing API before and since Gradle 7.6 + */ +interface MppTestReportHelper { + fun reportFailure( + results: TestResultProcessor, + id: Any, + failure: KotlinTestFailure, + isAssertionFailure: Boolean, + ) + + fun createDelegatingTestReportProcessor(origin: TestResultProcessor, targetName: String): TestResultProcessor + + interface MppTestReportHelperVariantFactory : VariantImplementationFactories.VariantImplementationFactory { + fun getInstance(): MppTestReportHelper + } +} + +internal class DefaultMppTestReportHelperVariantFactory : MppTestReportHelper.MppTestReportHelperVariantFactory { + override fun getInstance(): MppTestReportHelper = DefaultMppTestReportHelper() +} + +internal class DefaultMppTestReportHelper : MppTestReportHelper { + override fun reportFailure( + results: TestResultProcessor, + id: Any, + failure: KotlinTestFailure, + isAssertionFailure: Boolean, + ) { + results.failure( + id, + if (isAssertionFailure) { + TestFailure.fromTestAssertionFailure(failure, failure.expected, failure.actual) + } else { + TestFailure.fromTestFrameworkFailure(failure) + } + ) + } + + @Suppress("DuplicatedCode") // the delegating processor implements different interfaces with the same code + override fun createDelegatingTestReportProcessor(origin: TestResultProcessor, targetName: String) = + object : TestResultProcessor by origin { + override fun started(test: TestDescriptorInternal, event: TestStartEvent) { + val myTest = object : TestDescriptorInternal by test { + override fun getDisplayName(): String = "${test.displayName}[$targetName]" + override fun getClassName(): String? = test.className?.replace('$', '.') + override fun getClassDisplayName(): String? = test.classDisplayName?.replace('$', '.') + } + origin.started(myTest, event) + } + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/JSServiceMessages.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/JSServiceMessages.kt index 50571312f5e..27cdb3f6b7d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/JSServiceMessages.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/JSServiceMessages.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.gradle.internal.LogType import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesClient import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesClientSettings import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutionSpec +import org.jetbrains.kotlin.gradle.plugin.internal.MppTestReportHelper import org.slf4j.Logger internal open class JSServiceMessagesTestExecutionSpec( @@ -24,11 +25,12 @@ internal open class JSServiceMessagesTestExecutionSpec( checkExitCode, clientSettings ) { - override fun createClient(testResultProcessor: TestResultProcessor, log: Logger): TCServiceMessagesClient { + override fun createClient(testResultProcessor: TestResultProcessor, log: Logger, testReporter: MppTestReportHelper): TCServiceMessagesClient { return JSServiceMessagesClient( results = testResultProcessor, settings = clientSettings, - log = log + log = log, + testReporter = testReporter, ) } } @@ -36,8 +38,9 @@ internal open class JSServiceMessagesTestExecutionSpec( internal open class JSServiceMessagesClient( results: TestResultProcessor, settings: TCServiceMessagesClientSettings, - log: Logger -) : TCServiceMessagesClient(results, settings, log) { + log: Logger, + testReporter: MppTestReportHelper, +) : TCServiceMessagesClient(results, settings, log, testReporter) { override fun printNonTestOutput(text: String, type: LogType?) { if (log.isDebugEnabled) { log.debug(text) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/karma/KotlinKarma.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/karma/KotlinKarma.kt index 3496cf2b1e2..37651f1c463 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/karma/KotlinKarma.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/karma/KotlinKarma.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecuti import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutor import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider +import org.jetbrains.kotlin.gradle.plugin.internal.MppTestReportHelper import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation import org.jetbrains.kotlin.gradle.targets.js.* import org.jetbrains.kotlin.gradle.targets.js.dsl.WebpackRulesDsl.Companion.webpackRulesContainer @@ -467,11 +468,12 @@ class KotlinKarma( } } - override fun createClient(testResultProcessor: TestResultProcessor, log: Logger) = + override fun createClient(testResultProcessor: TestResultProcessor, log: Logger, testReporter: MppTestReportHelper) = object : JSServiceMessagesClient( testResultProcessor, clientSettings, - log + log, + testReporter, ) { val baseTestNameSuffix get() = settings.testNameSuffix override var testNameSuffix: String? = baseTestNameSuffix diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/jvm/tasks/KotlinJvmTest.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/jvm/tasks/KotlinJvmTest.kt index c82cd4e8264..827dae21621 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/jvm/tasks/KotlinJvmTest.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/jvm/tasks/KotlinJvmTest.kt @@ -10,9 +10,8 @@ import org.gradle.api.tasks.CacheableTask import org.gradle.api.tasks.Input import org.gradle.api.tasks.Optional import org.gradle.api.tasks.testing.Test -import org.gradle.api.tasks.testing.TestFilter -import org.jetbrains.kotlin.gradle.plugin.KotlinTarget -import org.jetbrains.kotlin.gradle.plugin.KotlinTestRun +import org.jetbrains.kotlin.gradle.plugin.internal.MppTestReportHelper +import org.jetbrains.kotlin.gradle.plugin.variantImplementationFactoryProvider @CacheableTask open class KotlinJvmTest : Test() { @@ -20,28 +19,25 @@ open class KotlinJvmTest : Test() { @Optional var targetName: String? = null + private val testReporter = project.gradle + .variantImplementationFactoryProvider() + .map { it.getInstance() } + override fun createTestExecuter(): TestExecuter = if (targetName != null) Executor( super.createTestExecuter(), - targetName!! + targetName!!, + testReporter.get(), ) else super.createTestExecuter() class Executor( private val delegate: TestExecuter, - private val targetName: String + private val targetName: String, + private val testReporter: MppTestReportHelper, ) : TestExecuter by delegate { override fun execute(testExecutionSpec: JvmTestExecutionSpec, testResultProcessor: TestResultProcessor) { - delegate.execute(testExecutionSpec, object : TestResultProcessor by testResultProcessor { - override fun started(test: TestDescriptorInternal, event: TestStartEvent) { - val myTest = object : TestDescriptorInternal by test { - override fun getDisplayName(): String = "${test.displayName}[$targetName]" - override fun getClassName(): String? = test.className?.replace('$', '.') - override fun getClassDisplayName(): String? = test.classDisplayName?.replace('$', '.') - } - testResultProcessor.started(myTest, event) - } - }) + delegate.execute(testExecutionSpec, testReporter.createDelegatingTestReportProcessor(testResultProcessor, targetName)) } } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinTest.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinTest.kt index 7ce7ce1ed71..a97c28bb369 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinTest.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinTest.kt @@ -15,6 +15,8 @@ import org.gradle.process.internal.ExecHandleFactory import org.jetbrains.kotlin.gradle.internal.testing.KotlinTestRunnerListener import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutor import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider +import org.jetbrains.kotlin.gradle.plugin.internal.MppTestReportHelper +import org.jetbrains.kotlin.gradle.plugin.variantImplementationFactoryProvider import org.jetbrains.kotlin.gradle.utils.injected import javax.inject.Inject @@ -62,11 +64,16 @@ abstract class KotlinTest : AbstractTestTask() { PropertiesProvider(project).ignoreTcsmOverflow } + private val testReporter = project.gradle + .variantImplementationFactoryProvider() + .map { it.getInstance() } + override fun createTestExecuter() = TCServiceMessagesTestExecutor( execHandleFactory, buildOperationExecutor, runListeners, ignoreTcsmOverflow, - ignoreRunFailures + ignoreRunFailures, + testReporter.get(), ) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/testing/KotlinTestFailure.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/testing/KotlinTestFailure.kt index 84443e4012c..6dd07431c80 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/testing/KotlinTestFailure.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/testing/KotlinTestFailure.kt @@ -9,13 +9,16 @@ import org.gradle.internal.serialize.PlaceholderException import java.io.PrintWriter /** - * Class to be shown in default Gradle tests console reporter. + * Class to be shown in the default Gradle tests console reporter. * * Example console output: * ``` * sample.SampleTests.testMe FAILED * AssertionError at mpplib2/src/commonTest/kotlin/sample/SampleTests.kt:9 * ``` + * + * Inherits [PlaceholderException] in order to override a displayed exception-class name, + * e.g. [kotlin.AssertionError] instead of [KotlinTestFailure] */ class KotlinTestFailure( className: String, diff --git a/libraries/tools/kotlin-gradle-plugin/src/gradle70/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt b/libraries/tools/kotlin-gradle-plugin/src/gradle70/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt index a0fde6717fc..5394b968627 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/gradle70/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/gradle70/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt @@ -145,4 +145,6 @@ private fun Project.registerVariantImplementations() { IdeaSyncDetectorG70.IdeaSyncDetectorVariantFactoryG70() factories[ConfigurationTimePropertiesAccessor.ConfigurationTimePropertiesAccessorVariantFactory::class] = ConfigurationTimePropertiesAccessorG70.ConfigurationTimePropertiesAccessorVariantFactoryG70() + factories[MppTestReportHelper.MppTestReportHelperVariantFactory::class] = + MppTestReportHelperG70.MppTestReportHelperVariantFactoryG70() } diff --git a/libraries/tools/kotlin-gradle-plugin/src/gradle70/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/MppTestReportHelperG70.kt b/libraries/tools/kotlin-gradle-plugin/src/gradle70/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/MppTestReportHelperG70.kt new file mode 100644 index 00000000000..b8dab031c74 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/gradle70/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/MppTestReportHelperG70.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2022 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.plugin.internal + +import org.gradle.api.internal.tasks.testing.TestDescriptorInternal +import org.gradle.api.internal.tasks.testing.TestResultProcessor +import org.gradle.api.internal.tasks.testing.TestStartEvent +import org.jetbrains.kotlin.gradle.testing.KotlinTestFailure + +internal class MppTestReportHelperG70 : MppTestReportHelper { + internal class MppTestReportHelperVariantFactoryG70 : + MppTestReportHelper.MppTestReportHelperVariantFactory { + override fun getInstance(): MppTestReportHelper = MppTestReportHelperG70() + } + + override fun reportFailure( + results: TestResultProcessor, + id: Any, + failure: KotlinTestFailure, + isAssertionFailure: Boolean, + ) { + results.failure( + id, + failure, + ) + } + + @Suppress("DuplicatedCode") // the delegating processor implements different interfaces with the same code + override fun createDelegatingTestReportProcessor(origin: TestResultProcessor, targetName: String) = + object : TestResultProcessor by origin { + override fun started(test: TestDescriptorInternal, event: TestStartEvent) { + val myTest = object : TestDescriptorInternal by test { + override fun getDisplayName(): String = "${test.displayName}[$targetName]" + override fun getClassName(): String? = test.className?.replace('$', '.') + override fun getClassDisplayName(): String? = test.classDisplayName?.replace('$', '.') + } + origin.started(myTest, event) + } + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/gradle71/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt b/libraries/tools/kotlin-gradle-plugin/src/gradle71/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt index 9c9a9ad43e7..01f6e4035a7 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/gradle71/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/gradle71/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt @@ -12,9 +12,8 @@ import org.gradle.api.Project import org.gradle.api.file.SourceDirectorySet import org.gradle.api.model.ObjectFactory import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry -import org.jetbrains.kotlin.gradle.plugin.internal.ConfigurationTimePropertiesAccessor +import org.jetbrains.kotlin.gradle.plugin.internal.* import org.jetbrains.kotlin.gradle.plugin.internal.ConfigurationTimePropertiesAccessorG71 -import org.jetbrains.kotlin.gradle.plugin.internal.IdeaSyncDetector import org.jetbrains.kotlin.gradle.plugin.internal.IdeaSyncDetectorG71 import javax.inject.Inject @@ -147,4 +146,6 @@ private fun Project.registerVariantImplementations() { IdeaSyncDetectorG71.IdeaSyncDetectorVariantFactoryG71() factories[ConfigurationTimePropertiesAccessor.ConfigurationTimePropertiesAccessorVariantFactory::class] = ConfigurationTimePropertiesAccessorG71.ConfigurationTimePropertiesAccessorVariantFactoryG71() + factories[MppTestReportHelper.MppTestReportHelperVariantFactory::class] = + MppTestReportHelperG71.MppTestReportHelperVariantFactoryG71() } diff --git a/libraries/tools/kotlin-gradle-plugin/src/gradle71/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/MppTestReportHelperG71.kt b/libraries/tools/kotlin-gradle-plugin/src/gradle71/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/MppTestReportHelperG71.kt new file mode 100644 index 00000000000..1f593a88d76 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/gradle71/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/MppTestReportHelperG71.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2022 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.plugin.internal + +import org.gradle.api.internal.tasks.testing.TestDescriptorInternal +import org.gradle.api.internal.tasks.testing.TestResultProcessor +import org.gradle.api.internal.tasks.testing.TestStartEvent +import org.jetbrains.kotlin.gradle.testing.KotlinTestFailure + +internal class MppTestReportHelperG71 : MppTestReportHelper { + internal class MppTestReportHelperVariantFactoryG71 : + MppTestReportHelper.MppTestReportHelperVariantFactory { + override fun getInstance(): MppTestReportHelper = MppTestReportHelperG71() + } + + override fun reportFailure( + results: TestResultProcessor, + id: Any, + failure: KotlinTestFailure, + isAssertionFailure: Boolean, + ) { + results.failure( + id, + failure, + ) + } + + @Suppress("DuplicatedCode") // the delegating processor implements different interfaces with the same code + override fun createDelegatingTestReportProcessor(origin: TestResultProcessor, targetName: String) = + object : TestResultProcessor by origin { + override fun started(test: TestDescriptorInternal, event: TestStartEvent) { + val myTest = object : TestDescriptorInternal by test { + override fun getDisplayName(): String = "${test.displayName}[$targetName]" + override fun getClassName(): String? = test.className?.replace('$', '.') + override fun getClassDisplayName(): String? = test.classDisplayName?.replace('$', '.') + } + origin.started(myTest, event) + } + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/gradle75/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt b/libraries/tools/kotlin-gradle-plugin/src/gradle75/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt index 946ad93cbf9..cdac8150919 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/gradle75/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/gradle75/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt @@ -12,6 +12,8 @@ import org.gradle.api.Project import org.gradle.api.file.SourceDirectorySet import org.gradle.api.model.ObjectFactory import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry +import org.jetbrains.kotlin.gradle.plugin.internal.MppTestReportHelper +import org.jetbrains.kotlin.gradle.plugin.internal.MppTestReportHelperG75 import javax.inject.Inject private const val PLUGIN_VARIANT_NAME = "gradle75" @@ -137,7 +139,8 @@ open class KotlinPlatformCommonPlugin : KotlinPlatformPluginBase("common") { } } -@Suppress("UnusedReceiverParameter") private fun Project.registerVariantImplementations() { - + val factories = VariantImplementationFactories.get(gradle) + factories[MppTestReportHelper.MppTestReportHelperVariantFactory::class] = + MppTestReportHelperG75.MppTestReportHelperVariantFactoryG75() } diff --git a/libraries/tools/kotlin-gradle-plugin/src/gradle75/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/MppTestReportHelperG75.kt b/libraries/tools/kotlin-gradle-plugin/src/gradle75/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/MppTestReportHelperG75.kt new file mode 100644 index 00000000000..80bacb99f4c --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/gradle75/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/MppTestReportHelperG75.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2022 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.plugin.internal + +import org.gradle.api.internal.tasks.testing.TestDescriptorInternal +import org.gradle.api.internal.tasks.testing.TestResultProcessor +import org.gradle.api.internal.tasks.testing.TestStartEvent +import org.jetbrains.kotlin.gradle.testing.KotlinTestFailure + +internal class MppTestReportHelperG75 : MppTestReportHelper { + internal class MppTestReportHelperVariantFactoryG75 : + MppTestReportHelper.MppTestReportHelperVariantFactory { + override fun getInstance(): MppTestReportHelper = MppTestReportHelperG75() + } + + override fun reportFailure( + results: TestResultProcessor, + id: Any, + failure: KotlinTestFailure, + isAssertionFailure: Boolean, + ) { + results.failure( + id, + failure, + ) + } + + @Suppress("DuplicatedCode") // the delegating processor implements different interfaces with the same code + override fun createDelegatingTestReportProcessor(origin: TestResultProcessor, targetName: String) = + object : TestResultProcessor by origin { + override fun started(test: TestDescriptorInternal, event: TestStartEvent) { + val myTest = object : TestDescriptorInternal by test { + override fun getDisplayName(): String = "${test.displayName}[$targetName]" + override fun getClassName(): String? = test.className?.replace('$', '.') + override fun getClassDisplayName(): String? = test.classDisplayName?.replace('$', '.') + } + origin.started(myTest, event) + } + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt index 72bcce16520..9618f910626 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt @@ -151,4 +151,6 @@ private fun Project.registerVariantImplementations() { IdeaSyncDetectorG6.IdeaSyncDetectorVariantFactoryG6() factories[ConfigurationTimePropertiesAccessor.ConfigurationTimePropertiesAccessorVariantFactory::class] = ConfigurationTimePropertiesAccessorG6.ConfigurationTimePropertiesAccessorVariantFactoryG6() + factories[MppTestReportHelper.MppTestReportHelperVariantFactory::class] = + MppTestReportHelperG6.MppTestReportHelperVariantFactoryG6() } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/MppTestReportHelperG6.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/MppTestReportHelperG6.kt new file mode 100644 index 00000000000..71b57b21579 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/MppTestReportHelperG6.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2022 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.plugin.internal + +import org.gradle.api.internal.tasks.testing.TestDescriptorInternal +import org.gradle.api.internal.tasks.testing.TestResultProcessor +import org.gradle.api.internal.tasks.testing.TestStartEvent +import org.jetbrains.kotlin.gradle.testing.KotlinTestFailure + +internal class MppTestReportHelperG6 : MppTestReportHelper { + internal class MppTestReportHelperVariantFactoryG6 : + MppTestReportHelper.MppTestReportHelperVariantFactory { + override fun getInstance(): MppTestReportHelper = MppTestReportHelperG6() + } + + override fun reportFailure( + results: TestResultProcessor, + id: Any, + failure: KotlinTestFailure, + isAssertionFailure: Boolean, + ) { + results.failure( + id, + failure, + ) + } + + @Suppress("DuplicatedCode") // the delegating processor implements different interfaces with the same code + override fun createDelegatingTestReportProcessor(origin: TestResultProcessor, targetName: String) = + object : TestResultProcessor by origin { + override fun started(test: TestDescriptorInternal, event: TestStartEvent) { + val myTest = object : TestDescriptorInternal by test { + override fun getDisplayName(): String = "${test.displayName}[$targetName]" + override fun getClassName(): String? = test.className?.replace('$', '.') + override fun getClassDisplayName(): String? = test.classDisplayName?.replace('$', '.') + } + origin.started(myTest, event) + } + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/internal/testing/tcsmc/TCServiceMessagesClientTest.kt b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/internal/testing/tcsmc/TCServiceMessagesClientTest.kt index 2461407257a..13f31d87429 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/internal/testing/tcsmc/TCServiceMessagesClientTest.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/internal/testing/tcsmc/TCServiceMessagesClientTest.kt @@ -1,10 +1,13 @@ package org.jetbrains.kotlin.gradle.internal.testing.tcsmc import jetbrains.buildServer.messages.serviceMessages.ServiceMessage +import org.gradle.api.internal.tasks.testing.TestResultProcessor import org.gradle.internal.operations.OperationIdentifier import org.jetbrains.kotlin.gradle.internal.testing.RecordingTestResultProcessor import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesClient import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesClientSettings +import org.jetbrains.kotlin.gradle.plugin.internal.MppTestReportHelper +import org.jetbrains.kotlin.gradle.testing.KotlinTestFailure import org.jetbrains.kotlin.test.util.trimTrailingWhitespaces import org.slf4j.LoggerFactory import kotlin.test.assertEquals @@ -38,7 +41,15 @@ open class TCServiceMessagesClientTest { rootNodeName, treatFailedTestOutputAsStacktrace = treatFailedTestOutputAsStacktrace ), - LoggerFactory.getLogger("test") + LoggerFactory.getLogger("test"), + object : MppTestReportHelper { + override fun reportFailure(results: TestResultProcessor, id: Any, failure: KotlinTestFailure, isAssertionFailure: Boolean) { + results.failure(id, failure) + } + + override fun createDelegatingTestReportProcessor(origin: TestResultProcessor, targetName: String): TestResultProcessor = + origin + } ) }