Gradle, js, browser: best effort for parsing karma suite names

#KT-31011
This commit is contained in:
Sergey Rostov
2019-05-15 10:46:05 +03:00
parent 236dfa98b6
commit 7e4eaa8210
5 changed files with 54 additions and 13 deletions
@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.gradle.logging.kotlinDebug
import org.jetbrains.kotlin.gradle.testing.KotlinTestFailure import org.jetbrains.kotlin.gradle.testing.KotlinTestFailure
import org.slf4j.Logger import org.slf4j.Logger
import java.text.ParseException import java.text.ParseException
import java.lang.System.currentTimeMillis as currentTimeMillis1
data class TCServiceMessagesClientSettings( data class TCServiceMessagesClientSettings(
val rootNodeName: String, val rootNodeName: String,
@@ -28,7 +27,7 @@ data class TCServiceMessagesClientSettings(
val ignoreOutOfRootNodes: Boolean = false val ignoreOutOfRootNodes: Boolean = false
) )
internal class TCServiceMessagesClient( internal open class TCServiceMessagesClient(
private val results: TestResultProcessor, private val results: TestResultProcessor,
val settings: TCServiceMessagesClientSettings, val settings: TCServiceMessagesClientSettings,
val log: Logger val log: Logger
@@ -51,7 +50,7 @@ internal class TCServiceMessagesClient(
log.kotlinDebug { "TCSM: $message" } log.kotlinDebug { "TCSM: $message" }
when (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 TestStarted -> beginTest(message.ts, message.testName)
is TestStdOut -> requireLeafTest().output(StdOut, message.stdOut) is TestStdOut -> requireLeafTest().output(StdOut, message.stdOut)
is TestStdErr -> requireLeafTest().output(StdErr, message.stdErr) is TestStdErr -> requireLeafTest().output(StdErr, message.stdErr)
@@ -66,11 +65,13 @@ internal class TCServiceMessagesClient(
endTest(message.ts, message.testName) endTest(message.ts, message.testName)
} }
} }
is TestSuiteFinished -> close(message.ts, message.suiteName) is TestSuiteFinished -> close(message.ts, getSuiteName(message))
else -> Unit else -> Unit
} }
} }
protected open fun getSuiteName(message: BaseTestSuiteMessage) = message.suiteName
override fun regularText(text: String) { override fun regularText(text: String) {
log.kotlinDebug { "TCSM stdout captured: $text" } log.kotlinDebug { "TCSM stdout captured: $text" }
val actualText = text + "\n" 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) { private fun beginTest(ts: Long, testName: String, isIgnored: Boolean = false) {
val parent = requireLeafGroup() val parent = requireLeafGroup()
parent.requireReportingNode() parent.requireReportingNode()
@@ -93,8 +97,8 @@ internal class TCServiceMessagesClient(
} }
val parsedName = ParsedTestName(finalTestName, parent.localId) val parsedName = ParsedTestName(finalTestName, parent.localId)
val fullTestName = if (settings.testNameSuffix == null) parsedName.methodName val fullTestName = if (testNameSuffix == null) parsedName.methodName
else "${parsedName.methodName}[${settings.testNameSuffix}]" else "${parsedName.methodName}[$testNameSuffix]"
open( open(
ts, TestNode( ts, TestNode(
@@ -8,17 +8,21 @@ import org.gradle.internal.operations.BuildOperationExecutor
import org.gradle.process.ProcessForkOptions import org.gradle.process.ProcessForkOptions
import org.gradle.process.internal.ExecHandle import org.gradle.process.internal.ExecHandle
import org.gradle.process.internal.ExecHandleFactory import org.gradle.process.internal.ExecHandleFactory
import org.slf4j.Logger
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.io.PipedInputStream import java.io.PipedInputStream
import java.io.PipedOutputStream import java.io.PipedOutputStream
import kotlin.concurrent.thread import kotlin.concurrent.thread
data class TCServiceMessagesTestExecutionSpec( open class TCServiceMessagesTestExecutionSpec(
val forkOptions: ProcessForkOptions, val forkOptions: ProcessForkOptions,
val args: List<String>, val args: List<String>,
val checkExitCode: Boolean, val checkExitCode: Boolean,
val clientSettings: TCServiceMessagesClientSettings 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") private val log = LoggerFactory.getLogger("org.jetbrains.kotlin.gradle.tasks.testing")
@@ -37,7 +41,7 @@ class TCServiceMessagesTestExecutor(
outputReaderThread = thread(name = "${spec.forkOptions} output reader") { outputReaderThread = thread(name = "${spec.forkOptions} output reader") {
try { try {
val client = TCServiceMessagesClient(testResultProcessor, spec.clientSettings, log) val client = spec.createClient(testResultProcessor, log)
client.root(rootOperation) { client.root(rootOperation) {
stdInPipe.reader().useLines { lines -> stdInPipe.reader().useLines { lines ->
@@ -69,7 +69,7 @@ abstract class KotlinJsSubTarget(
compileTask.outputFile.exists() compileTask.outputFile.exists()
} }
testJs.targetName = disambiguationClassifier testJs.targetName = target.disambiguationClassifier + "," + disambiguationClassifier
testJs.nodeModulesToLoad.add(compileTask.outputFile.nameWithoutExtension) testJs.nodeModulesToLoad.add(compileTask.outputFile.nameWithoutExtension)
testJs.configureConventions() testJs.configureConventions()
@@ -6,8 +6,11 @@
package org.jetbrains.kotlin.gradle.targets.js.testing.karma package org.jetbrains.kotlin.gradle.targets.js.testing.karma
import com.google.gson.GsonBuilder import com.google.gson.GsonBuilder
import jetbrains.buildServer.messages.serviceMessages.BaseTestSuiteMessage
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.internal.tasks.testing.TestResultProcessor
import org.gradle.process.ProcessForkOptions 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.TCServiceMessagesClientSettings
import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutionSpec import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutionSpec
import org.jetbrains.kotlin.gradle.targets.js.appendConfigsFromDir 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.testing.karma.KarmaConfig.CoverageReporter.Reporter
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfigWriter import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfigWriter
import org.jetbrains.kotlin.gradle.testing.internal.reportsDir import org.jetbrains.kotlin.gradle.testing.internal.reportsDir
import org.slf4j.Logger
import java.io.File import java.io.File
class KotlinKarma(val project: Project) : KotlinJsTestFramework { class KotlinKarma(val project: Project) : KotlinJsTestFramework {
@@ -209,12 +213,42 @@ class KotlinKarma(val project: Project) : KotlinJsTestFramework {
} + } +
listOf("start", karmaConfJs.absolutePath) listOf("start", karmaConfJs.absolutePath)
return TCServiceMessagesTestExecutionSpec( return object : TCServiceMessagesTestExecutionSpec(
forkOptions, forkOptions,
args, args,
false, false,
clientSettings 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() { private fun Appendable.appendFromConfigDir() {
@@ -9,7 +9,6 @@ import org.gradle.api.Project
import org.gradle.process.ProcessForkOptions import org.gradle.process.ProcessForkOptions
import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesClientSettings import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesClientSettings
import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutionSpec 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.internal.parseNodeJsStackTraceAsJvm
import org.jetbrains.kotlin.gradle.targets.js.nodejs.nodeJs import org.jetbrains.kotlin.gradle.targets.js.nodejs.nodeJs
import org.jetbrains.kotlin.gradle.targets.js.npm.KotlinGradleNpmPackage import org.jetbrains.kotlin.gradle.targets.js.npm.KotlinGradleNpmPackage