[Wasm] Add Promise and support tests that return Promise

Co-authored-by: Ilya Gorbunov <Ilya.Gorbunov@jetbrains.com>

Merge-request: KT-MR-7717
Merged-by: Svyatoslav Kuzmich <svyatoslav.kuzmich@jetbrains.com>
This commit is contained in:
Svyatoslav Kuzmich
2022-11-25 20:56:47 +00:00
committed by Space Team
parent 002f6bd34a
commit 7ec6608e29
5 changed files with 215 additions and 28 deletions
@@ -7,6 +7,7 @@ package kotlin.test
import kotlin.test.FrameworkAdapter
import kotlin.math.abs
import kotlin.js.*
@JsFun("() => (typeof arguments !== 'undefined' && typeof arguments.join !== 'undefined') ? arguments.join(' ') : '' ")
private external fun d8Arguments(): String
@@ -14,6 +15,28 @@ private external fun d8Arguments(): String
private external fun nodeArguments(): String
internal class TeamcityAdapter : FrameworkAdapter {
private var scheduleNextTaskAfter: Promise<Dynamic?>? = null
private fun runOrScheduleNext(block: () -> Unit) {
if (scheduleNextTaskAfter == null) {
block()
} else {
scheduleNextTaskAfter = scheduleNextTaskAfter!!.finally(block)
}
}
private fun runOrScheduleNextWithResult(block: () -> Promise<Dynamic?>?) {
if (scheduleNextTaskAfter == null) {
val result = block()
if (result != null)
scheduleNextTaskAfter = result
} else {
scheduleNextTaskAfter = scheduleNextTaskAfter!!.then {
block() as Dynamic?
}
}
}
private enum class MessageType(val type: String) {
Started("testStarted"),
Finished("testFinished"),
@@ -50,25 +73,40 @@ internal class TeamcityAdapter : FrameworkAdapter {
}
}
private fun MessageType.report(name: String, errorMessage: String) {
println("##teamcity[$type name='${name.tcEscape()}' message='${errorMessage.tcEscape()}' $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)
runOrScheduleNext {
MessageType.SuiteStarted.report(name)
}
try {
suiteFn()
MessageType.SuiteFinished.report(name)
runOrScheduleNext {
MessageType.SuiteFinished.report(name)
}
} catch (e: Throwable) {
MessageType.SuiteFinished.report(name, e)
runOrScheduleNext {
MessageType.SuiteFinished.report(name, e)
}
}
}
private fun runIgnoredSuite(name: String, suiteFn: () -> Unit) {
MessageType.SuiteStarted.report(name)
runOrScheduleNext {
MessageType.SuiteStarted.report(name)
}
suiteFn()
MessageType.SuiteFinished.report(name)
runOrScheduleNext {
MessageType.SuiteFinished.report(name)
}
}
private var isUnderIgnoredSuit: Boolean = false
@@ -117,45 +155,77 @@ internal class TeamcityAdapter : FrameworkAdapter {
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
runOrScheduleNext {
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 -> {}
}
IgnoredTestSuitesReporting.skip -> { }
}
}
}
override fun test(name: String, ignored: Boolean, testFn: () -> Any?) {
if (isUnderIgnoredSuit) {
MessageType.Ignored.report(name)
runOrScheduleNext {
MessageType.Ignored.report(name)
}
return
}
if (ignored) {
MessageType.Ignored.report(name)
runOrScheduleNext {
MessageType.Ignored.report(name)
}
return
}
enterIfIncluded(name, false) {
try {
runOrScheduleNextWithResult {
MessageType.Started.report(name)
if (!testArguments.dryRun) {
testFn()
val result = try {
if (!testArguments.dryRun) {
testFn()
} else {
null
}
} catch (e: Throwable) {
MessageType.Failed.report(name, e)
}
} catch (e: Throwable) {
MessageType.Failed.report(name, e)
if (result is Promise<*>) {
return@runOrScheduleNextWithResult result.then(
onFulfilled = { value ->
MessageType.Finished.report(name)
value
},
onRejected = { e ->
val throwable = e.toThrowableOrNull()
if (throwable != null) {
MessageType.Failed.report(name, throwable)
} else {
MessageType.Failed.report(name, e.toString())
}
MessageType.Finished.report(name)
null
}
)
}
MessageType.Finished.report(name)
return@runOrScheduleNextWithResult null
}
MessageType.Finished.report(name)
}
}
}