From 7e4eaa8210e18d5bfa3737e0ab031dcb62369c90 Mon Sep 17 00:00:00 2001 From: Sergey Rostov Date: Wed, 15 May 2019 10:46:05 +0300 Subject: [PATCH] Gradle, js, browser: best effort for parsing karma suite names #KT-31011 --- .../testing/TCServiceMessagesClient.kt | 16 +++++--- .../testing/TCServiceMessagesTestExecutor.kt | 10 +++-- .../js/subtargets/KotlinJsSubTarget.kt | 2 +- .../targets/js/testing/karma/KotlinKarma.kt | 38 ++++++++++++++++++- .../targets/js/testing/mocha/KotlinMocha.kt | 1 - 5 files changed, 54 insertions(+), 13 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesClient.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesClient.kt index 02550b7e504..de05ccc95b8 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesClient.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesClient.kt @@ -17,7 +17,6 @@ import org.jetbrains.kotlin.gradle.logging.kotlinDebug import org.jetbrains.kotlin.gradle.testing.KotlinTestFailure import org.slf4j.Logger import java.text.ParseException -import java.lang.System.currentTimeMillis as currentTimeMillis1 data class TCServiceMessagesClientSettings( val rootNodeName: String, @@ -28,7 +27,7 @@ data class TCServiceMessagesClientSettings( val ignoreOutOfRootNodes: Boolean = false ) -internal class TCServiceMessagesClient( +internal open class TCServiceMessagesClient( private val results: TestResultProcessor, val settings: TCServiceMessagesClientSettings, val log: Logger @@ -51,7 +50,7 @@ internal class TCServiceMessagesClient( log.kotlinDebug { "TCSM: $message" } when (message) { - is TestSuiteStarted -> open(message.ts, SuiteNode(requireLeafGroup(), message.suiteName)) + is TestSuiteStarted -> open(message.ts, SuiteNode(requireLeafGroup(), getSuiteName(message))) is TestStarted -> beginTest(message.ts, message.testName) is TestStdOut -> requireLeafTest().output(StdOut, message.stdOut) is TestStdErr -> requireLeafTest().output(StdErr, message.stdErr) @@ -66,11 +65,13 @@ internal class TCServiceMessagesClient( endTest(message.ts, message.testName) } } - is TestSuiteFinished -> close(message.ts, message.suiteName) + is TestSuiteFinished -> close(message.ts, getSuiteName(message)) else -> Unit } } + protected open fun getSuiteName(message: BaseTestSuiteMessage) = message.suiteName + override fun regularText(text: String) { log.kotlinDebug { "TCSM stdout captured: $text" } val actualText = text + "\n" @@ -83,6 +84,9 @@ internal class TCServiceMessagesClient( } } + protected open val testNameSuffix: String? + get() = settings.testNameSuffix + private fun beginTest(ts: Long, testName: String, isIgnored: Boolean = false) { val parent = requireLeafGroup() parent.requireReportingNode() @@ -93,8 +97,8 @@ internal class TCServiceMessagesClient( } val parsedName = ParsedTestName(finalTestName, parent.localId) - val fullTestName = if (settings.testNameSuffix == null) parsedName.methodName - else "${parsedName.methodName}[${settings.testNameSuffix}]" + val fullTestName = if (testNameSuffix == null) parsedName.methodName + else "${parsedName.methodName}[$testNameSuffix]" open( ts, TestNode( diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesTestExecutor.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesTestExecutor.kt index 552d273d115..67affb4dc38 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesTestExecutor.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/testing/TCServiceMessagesTestExecutor.kt @@ -8,17 +8,21 @@ import org.gradle.internal.operations.BuildOperationExecutor import org.gradle.process.ProcessForkOptions import org.gradle.process.internal.ExecHandle import org.gradle.process.internal.ExecHandleFactory +import org.slf4j.Logger import org.slf4j.LoggerFactory import java.io.PipedInputStream import java.io.PipedOutputStream import kotlin.concurrent.thread -data class TCServiceMessagesTestExecutionSpec( +open class TCServiceMessagesTestExecutionSpec( val forkOptions: ProcessForkOptions, val args: List, val checkExitCode: Boolean, val clientSettings: TCServiceMessagesClientSettings -) : TestExecutionSpec +) : TestExecutionSpec { + internal open fun createClient(testResultProcessor: TestResultProcessor, log: Logger): TCServiceMessagesClient = + TCServiceMessagesClient(testResultProcessor, clientSettings, log) +} private val log = LoggerFactory.getLogger("org.jetbrains.kotlin.gradle.tasks.testing") @@ -37,7 +41,7 @@ class TCServiceMessagesTestExecutor( outputReaderThread = thread(name = "${spec.forkOptions} output reader") { try { - val client = TCServiceMessagesClient(testResultProcessor, spec.clientSettings, log) + val client = spec.createClient(testResultProcessor, log) client.root(rootOperation) { stdInPipe.reader().useLines { lines -> diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/KotlinJsSubTarget.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/KotlinJsSubTarget.kt index 6308d904036..7ed57b59f90 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/KotlinJsSubTarget.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/KotlinJsSubTarget.kt @@ -69,7 +69,7 @@ abstract class KotlinJsSubTarget( compileTask.outputFile.exists() } - testJs.targetName = disambiguationClassifier + testJs.targetName = target.disambiguationClassifier + "," + disambiguationClassifier testJs.nodeModulesToLoad.add(compileTask.outputFile.nameWithoutExtension) testJs.configureConventions() diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/karma/KotlinKarma.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/karma/KotlinKarma.kt index e4d301f8699..20290383483 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/karma/KotlinKarma.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/karma/KotlinKarma.kt @@ -6,8 +6,11 @@ package org.jetbrains.kotlin.gradle.targets.js.testing.karma import com.google.gson.GsonBuilder +import jetbrains.buildServer.messages.serviceMessages.BaseTestSuiteMessage import org.gradle.api.Project +import org.gradle.api.internal.tasks.testing.TestResultProcessor import org.gradle.process.ProcessForkOptions +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.targets.js.appendConfigsFromDir @@ -21,6 +24,7 @@ import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTestFramework import org.jetbrains.kotlin.gradle.targets.js.testing.karma.KarmaConfig.CoverageReporter.Reporter import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfigWriter import org.jetbrains.kotlin.gradle.testing.internal.reportsDir +import org.slf4j.Logger import java.io.File class KotlinKarma(val project: Project) : KotlinJsTestFramework { @@ -209,12 +213,42 @@ class KotlinKarma(val project: Project) : KotlinJsTestFramework { } + listOf("start", karmaConfJs.absolutePath) - return TCServiceMessagesTestExecutionSpec( + return object : TCServiceMessagesTestExecutionSpec( forkOptions, args, false, clientSettings - ) + ) { + override fun createClient(testResultProcessor: TestResultProcessor, log: Logger) = + object : TCServiceMessagesClient(testResultProcessor, clientSettings, log) { + val baseTestNameSuffix get() = settings.testNameSuffix + override var testNameSuffix: String? = baseTestNameSuffix + + override fun getSuiteName(message: BaseTestSuiteMessage): String { + val src = message.suiteName.trim() + // example: "sample.a DeepPackageTest Inner.HeadlessChrome 74.0.3729 (Mac OS X 10.14.4)" + // should be reported as "sample.a.DeepPackageTest.Inner[js,browser,HeadlessChrome74.0.3729,MacOSX10.14.4]" + + // lets parse it from the end: + val os = src.substringAfterLast("(") // Mac OS X 10.14.4) + .removeSuffix(")") // Mac OS X 10.14.4 + .replace(" ", "") // MacOSX10.14.4 + + val withoutOs = src.substringBeforeLast(" (") // sample.a DeepPackageTest Inner.HeadlessChrome 74.0.3729 + + val rawSuiteNameOnly = withoutOs + .substringBeforeLast(" ") // sample.a DeepPackageTest Inner.HeadlessChrome + .substringBeforeLast(".") // sample.a DeepPackageTest Inner + + val browser = withoutOs.substring(rawSuiteNameOnly.length + 1) // HeadlessChrome 74.0.3729 + .replace(" ", "") // HeadlessChrome74.0.3729 + + testNameSuffix = "$baseTestNameSuffix,$browser,$os" + + return rawSuiteNameOnly.replace(" ", ".") // sample.a.DeepPackageTest.Inner + } + } + } } private fun Appendable.appendFromConfigDir() { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/mocha/KotlinMocha.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/mocha/KotlinMocha.kt index fbd735ea49f..c0d92bdff4f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/mocha/KotlinMocha.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/mocha/KotlinMocha.kt @@ -9,7 +9,6 @@ import org.gradle.api.Project import org.gradle.process.ProcessForkOptions import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesClientSettings import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutionSpec -import org.jetbrains.kotlin.gradle.plugin.HasKotlinDependencies import org.jetbrains.kotlin.gradle.targets.js.internal.parseNodeJsStackTraceAsJvm import org.jetbrains.kotlin.gradle.targets.js.nodejs.nodeJs import org.jetbrains.kotlin.gradle.targets.js.npm.KotlinGradleNpmPackage