[WASM] Support wasm backend DSL for d8
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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 kotlin.test
|
||||
|
||||
@Suppress("EnumEntryName")
|
||||
internal enum class IgnoredTestSuitesReporting {
|
||||
skip, reportAsIgnoredTest, reportAllInnerTestsAsIgnored
|
||||
}
|
||||
|
||||
internal class FrameworkTestArguments(
|
||||
val includedQualifiers: List<String>,
|
||||
val includedClassMethods: List<Pair<String, String>>,
|
||||
val excludedQualifiers: List<String>,
|
||||
val excludedClassMethods: List<Pair<String, String>>,
|
||||
val ignoredTestSuites: IgnoredTestSuitesReporting,
|
||||
val dryRun: Boolean
|
||||
) {
|
||||
companion object {
|
||||
fun parse(args: List<String>): FrameworkTestArguments {
|
||||
var isInclude = false
|
||||
var isExclude = false
|
||||
|
||||
val includesClassMethods = mutableListOf<Pair<String, String>>()
|
||||
val includesQualifiers = mutableListOf<String>()
|
||||
val excludesClassMethods = mutableListOf<Pair<String, String>>()
|
||||
val excludesQualifiers = mutableListOf<String>()
|
||||
|
||||
fun addToIncludeOrExcludeList(argument: String) {
|
||||
if (argument.isEmpty()) return
|
||||
if (argument[0].let { it != it.lowercaseChar() }){
|
||||
val dotIndex = argument.indexOf('.')
|
||||
val listToAdd = if (isInclude) includesClassMethods else excludesClassMethods
|
||||
if (dotIndex == -1) {
|
||||
listToAdd.add(argument to "*")
|
||||
} else {
|
||||
if (dotIndex < 1 || dotIndex >= argument.lastIndex) return
|
||||
val className = argument.substring(0, dotIndex)
|
||||
val methodName = argument.substring(dotIndex + 1)
|
||||
listToAdd.add(className to methodName)
|
||||
}
|
||||
} else {
|
||||
(if (isInclude) includesQualifiers else excludesQualifiers).add(argument)
|
||||
}
|
||||
}
|
||||
|
||||
var ignoredTestSuites: IgnoredTestSuitesReporting = IgnoredTestSuitesReporting.reportAllInnerTestsAsIgnored
|
||||
var isIgnoredTestSuites = false
|
||||
var dryRun = false
|
||||
|
||||
for (arg in args) {
|
||||
if (isInclude || isExclude) {
|
||||
for (splitArg in arg.split(',')) {
|
||||
addToIncludeOrExcludeList(splitArg)
|
||||
}
|
||||
isInclude = false
|
||||
isExclude = false
|
||||
continue
|
||||
}
|
||||
|
||||
if (isIgnoredTestSuites) {
|
||||
val value = IgnoredTestSuitesReporting.values().firstOrNull { it.name == arg }
|
||||
if (value != null) {
|
||||
ignoredTestSuites = value
|
||||
}
|
||||
isIgnoredTestSuites = false
|
||||
continue
|
||||
}
|
||||
|
||||
when (arg) {
|
||||
"--include" -> isInclude = true
|
||||
"--exclude" -> isExclude = true
|
||||
"--ignoredTestSuites" -> isIgnoredTestSuites = true
|
||||
"--dryRun" -> dryRun = true
|
||||
}
|
||||
}
|
||||
|
||||
if (includesClassMethods.isEmpty() && includesQualifiers.isEmpty()) {
|
||||
includesQualifiers.add("*")
|
||||
}
|
||||
|
||||
return FrameworkTestArguments(
|
||||
includedQualifiers = includesQualifiers,
|
||||
includedClassMethods = includesClassMethods,
|
||||
excludedQualifiers = excludesQualifiers,
|
||||
excludedClassMethods = excludesClassMethods,
|
||||
ignoredTestSuites = ignoredTestSuites,
|
||||
dryRun = dryRun
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,12 @@
|
||||
package kotlin.test
|
||||
|
||||
import kotlin.test.FrameworkAdapter
|
||||
import kotlin.math.abs
|
||||
|
||||
@JsFun("() => (typeof arguments !== 'undefined' && typeof arguments.join !== 'undefined') ? arguments.join(' ') : '' ")
|
||||
private external fun d8Arguments(): String
|
||||
@JsFun("() => (typeof process != 'undefined' && typeof process.argv != 'undefined') ? process.argv.slice(2).join(' ') : ''")
|
||||
private external fun nodeArguments(): String
|
||||
|
||||
internal class TeamcityAdapter : FrameworkAdapter {
|
||||
private enum class MessageType(val type: String) {
|
||||
@@ -30,41 +36,153 @@ internal class TeamcityAdapter : FrameworkAdapter {
|
||||
?.replace("]", "|]")
|
||||
?: ""
|
||||
|
||||
private val flowId: String = "flowId='wasmTcAdapter${abs(hashCode())}'"
|
||||
|
||||
private fun MessageType.report(name: String) {
|
||||
println("##teamcity[$type name='${name.tcEscape()}']")
|
||||
println("##teamcity[$type name='${name.tcEscape()}' $flowId]")
|
||||
}
|
||||
|
||||
private fun MessageType.report(name: String, e: Throwable) {
|
||||
if (this == MessageType.Failed) {
|
||||
println("##teamcity[$type name='${name.tcEscape()}' message='${e.message.tcEscape()}' details='${e.stackTraceToString().tcEscape()}']")
|
||||
println("##teamcity[$type name='${name.tcEscape()}' message='${e.message.tcEscape()}' details='${e.stackTraceToString().tcEscape()}' $flowId]")
|
||||
} else {
|
||||
println("##teamcity[$type name='${name.tcEscape()}' text='${e.message.tcEscape()}' errorDetails='${e.stackTraceToString().tcEscape()}' status='ERROR']")
|
||||
println("##teamcity[$type name='${name.tcEscape()}' text='${e.message.tcEscape()}' errorDetails='${e.stackTraceToString().tcEscape()}' status='ERROR' $flowId]")
|
||||
}
|
||||
}
|
||||
|
||||
private val testArguments: FrameworkTestArguments by lazy {
|
||||
val arguments = d8Arguments().takeIf { it.isNotEmpty() } ?: nodeArguments()
|
||||
FrameworkTestArguments.parse(arguments.split(' '))
|
||||
}
|
||||
|
||||
private fun runSuite(name: String, suiteFn: () -> Unit) {
|
||||
MessageType.SuiteStarted.report(name)
|
||||
try {
|
||||
suiteFn()
|
||||
MessageType.SuiteFinished.report(name)
|
||||
} catch (e: Throwable) {
|
||||
MessageType.SuiteFinished.report(name, e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun runIgnoredSuite(name: String, suiteFn: () -> Unit) {
|
||||
MessageType.SuiteStarted.report(name)
|
||||
suiteFn()
|
||||
MessageType.SuiteFinished.report(name)
|
||||
}
|
||||
|
||||
private var isUnderIgnoredSuit: Boolean = false
|
||||
private var qualifiedName: String = ""
|
||||
private var className: String = ""
|
||||
private inline fun enterIfIncluded(name: String, isSuit: Boolean, body: () -> Unit) {
|
||||
if (name.isEmpty()) {
|
||||
body()
|
||||
return
|
||||
}
|
||||
|
||||
val oldQualifiedName = qualifiedName
|
||||
val oldClassName = className
|
||||
try {
|
||||
qualifiedName = if (oldQualifiedName.isEmpty()) name else "$oldQualifiedName.$name"
|
||||
className = name
|
||||
if (isSuit) {
|
||||
body()
|
||||
} else {
|
||||
val runTest = testArguments.run {
|
||||
val included =
|
||||
includedClassMethods.any { it.first == oldClassName && name.matched(it.second) } ||
|
||||
includedQualifiers.any { oldQualifiedName.matched(it) || qualifiedName.matched(it) }
|
||||
included &&
|
||||
excludedClassMethods.none { it.first == oldClassName && name.matched(it.second) } &&
|
||||
excludedQualifiers.none { oldQualifiedName.matched(it) || qualifiedName.matched(it) }
|
||||
}
|
||||
if (runTest) {
|
||||
body()
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
qualifiedName = oldQualifiedName
|
||||
className = oldClassName
|
||||
}
|
||||
}
|
||||
|
||||
override fun suite(name: String, ignored: Boolean, suiteFn: () -> Unit) {
|
||||
MessageType.SuiteStarted.report(name)
|
||||
if (isUnderIgnoredSuit) {
|
||||
runIgnoredSuite(name, suiteFn)
|
||||
return
|
||||
}
|
||||
|
||||
if (!ignored) {
|
||||
try {
|
||||
suiteFn()
|
||||
MessageType.SuiteFinished.report(name)
|
||||
} catch (e: Throwable) {
|
||||
MessageType.SuiteFinished.report(name, e)
|
||||
enterIfIncluded(name, true) {
|
||||
runSuite(name, suiteFn)
|
||||
}
|
||||
} else {
|
||||
when (testArguments.ignoredTestSuites) {
|
||||
IgnoredTestSuitesReporting.reportAsIgnoredTest -> {
|
||||
MessageType.Ignored.report(name)
|
||||
}
|
||||
IgnoredTestSuitesReporting.reportAllInnerTestsAsIgnored -> {
|
||||
var oldIsUnderIgnoredSuit = isUnderIgnoredSuit
|
||||
isUnderIgnoredSuit = true
|
||||
try {
|
||||
runIgnoredSuite(name, suiteFn)
|
||||
} finally {
|
||||
isUnderIgnoredSuit = oldIsUnderIgnoredSuit
|
||||
}
|
||||
}
|
||||
IgnoredTestSuitesReporting.skip -> { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun test(name: String, ignored: Boolean, testFn: () -> Any?) {
|
||||
if (isUnderIgnoredSuit) {
|
||||
MessageType.Ignored.report(name)
|
||||
return
|
||||
}
|
||||
|
||||
if (ignored) {
|
||||
MessageType.Ignored.report(name)
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
||||
enterIfIncluded(name, false) {
|
||||
try {
|
||||
MessageType.Started.report(name)
|
||||
testFn()
|
||||
if (!testArguments.dryRun) {
|
||||
testFn()
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
MessageType.Failed.report(name, e)
|
||||
}
|
||||
MessageType.Finished.report(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.matched(prefix: String, startSourceIndex: Int = 0, startPrefixIndex: Int = 0): Boolean {
|
||||
var sourceIndex = startSourceIndex
|
||||
var prefixIndex = startPrefixIndex
|
||||
|
||||
if (prefixIndex == prefix.lastIndex && prefix[prefixIndex] == '*') return true
|
||||
if (sourceIndex > this.lastIndex) return false
|
||||
|
||||
while (prefixIndex <= prefix.lastIndex && sourceIndex <= this.lastIndex) {
|
||||
val currentSearchSymbol = prefix[prefixIndex]
|
||||
if (currentSearchSymbol == '*') {
|
||||
if (prefixIndex == prefix.lastIndex) return true
|
||||
val searchSymbolAfterStar = prefix[prefixIndex + 1]
|
||||
val foundIndexOfSymbolAfterStar = this.indexOf(searchSymbolAfterStar, sourceIndex)
|
||||
if (foundIndexOfSymbolAfterStar == -1) return false
|
||||
if (this.matched(prefix, foundIndexOfSymbolAfterStar + 1, prefixIndex)) return true
|
||||
sourceIndex = foundIndexOfSymbolAfterStar
|
||||
} else {
|
||||
if (currentSearchSymbol != this[sourceIndex]) return false
|
||||
sourceIndex++
|
||||
}
|
||||
prefixIndex++
|
||||
}
|
||||
|
||||
return sourceIndex > this.lastIndex &&
|
||||
(prefixIndex > prefix.lastIndex || (prefixIndex == prefix.lastIndex && prefix[prefixIndex] == '*'))
|
||||
}
|
||||
Reference in New Issue
Block a user