[KLIB tool] Add tests for dumping metadata signatures

This commit is contained in:
Dmitriy Dolovov
2023-10-25 12:26:02 +02:00
committed by Space Team
parent 88a297b022
commit e18a2d0a2e
25 changed files with 1004 additions and 41 deletions
@@ -259,6 +259,25 @@ fun main() {
}
}
// Dump KLIB metadata signatures tests
testGroup("native/native.tests/tests-gen", "native/native.tests/testData") {
testClass<AbstractNativeKlibDumpMetadataSignaturesTest>(
suiteTestClassName = "NativeKlibDumpMetadataSignaturesTestGenerated",
) {
model("klib/dump-signatures", pattern = "^([^_](.+)).(kt|def)$", recursive = true)
}
}
testGroup("native/native.tests/tests-gen", "native/native.tests/testData") {
testClass<AbstractNativeKlibDumpMetadataSignaturesTest>(
suiteTestClassName = "FirNativeKlibDumpMetadataSignaturesTestGenerated",
annotations = listOf(
*frontendFir()
)
) {
model("klib/dump-signatures", pattern = "^([^_](.+)).(kt|def)$", recursive = true)
}
}
// LLDB integration tests.
testGroup("native/native.tests/tests-gen", "native/native.tests/testData") {
testClass<AbstractNativeBlackBoxTest>(
@@ -78,8 +78,8 @@ abstract class AbstractNativeCInteropTest : AbstractNativeCInteropBaseTest() {
val includeFolder = testDataDir.resolve("include")
val defFile = testPathFull.resolve(defFileName)
val defContents = defFile.readText().split("\n").map { it.trim() }
val defHasObjC = defContents.any { it.endsWith("Objective-C") }
Assumptions.assumeFalse(defHasObjC && !targets.testTarget.family.isAppleFamily)
muteCInteropTestIfNecessary(defFile, targets.testTarget)
val defHasHeaders = defContents.any { it.startsWith("headers") }
Assumptions.assumeFalse(fmodules && defHasHeaders)
@@ -156,3 +156,21 @@ abstract class AbstractNativeCInteropTest : AbstractNativeCInteropBaseTest() {
return testPathFull.resolve("contents.gold.${goldenFilePart}.txt")
}
}
internal fun muteCInteropTestIfNecessary(defFile: File, target: KonanTarget) {
if (target.family.isAppleFamily) return
defFile.readLines().forEach { line ->
if (line.startsWith("---")) return
val parts = line.split('=')
if (parts.size == 2
&& parts[0].trim().equals("language", ignoreCase = true)
&& parts[1].trim().equals("Objective-C", ignoreCase = true)
) {
Assumptions.abort<Nothing>("C-interop tests with Objective-C are not supported at non-Apple targets, def file: $defFile")
}
}
}
//Assumptions.assumeFalse(defHasObjC && !targets.testTarget.family.isAppleFamily)
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.konan.test.blackbox
import com.intellij.testFramework.TestDataFile
import org.jetbrains.kotlin.konan.test.blackbox.support.*
import org.jetbrains.kotlin.konan.test.blackbox.support.compilation.TestCompilationArtifact
import org.jetbrains.kotlin.konan.test.blackbox.support.compilation.TestCompilationArtifact.KLIB
import org.jetbrains.kotlin.konan.test.blackbox.support.compilation.TestCompilationDependency
import org.jetbrains.kotlin.konan.test.blackbox.support.compilation.TestCompilationResult.Companion.assertSuccess
import org.jetbrains.kotlin.konan.test.blackbox.support.runner.TestRunChecks
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.konan.test.blackbox.support.settings.PipelineType
import org.jetbrains.kotlin.konan.test.blackbox.support.settings.Timeouts
import org.jetbrains.kotlin.konan.test.blackbox.support.util.getAbsoluteFile
import org.jetbrains.kotlin.konan.test.blackbox.support.util.dumpIrSignatures
import org.jetbrains.kotlin.konan.test.blackbox.support.util.dumpMetadataSignatures
import org.jetbrains.kotlin.library.KotlinIrSignatureVersion
import org.jetbrains.kotlin.test.services.JUnit5Assertions.assertEqualsToFile
import org.jetbrains.kotlin.test.utils.withExtension
@@ -24,59 +25,37 @@ import org.junit.jupiter.api.Tag
import java.io.File
@Tag("klib")
abstract class AbstractNativeKlibDumpIrSignaturesTest : AbstractNativeSimpleTest() {
abstract class AbstractNativeKlibDumpSignaturesTest : AbstractNativeSimpleTest() {
protected fun runTest(@TestDataFile testDataPath: String) {
val testDataFile = getAbsoluteFile(testDataPath)
muteTestIfNecessary(testDataFile)
val dependencies: List<TestCompilationDependency<TestCompilationArtifact.KLIB>> = buildList {
this += compileRegularDependencies(testDataFile)
this += compileInteropDependencies(testDataFile)
}
val library = compileSingleFileToLibrary(testDataFile, dependencies)
val library = buildLibrary(testDataFile)
val testPathNoExtension = testDataFile.canonicalPath.substringBeforeLast(".")
val firSpecificExt =
if (testRunSettings.get<PipelineType>() == PipelineType.K2 && !firIdentical(testDataFile))
".fir"
else ""
val firSpecificExt = if (testRunSettings.get<PipelineType>() == PipelineType.K2 && !firIdentical(testDataFile)) ".fir" else ""
KotlinIrSignatureVersion.CURRENTLY_SUPPORTED_VERSIONS.forEach { signatureVersion ->
val expectedContents = File("$testPathNoExtension$firSpecificExt.ir-signatures.v${signatureVersion.number}.txt")
val expectedContents = File("$testPathNoExtension$firSpecificExt.$suffix.v${signatureVersion.number}.txt")
assertSignaturesMatchExpected(library, expectedContents, signatureVersion)
}
}
internal abstract val suffix: String
internal abstract fun buildLibrary(testDataFile: File): KLIB
internal abstract fun dumpSignatures(library: KLIB, signatureVersion: KotlinIrSignatureVersion): String
private fun assertSignaturesMatchExpected(
library: TestCompilationArtifact.KLIB,
library: KLIB,
expectedContents: File,
signatureVersion: KotlinIrSignatureVersion
signatureVersion: KotlinIrSignatureVersion,
) {
val kotlinNativeClassLoader = testRunSettings.get<KotlinNativeClassLoader>()
val dumpedSignatures = library.dumpIrSignatures(kotlinNativeClassLoader.classLoader, signatureVersion)
val dumpedSignatures = dumpSignatures(library, signatureVersion)
assertEqualsToFile(expectedContents, dumpedSignatures)
}
private fun compileInteropDependencies(testDataFile: File): List<TestCompilationDependency<TestCompilationArtifact.KLIB>> {
val defFile = testDataFile.withExtension(".lib.def")
if (!defFile.exists()) return emptyList()
assertTrue(defFile.isFile) { "Def file does not exist: $defFile" }
return listOf(
cinteropToLibrary(
targets = targets,
defFile = defFile,
outputDir = buildDir,
freeCompilerArgs = TestCompilerArgs.EMPTY
).assertSuccess().resultingArtifact.asLibraryDependency()
)
}
private fun compileRegularDependencies(testDataFile: File): List<TestCompilationDependency<TestCompilationArtifact.KLIB>> {
internal fun compileRegularDependencies(testDataFile: File): List<TestCompilationDependency<KLIB>> {
val mainSourceFileName = testDataFile.name
return testDataFile.parentFile.listFiles().orEmpty().mapNotNull { dependencyTestDataFile ->
@@ -87,14 +66,23 @@ abstract class AbstractNativeKlibDumpIrSignaturesTest : AbstractNativeSimpleTest
if (dependencyName.isBlank()) return@mapNotNull null
val dependencySourceFile = dependencyTestDataFile.copyTo(buildDir.resolve("$dependencyName.kt"))
compileSingleFileToLibrary(dependencySourceFile, emptyList()).asLibraryDependency()
compileSingleKotlinFileToLibrary(dependencySourceFile, emptyList()).asLibraryDependency()
}
}
private fun compileSingleFileToLibrary(
internal fun compileCInteropDependencies(testDataFile: File): List<TestCompilationDependency<KLIB>> {
val defFile = testDataFile.withExtension(".lib.def")
if (!defFile.exists()) return emptyList()
assertTrue(defFile.isFile) { "Def file does not exist: $defFile" }
return listOf(compileDefFileToLibrary(defFile).asLibraryDependency())
}
internal fun compileSingleKotlinFileToLibrary(
sourceFile: File,
dependencies: List<TestCompilationDependency<TestCompilationArtifact.KLIB>>,
): TestCompilationArtifact.KLIB {
dependencies: List<TestCompilationDependency<KLIB>>,
): KLIB {
val moduleName: String = sourceFile.nameWithoutExtension
val module = TestModule.Exclusive(moduleName, emptySet(), emptySet(), emptySet())
module.files += TestFile.createCommitted(sourceFile, module)
@@ -113,4 +101,49 @@ abstract class AbstractNativeKlibDumpIrSignaturesTest : AbstractNativeSimpleTest
return compileToLibrary(testCase, *dependencies.toTypedArray()).assertSuccess().resultingArtifact
}
internal fun compileDefFileToLibrary(defFile: File): KLIB {
muteCInteropTestIfNecessary(defFile, targets.testTarget)
return cinteropToLibrary(
targets = targets,
defFile = defFile,
outputDir = buildDir,
freeCompilerArgs = TestCompilerArgs.EMPTY
).assertSuccess().resultingArtifact
}
}
abstract class AbstractNativeKlibDumpIrSignaturesTest : AbstractNativeKlibDumpSignaturesTest() {
override val suffix get() = "ir-signatures"
override fun buildLibrary(testDataFile: File) = compileSingleKotlinFileToLibrary(
sourceFile = testDataFile,
dependencies = compileRegularDependencies(testDataFile) + compileCInteropDependencies(testDataFile)
)
override fun dumpSignatures(library: KLIB, signatureVersion: KotlinIrSignatureVersion) =
library.dumpIrSignatures(
testRunSettings.get<KotlinNativeClassLoader>().classLoader,
signatureVersion
)
}
abstract class AbstractNativeKlibDumpMetadataSignaturesTest : AbstractNativeKlibDumpSignaturesTest() {
override val suffix get() = "metadata-signatures"
override fun buildLibrary(testDataFile: File) = when (testDataFile.extension) {
"kt" -> compileSingleKotlinFileToLibrary(
sourceFile = testDataFile,
dependencies = compileRegularDependencies(testDataFile) + compileCInteropDependencies(testDataFile)
)
"def" -> compileDefFileToLibrary(testDataFile)
else -> error("Unexpected test data file: $testDataFile")
}
override fun dumpSignatures(library: KLIB, signatureVersion: KotlinIrSignatureVersion) =
library.dumpMetadataSignatures(
testRunSettings.get<KotlinNativeClassLoader>().classLoader,
signatureVersion
).lineSequence().filter(String::isNotBlank).sorted().joinToString("\n", postfix = "\n")
}
@@ -44,6 +44,16 @@ internal fun TestCompilationArtifact.KLIB.dumpIr(
/* signatureVersion= */ signatureVersion?.let { getSignatureVersionForIsolatedClassLoader(kotlinNativeClassLoader, signatureVersion) }
)
internal fun TestCompilationArtifact.KLIB.dumpMetadataSignatures(
kotlinNativeClassLoader: ClassLoader,
signatureVersion: KotlinIrSignatureVersion,
): String = invokeKlibTool(
kotlinNativeClassLoader = kotlinNativeClassLoader,
klibFile = klibFile,
functionName = "dumpMetadataSignatures",
/* signatureVersion= */ getSignatureVersionForIsolatedClassLoader(kotlinNativeClassLoader, signatureVersion)
)
internal fun TestCompilationArtifact.KLIB.dumpIrSignatures(
kotlinNativeClassLoader: ClassLoader,
signatureVersion: KotlinIrSignatureVersion,