[K/N][tests] Remove now unused LocalTestNameExtractor
This commit is contained in:
committed by
Space Team
parent
234eb29bab
commit
8d696dae03
+2
-112
@@ -7,92 +7,17 @@ package org.jetbrains.kotlin.konan.test.blackbox.support.runner
|
|||||||
|
|
||||||
import com.intellij.openapi.util.SystemInfo
|
import com.intellij.openapi.util.SystemInfo
|
||||||
import com.intellij.openapi.util.text.StringUtilRt.convertLineSeparators
|
import com.intellij.openapi.util.text.StringUtilRt.convertLineSeparators
|
||||||
import kotlinx.coroutines.*
|
|
||||||
import org.jetbrains.kotlin.konan.target.Architecture
|
import org.jetbrains.kotlin.konan.target.Architecture
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
import org.jetbrains.kotlin.konan.target.needSmallBinary
|
import org.jetbrains.kotlin.konan.target.needSmallBinary
|
||||||
import org.jetbrains.kotlin.konan.test.blackbox.support.TestCaseId
|
import org.jetbrains.kotlin.konan.test.blackbox.support.TestCaseId
|
||||||
import org.jetbrains.kotlin.konan.test.blackbox.support.runner.AbstractRunner.AbstractRun
|
|
||||||
import org.jetbrains.kotlin.konan.test.blackbox.support.runner.TestRunCheck.ExecutionTimeout
|
import org.jetbrains.kotlin.konan.test.blackbox.support.runner.TestRunCheck.ExecutionTimeout
|
||||||
import org.jetbrains.kotlin.konan.test.blackbox.support.runner.TestRunCheck.ExitCode
|
import org.jetbrains.kotlin.konan.test.blackbox.support.runner.TestRunCheck.ExitCode
|
||||||
import org.jetbrains.kotlin.konan.test.blackbox.support.runner.UnfilteredProcessOutput.Companion.launchReader
|
|
||||||
import org.jetbrains.kotlin.konan.test.blackbox.support.settings.KotlinNativeTargets
|
import org.jetbrains.kotlin.konan.test.blackbox.support.settings.KotlinNativeTargets
|
||||||
import org.jetbrains.kotlin.konan.test.blackbox.support.settings.OptimizationMode
|
import org.jetbrains.kotlin.konan.test.blackbox.support.settings.OptimizationMode
|
||||||
import org.jetbrains.kotlin.konan.test.blackbox.support.settings.configurables
|
import org.jetbrains.kotlin.konan.test.blackbox.support.settings.configurables
|
||||||
import org.jetbrains.kotlin.konan.test.blackbox.support.util.TestOutputFilter
|
|
||||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toUpperCaseAsciiOnly
|
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toUpperCaseAsciiOnly
|
||||||
import java.io.*
|
import java.io.File
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
|
||||||
import kotlin.time.*
|
|
||||||
|
|
||||||
internal abstract class AbstractLocalProcessRunner<R>(protected val checks: TestRunChecks) : AbstractRunner<R>() {
|
|
||||||
protected abstract val visibleProcessName: String
|
|
||||||
protected abstract val executable: TestExecutable
|
|
||||||
protected abstract val programArgs: List<String>
|
|
||||||
protected abstract val outputFilter: TestOutputFilter
|
|
||||||
|
|
||||||
protected open fun customizeProcess(process: Process) = Unit
|
|
||||||
|
|
||||||
@OptIn(ExperimentalTime::class)
|
|
||||||
final override fun buildRun() = AbstractRun {
|
|
||||||
runBlocking(Dispatchers.IO) {
|
|
||||||
val unfilteredOutput = UnfilteredProcessOutput()
|
|
||||||
val unfilteredOutputReader: Job
|
|
||||||
|
|
||||||
val executionTimeout: Duration = checks.executionTimeoutCheck.timeout
|
|
||||||
|
|
||||||
val process: Process
|
|
||||||
val hasFinishedOnTime: Boolean
|
|
||||||
|
|
||||||
// Don't ignore IO errors that happen just after the process is started.
|
|
||||||
val ignoreIOErrorsInProcessOutput = AtomicBoolean(false)
|
|
||||||
|
|
||||||
val duration = measureTime {
|
|
||||||
process = ProcessBuilder(programArgs).directory(executable.executable.executableFile.parentFile).start()
|
|
||||||
customizeProcess(process)
|
|
||||||
|
|
||||||
unfilteredOutputReader = launchReader(
|
|
||||||
unfilteredOutput,
|
|
||||||
processStdout = process.inputStream,
|
|
||||||
processStderr = process.errorStream,
|
|
||||||
ignoreIOErrorsInProcessOutput
|
|
||||||
)
|
|
||||||
|
|
||||||
hasFinishedOnTime = process.waitFor(
|
|
||||||
executionTimeout.toLong(DurationUnit.MILLISECONDS),
|
|
||||||
DurationUnit.MILLISECONDS.toTimeUnit()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val exitCode: Int? = if (hasFinishedOnTime) {
|
|
||||||
unfilteredOutputReader.join() // Wait until all output streams are drained.
|
|
||||||
process.exitValue()
|
|
||||||
} else {
|
|
||||||
try { // It could happen just by an accident that the process has exited by itself.
|
|
||||||
val exitCode = process.exitValue() // Fetch exit code.
|
|
||||||
unfilteredOutputReader.join() // Wait until all streams are drained.
|
|
||||||
exitCode
|
|
||||||
} catch (_: IllegalThreadStateException) { // Still not destroyed.
|
|
||||||
ignoreIOErrorsInProcessOutput.set(true) // Ignore IO errors caused by the closed streams of the killed process.
|
|
||||||
unfilteredOutputReader.cancel() // Cancel it. No need to read streams, actually.
|
|
||||||
process.destroyForcibly() // kill -9
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RunResult(
|
|
||||||
testExecutable = executable,
|
|
||||||
exitCode = exitCode,
|
|
||||||
timeout = executionTimeout,
|
|
||||||
duration = duration,
|
|
||||||
hasFinishedOnTime = hasFinishedOnTime,
|
|
||||||
processOutput = unfilteredOutput.toProcessOutput(outputFilter)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract override fun buildResultHandler(runResult: RunResult): LocalResultHandler<R> // ?? Narrow returned type.
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun RunResult.processOutputAsString(output: TestRunCheck.Output) = when (output) {
|
private fun RunResult.processOutputAsString(output: TestRunCheck.Output) = when (output) {
|
||||||
TestRunCheck.Output.STDOUT -> processOutput.stdOut.filteredOutput
|
TestRunCheck.Output.STDOUT -> processOutput.stdOut.filteredOutput
|
||||||
@@ -234,43 +159,8 @@ internal abstract class LocalResultHandler<R>(
|
|||||||
protected abstract fun doHandle(): R
|
protected abstract fun doHandle(): R
|
||||||
}
|
}
|
||||||
|
|
||||||
private class UnfilteredProcessOutput {
|
|
||||||
private val stdOut = ByteArrayOutputStream()
|
|
||||||
private val stdErr = ByteArrayOutputStream()
|
|
||||||
|
|
||||||
fun toProcessOutput(outputFilter: TestOutputFilter): ProcessOutput = ProcessOutput(
|
|
||||||
stdOut = outputFilter.filter(stdOut.toString(Charsets.UTF_8.name())),
|
|
||||||
stdErr = stdErr.toString(Charsets.UTF_8.name())
|
|
||||||
)
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun CoroutineScope.launchReader(
|
|
||||||
unfilteredOutput: UnfilteredProcessOutput,
|
|
||||||
processStdout: InputStream,
|
|
||||||
processStderr: InputStream,
|
|
||||||
ignoreIOErrors: AtomicBoolean
|
|
||||||
): Job = launch {
|
|
||||||
fun InputStream.safeCopyTo(output: OutputStream) {
|
|
||||||
try {
|
|
||||||
copyTo(output)
|
|
||||||
} catch (e: IOException) {
|
|
||||||
if (ignoreIOErrors.get()) { // Note: Just checking `!process.isAlive` seems to be not reliable in concurrent environment.
|
|
||||||
// The IO exception might be caused by the closed stream due to process death. Just ignore.
|
|
||||||
} else {
|
|
||||||
// The process is still alive. Some I/O error happened, which is better to rethrow.
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
launch { processStdout.safeCopyTo(unfilteredOutput.stdOut) }
|
|
||||||
launch { processStderr.safeCopyTo(unfilteredOutput.stdErr) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shameless borrowing `val KonanTarget.abiInfo` from module `:kotlin-native:backend.native`, which cannot be imported here for now.
|
// Shameless borrowing `val KonanTarget.abiInfo` from module `:kotlin-native:backend.native`, which cannot be imported here for now.
|
||||||
val KonanTarget.abiInfoString: String
|
private val KonanTarget.abiInfoString: String
|
||||||
get() = when {
|
get() = when {
|
||||||
this == KonanTarget.MINGW_X64 -> "WINDOWSX64"
|
this == KonanTarget.MINGW_X64 -> "WINDOWSX64"
|
||||||
!family.isAppleFamily && architecture == Architecture.ARM64 -> "AAPCS"
|
!family.isAppleFamily && architecture == Architecture.ARM64 -> "AAPCS"
|
||||||
-46
@@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2023 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.konan.test.blackbox.support.runner
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.konan.test.blackbox.support.LoggedData
|
|
||||||
import org.jetbrains.kotlin.konan.test.blackbox.support.TestName
|
|
||||||
import org.jetbrains.kotlin.konan.test.blackbox.support.util.GTestListing
|
|
||||||
import org.jetbrains.kotlin.konan.test.blackbox.support.util.TestOutputFilter
|
|
||||||
import org.jetbrains.kotlin.test.services.JUnit5Assertions.fail
|
|
||||||
|
|
||||||
internal class LocalTestNameExtractor(
|
|
||||||
override val executable: TestExecutable,
|
|
||||||
checks: TestRunChecks
|
|
||||||
) : AbstractLocalProcessRunner<Collection<TestName>>(checks) {
|
|
||||||
override val visibleProcessName get() = "Test name extractor"
|
|
||||||
override val programArgs = listOf(executable.executable.executableFile.path, "--ktest_list_tests")
|
|
||||||
override val outputFilter get() = TestOutputFilter.NO_FILTERING
|
|
||||||
|
|
||||||
override fun getLoggedParameters() = LoggedData.TestRunParameters(
|
|
||||||
compilationToolCall = executable.loggedCompilationToolCall,
|
|
||||||
testCaseId = null,
|
|
||||||
runArgs = programArgs,
|
|
||||||
runParameters = null
|
|
||||||
)
|
|
||||||
|
|
||||||
override fun buildResultHandler(runResult: RunResult) =
|
|
||||||
TestNameResultHandler(runResult, visibleProcessName, checks, getLoggedParameters())
|
|
||||||
|
|
||||||
override fun handleUnexpectedFailure(t: Throwable) = fail {
|
|
||||||
LoggedData.TestRunUnexpectedFailure(getLoggedParameters(), t)
|
|
||||||
.withErrorMessage("Test name extraction failed with unexpected exception.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class TestNameResultHandler(
|
|
||||||
runResult: RunResult,
|
|
||||||
visibleProcessName: String,
|
|
||||||
checks: TestRunChecks,
|
|
||||||
private val loggedParameters: LoggedData.TestRunParameters
|
|
||||||
) : LocalResultHandler<Collection<TestName>>(runResult, visibleProcessName, checks, null, false) {
|
|
||||||
override fun getLoggedRun() = LoggedData.TestRun(loggedParameters, runResult)
|
|
||||||
override fun doHandle() = GTestListing.parse(runResult.processOutput.stdOut.filteredOutput)
|
|
||||||
}
|
|
||||||
-10
@@ -35,16 +35,6 @@ internal object TestRunners {
|
|||||||
|
|
||||||
private val executorCache: ConcurrentHashMap<KonanTarget, Executor> = ConcurrentHashMap()
|
private val executorCache: ConcurrentHashMap<KonanTarget, Executor> = ConcurrentHashMap()
|
||||||
|
|
||||||
// Currently, only local test name extractor is supported.
|
|
||||||
fun extractTestNames(executable: TestExecutable, settings: Settings): Collection<TestName> = with(settings) {
|
|
||||||
with(get<KotlinNativeTargets>()) {
|
|
||||||
if (testTarget == hostTarget)
|
|
||||||
LocalTestNameExtractor(executable, TestRunChecks.Default(get<Timeouts>().executionTimeout)).run()
|
|
||||||
else
|
|
||||||
runningOnUnsupportedTarget()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun KotlinNativeTargets.runningOnUnsupportedTarget(): Nothing = fail {
|
private fun KotlinNativeTargets.runningOnUnsupportedTarget(): Nothing = fail {
|
||||||
"Running tests for $testTarget on $hostTarget is not supported yet."
|
"Running tests for $testTarget on $hostTarget is not supported yet."
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user