[Native][tests] Do not run test executable to fetch the list of test names
Use test listing produced during compilation instead. ^KT-50316
This commit is contained in:
+1
-1
@@ -88,7 +88,7 @@ abstract class AbstractNativeKlibABITest : AbstractNativeSimpleTest() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
val compilationResult = compilation.result.assertSuccess() // <-- trigger compilation
|
val compilationResult = compilation.result.assertSuccess() // <-- trigger compilation
|
||||||
val executable = TestExecutable(executableFile, compilationResult.loggedData)
|
val executable = TestExecutable.fromCompilationResult(testCase, compilationResult)
|
||||||
|
|
||||||
runExecutableAndVerify(testCase, executable) // <-- run executable and verify
|
runExecutableAndVerify(testCase, executable) // <-- run executable and verify
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -88,7 +88,7 @@ class InfrastructureDumpedTestListingTest : AbstractNativeSimpleTest() {
|
|||||||
assertTrue(dumpedTestListing.isNotEmpty())
|
assertTrue(dumpedTestListing.isNotEmpty())
|
||||||
|
|
||||||
// parse test listing obtained from executable file with the help of --ktest_list_tests flag:
|
// parse test listing obtained from executable file with the help of --ktest_list_tests flag:
|
||||||
val testExecutable = TestExecutable(executable.executableFile, executableCompilationResult.loggedData)
|
val testExecutable = TestExecutable.fromCompilationResult(executableTestCase, executableCompilationResult)
|
||||||
val extractedTestListing = TestRunners.extractTestNames(testExecutable, testRunSettings).toSet()
|
val extractedTestListing = TestRunners.extractTestNames(testExecutable, testRunSettings).toSet()
|
||||||
|
|
||||||
assertEquals(extractedTestListing, dumpedTestListing)
|
assertEquals(extractedTestListing, dumpedTestListing)
|
||||||
|
|||||||
+5
-1
@@ -28,9 +28,13 @@ internal abstract class LoggedData {
|
|||||||
protected abstract fun computeText(): String
|
protected abstract fun computeText(): String
|
||||||
final override fun toString() = text
|
final override fun toString() = text
|
||||||
|
|
||||||
fun withErrorMessage(errorMessage: String): String = buildString {
|
fun withErrorMessage(errorMessage: String, t: Throwable? = null): String = buildString {
|
||||||
appendLine(errorMessage)
|
appendLine(errorMessage)
|
||||||
appendLine()
|
appendLine()
|
||||||
|
if (t != null) {
|
||||||
|
appendLine(t.stackTraceToString())
|
||||||
|
appendLine()
|
||||||
|
}
|
||||||
appendLine(this@LoggedData)
|
appendLine(this@LoggedData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+37
-6
@@ -5,19 +5,50 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.konan.blackboxtest.support.runner
|
package org.jetbrains.kotlin.konan.blackboxtest.support.runner
|
||||||
|
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.LoggedData
|
import org.jetbrains.kotlin.konan.blackboxtest.support.*
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.PackageName
|
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationArtifact.Executable
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.TestCaseId
|
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationResult.Success
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.TestName
|
import org.jetbrains.kotlin.konan.blackboxtest.support.util.DumpedTestListing
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.util.startsWith
|
import org.jetbrains.kotlin.konan.blackboxtest.support.util.startsWith
|
||||||
import org.jetbrains.kotlin.test.services.JUnit5Assertions.assertFalse
|
import org.jetbrains.kotlin.test.services.JUnit5Assertions.assertFalse
|
||||||
|
import org.jetbrains.kotlin.test.services.JUnit5Assertions.fail
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
internal class TestExecutable(
|
internal class TestExecutable(
|
||||||
val executableFile: File,
|
val executableFile: File,
|
||||||
val loggedCompilerCall: LoggedData.CompilerCall
|
val loggedCompilerCall: LoggedData.CompilerCall,
|
||||||
)
|
val testNames: Collection<TestName>
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
fun fromCompilationResult(testCase: TestCase, compilationResult: Success<out Executable>): TestExecutable {
|
||||||
|
val testNames = when (testCase.kind) {
|
||||||
|
TestKind.REGULAR, TestKind.STANDALONE -> {
|
||||||
|
val testDumpFile = compilationResult.resultingArtifact.testDumpFile
|
||||||
|
val testDump = try {
|
||||||
|
testDumpFile.readText()
|
||||||
|
} catch (e: IOException) {
|
||||||
|
fail { compilationResult.loggedData.withErrorMessage("Failed to read test dump file: $testDumpFile", e) }
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
DumpedTestListing.parse(testDump)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
fail { compilationResult.loggedData.withErrorMessage("Failed to parse test dump file: $testDumpFile", e) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
return TestExecutable(
|
||||||
|
executableFile = compilationResult.resultingArtifact.executableFile,
|
||||||
|
loggedCompilerCall = compilationResult.loggedData,
|
||||||
|
testNames = testNames
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal class TestRun(
|
internal class TestRun(
|
||||||
val displayName: String,
|
val displayName: String,
|
||||||
|
|||||||
+18
-19
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilati
|
|||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationFactory
|
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationFactory
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationResult.Companion.assertSuccess
|
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationResult.Companion.assertSuccess
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.group.TestCaseGroupProvider
|
import org.jetbrains.kotlin.konan.blackboxtest.support.group.TestCaseGroupProvider
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.runner.TestRunners.extractTestNames
|
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.Settings
|
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.Settings
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.util.ThreadSafeCache
|
import org.jetbrains.kotlin.konan.blackboxtest.support.util.ThreadSafeCache
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.util.TreeNode
|
import org.jetbrains.kotlin.konan.blackboxtest.support.util.TreeNode
|
||||||
@@ -34,7 +33,6 @@ internal class TestRunProvider(
|
|||||||
) : BaseTestRunProvider(), ExtensionContext.Store.CloseableResource {
|
) : BaseTestRunProvider(), ExtensionContext.Store.CloseableResource {
|
||||||
private val compilationFactory = TestCompilationFactory()
|
private val compilationFactory = TestCompilationFactory()
|
||||||
private val cachedCompilations = ThreadSafeCache<TestCompilationCacheKey, TestCompilation<Executable>>()
|
private val cachedCompilations = ThreadSafeCache<TestCompilationCacheKey, TestCompilation<Executable>>()
|
||||||
private val cachedTestNames = ThreadSafeCache<TestCompilationCacheKey, Collection<TestName>>()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Produces a single [TestRun] per [TestCase]. So-called "one test case/one test run" mode.
|
* Produces a single [TestRun] per [TestCase]. So-called "one test case/one test run" mode.
|
||||||
@@ -64,7 +62,7 @@ internal class TestRunProvider(
|
|||||||
fun getSingleTestRun(
|
fun getSingleTestRun(
|
||||||
testCaseId: TestCaseId,
|
testCaseId: TestCaseId,
|
||||||
settings: Settings
|
settings: Settings
|
||||||
): TestRun = withTestExecutable(testCaseId, settings) { testCase, executable, _ ->
|
): TestRun = withTestExecutable(testCaseId, settings) { testCase, executable ->
|
||||||
createSingleTestRun(testCase, executable)
|
createSingleTestRun(testCase, executable)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +99,7 @@ internal class TestRunProvider(
|
|||||||
fun getTestRuns(
|
fun getTestRuns(
|
||||||
testCaseId: TestCaseId,
|
testCaseId: TestCaseId,
|
||||||
settings: Settings
|
settings: Settings
|
||||||
): Collection<TreeNode<TestRun>> = withTestExecutable(testCaseId, settings) { testCase, executable, cacheKey ->
|
): Collection<TreeNode<TestRun>> = withTestExecutable(testCaseId, settings) { testCase, executable ->
|
||||||
fun createTestRun(testRunName: String, testName: TestName?) = createTestRun(testCase, executable, testRunName, testName)
|
fun createTestRun(testRunName: String, testName: TestName?) = createTestRun(testCase, executable, testRunName, testName)
|
||||||
|
|
||||||
when (testCase.kind) {
|
when (testCase.kind) {
|
||||||
@@ -111,10 +109,7 @@ internal class TestRunProvider(
|
|||||||
TreeNode.oneLevel(testRun)
|
TreeNode.oneLevel(testRun)
|
||||||
}
|
}
|
||||||
TestKind.REGULAR, TestKind.STANDALONE -> {
|
TestKind.REGULAR, TestKind.STANDALONE -> {
|
||||||
val testNames = cachedTestNames.computeIfAbsent(cacheKey) {
|
val testNames = executable.testNames.filterIrrelevant(testCase)
|
||||||
extractTestNames(executable, settings)
|
|
||||||
}.filterIrrelevant(testCase)
|
|
||||||
|
|
||||||
testNames.buildTree(TestName::packageName) { testName ->
|
testNames.buildTree(TestName::packageName) { testName ->
|
||||||
createTestRun(testName.functionName, testName)
|
createTestRun(testName.functionName, testName)
|
||||||
}
|
}
|
||||||
@@ -125,7 +120,7 @@ internal class TestRunProvider(
|
|||||||
private fun <T> withTestExecutable(
|
private fun <T> withTestExecutable(
|
||||||
testCaseId: TestCaseId,
|
testCaseId: TestCaseId,
|
||||||
settings: Settings,
|
settings: Settings,
|
||||||
action: (TestCase, TestExecutable, TestCompilationCacheKey) -> T
|
action: (TestCase, TestExecutable) -> T
|
||||||
): T {
|
): T {
|
||||||
val testCaseGroup = testCaseGroupProvider.getTestCaseGroup(testCaseId.testCaseGroupId, settings)
|
val testCaseGroup = testCaseGroupProvider.getTestCaseGroup(testCaseId.testCaseGroupId, settings)
|
||||||
?: fail { "No test case for $testCaseId" }
|
?: fail { "No test case for $testCaseId" }
|
||||||
@@ -134,32 +129,36 @@ internal class TestRunProvider(
|
|||||||
|
|
||||||
val testCase = testCaseGroup.getByName(testCaseId) ?: fail { "No test case for $testCaseId" }
|
val testCase = testCaseGroup.getByName(testCaseId) ?: fail { "No test case for $testCaseId" }
|
||||||
|
|
||||||
val (testCompilation, cacheKey) = when (testCase.kind) {
|
val testCompilation = when (testCase.kind) {
|
||||||
TestKind.STANDALONE, TestKind.STANDALONE_NO_TR -> {
|
TestKind.STANDALONE, TestKind.STANDALONE_NO_TR -> {
|
||||||
// Create a separate compilation for each standalone test case.
|
// Create a separate compilation for each standalone test case.
|
||||||
val cacheKey = TestCompilationCacheKey.Standalone(testCaseId)
|
cachedCompilations.computeIfAbsent(
|
||||||
val testCompilation = cachedCompilations.computeIfAbsent(cacheKey) {
|
TestCompilationCacheKey.Standalone(testCaseId)
|
||||||
|
) {
|
||||||
compilationFactory.testCasesToExecutable(listOf(testCase), settings)
|
compilationFactory.testCasesToExecutable(listOf(testCase), settings)
|
||||||
}
|
}
|
||||||
testCompilation to cacheKey
|
|
||||||
}
|
}
|
||||||
TestKind.REGULAR -> {
|
TestKind.REGULAR -> {
|
||||||
// Group regular test cases by compiler arguments.
|
// Group regular test cases by compiler arguments.
|
||||||
val testRunnerType = testCase.extras<WithTestRunnerExtras>().runnerType
|
val testRunnerType = testCase.extras<WithTestRunnerExtras>().runnerType
|
||||||
val cacheKey = TestCompilationCacheKey.Grouped(testCaseId.testCaseGroupId, testCase.freeCompilerArgs, testRunnerType)
|
cachedCompilations.computeIfAbsent(
|
||||||
val testCompilation = cachedCompilations.computeIfAbsent(cacheKey) {
|
TestCompilationCacheKey.Grouped(
|
||||||
|
testCaseGroupId = testCaseId.testCaseGroupId,
|
||||||
|
freeCompilerArgs = testCase.freeCompilerArgs,
|
||||||
|
runnerType = testRunnerType
|
||||||
|
)
|
||||||
|
) {
|
||||||
val testCases = testCaseGroup.getRegularOnly(testCase.freeCompilerArgs, testRunnerType)
|
val testCases = testCaseGroup.getRegularOnly(testCase.freeCompilerArgs, testRunnerType)
|
||||||
assertTrue(testCases.isNotEmpty())
|
assertTrue(testCases.isNotEmpty())
|
||||||
compilationFactory.testCasesToExecutable(testCases, settings)
|
compilationFactory.testCasesToExecutable(testCases, settings)
|
||||||
}
|
}
|
||||||
testCompilation to cacheKey
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val (artifact, loggedCompilerCall) = testCompilation.result.assertSuccess() // <-- Compilation happens here.
|
val compilationResult = testCompilation.result.assertSuccess() // <-- Compilation happens here.
|
||||||
val executable = TestExecutable(artifact.executableFile, loggedCompilerCall)
|
val executable = TestExecutable.fromCompilationResult(testCase, compilationResult)
|
||||||
|
|
||||||
return action(testCase, executable, cacheKey)
|
return action(testCase, executable)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Collection<TestName>.filterIrrelevant(testCase: TestCase) =
|
private fun Collection<TestName>.filterIrrelevant(testCase: TestCase) =
|
||||||
|
|||||||
Reference in New Issue
Block a user