[K/N] Test for cinterop hints
This commit is contained in:
committed by
Space Team
parent
233b01f341
commit
64319477f0
+2
-3
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.konan.blackboxtest
|
|||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.*
|
import org.jetbrains.kotlin.konan.blackboxtest.support.*
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.*
|
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.*
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationArtifact.*
|
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationArtifact.*
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationResult.Companion.assertSuccess
|
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.runner.*
|
import org.jetbrains.kotlin.konan.blackboxtest.support.runner.*
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.*
|
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.*
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -18,7 +17,7 @@ abstract class AbstractNativeCInteropBaseTest : AbstractNativeSimpleTest() {
|
|||||||
internal val targets: KotlinNativeTargets get() = testRunSettings.get<KotlinNativeTargets>()
|
internal val targets: KotlinNativeTargets get() = testRunSettings.get<KotlinNativeTargets>()
|
||||||
internal val kotlinNativeClassLoader: KotlinNativeClassLoader get() = testRunSettings.get<KotlinNativeClassLoader>()
|
internal val kotlinNativeClassLoader: KotlinNativeClassLoader get() = testRunSettings.get<KotlinNativeClassLoader>()
|
||||||
|
|
||||||
internal fun TestCase.cinteropToLibrary(): TestCompilationResult.Success<out KLIB> {
|
internal fun TestCase.cinteropToLibrary(): TestCompilationResult<out KLIB> {
|
||||||
modules.singleOrNull()
|
modules.singleOrNull()
|
||||||
val compilation = CInteropCompilation(
|
val compilation = CInteropCompilation(
|
||||||
classLoader = testRunSettings.get(),
|
classLoader = testRunSettings.get(),
|
||||||
@@ -27,7 +26,7 @@ abstract class AbstractNativeCInteropBaseTest : AbstractNativeSimpleTest() {
|
|||||||
defFile = modules.singleOrNull()!!.files.singleOrNull()!!.location,
|
defFile = modules.singleOrNull()!!.files.singleOrNull()!!.location,
|
||||||
expectedArtifact = toLibraryArtifact()
|
expectedArtifact = toLibraryArtifact()
|
||||||
)
|
)
|
||||||
return compilation.result.assertSuccess()
|
return compilation.result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun TestCase.toLibraryArtifact() = KLIB(buildDir.resolve(modules.singleOrNull()!!.name + ".klib"))
|
private fun TestCase.toLibraryArtifact() = KLIB(buildDir.resolve(modules.singleOrNull()!!.name + ".klib"))
|
||||||
|
|||||||
+3
-2
@@ -10,6 +10,7 @@ import com.intellij.testFramework.TestDataFile
|
|||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.*
|
import org.jetbrains.kotlin.konan.blackboxtest.support.*
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.*
|
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.*
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationArtifact.*
|
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationArtifact.*
|
||||||
|
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationResult.Companion.assertSuccess
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.*
|
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.*
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.util.*
|
import org.jetbrains.kotlin.konan.blackboxtest.support.util.*
|
||||||
import org.junit.jupiter.api.Tag
|
import org.junit.jupiter.api.Tag
|
||||||
@@ -35,7 +36,7 @@ abstract class AbstractNativeCInteropKT39120Test : AbstractNativeCInteropBaseTes
|
|||||||
val includeFrameworkArgs = listOf("-compiler-option", "-F${testDataDir.canonicalPath}")
|
val includeFrameworkArgs = listOf("-compiler-option", "-F${testDataDir.canonicalPath}")
|
||||||
|
|
||||||
val test1Case: TestCase = generateCInteropTestCaseWithSingleDef(def1File, includeFrameworkArgs)
|
val test1Case: TestCase = generateCInteropTestCaseWithSingleDef(def1File, includeFrameworkArgs)
|
||||||
val klib1: KLIB = test1Case.cinteropToLibrary().resultingArtifact
|
val klib1: KLIB = test1Case.cinteropToLibrary().assertSuccess().resultingArtifact
|
||||||
val contents1 = klib1.getContents(kotlinNativeClassLoader.classLoader)
|
val contents1 = klib1.getContents(kotlinNativeClassLoader.classLoader)
|
||||||
|
|
||||||
val expectedFiltered1Output = golden1File.readText()
|
val expectedFiltered1Output = golden1File.readText()
|
||||||
@@ -44,7 +45,7 @@ abstract class AbstractNativeCInteropKT39120Test : AbstractNativeCInteropBaseTes
|
|||||||
|
|
||||||
val cinterop2ExtraArgs = listOf("-l", klib1.klibFile.canonicalPath, "-compiler-option", "-fmodules")
|
val cinterop2ExtraArgs = listOf("-l", klib1.klibFile.canonicalPath, "-compiler-option", "-fmodules")
|
||||||
val test2Case: TestCase = generateCInteropTestCaseWithSingleDef(def2File, includeFrameworkArgs + cinterop2ExtraArgs)
|
val test2Case: TestCase = generateCInteropTestCaseWithSingleDef(def2File, includeFrameworkArgs + cinterop2ExtraArgs)
|
||||||
val klib2: KLIB = test2Case.cinteropToLibrary().resultingArtifact
|
val klib2: KLIB = test2Case.cinteropToLibrary().assertSuccess().resultingArtifact
|
||||||
val contents2 = klib2.getContents(kotlinNativeClassLoader.classLoader)
|
val contents2 = klib2.getContents(kotlinNativeClassLoader.classLoader)
|
||||||
|
|
||||||
val expectedFiltered2Output = golden2File.readText()
|
val expectedFiltered2Output = golden2File.readText()
|
||||||
|
|||||||
+16
-7
@@ -10,12 +10,15 @@ import com.intellij.testFramework.TestDataFile
|
|||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.*
|
import org.jetbrains.kotlin.konan.blackboxtest.support.*
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.*
|
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.*
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationArtifact.*
|
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationArtifact.*
|
||||||
|
import org.jetbrains.kotlin.konan.blackboxtest.support.compilation.TestCompilationResult.Companion.assertSuccess
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.runner.*
|
import org.jetbrains.kotlin.konan.blackboxtest.support.runner.*
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.*
|
import org.jetbrains.kotlin.konan.blackboxtest.support.settings.*
|
||||||
import org.jetbrains.kotlin.konan.blackboxtest.support.util.*
|
import org.jetbrains.kotlin.konan.blackboxtest.support.util.*
|
||||||
import org.jetbrains.kotlin.konan.target.Family
|
import org.jetbrains.kotlin.konan.target.Family
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
|
import org.jetbrains.kotlin.konan.util.CInteropHints
|
||||||
import org.jetbrains.kotlin.test.services.JUnit5Assertions.assertEquals
|
import org.jetbrains.kotlin.test.services.JUnit5Assertions.assertEquals
|
||||||
|
import org.jetbrains.kotlin.test.services.JUnit5Assertions.assertTrue
|
||||||
import org.junit.jupiter.api.Assumptions
|
import org.junit.jupiter.api.Assumptions
|
||||||
import org.junit.jupiter.api.Tag
|
import org.junit.jupiter.api.Tag
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -40,8 +43,6 @@ abstract class AbstractNativeCInteropTest : AbstractNativeCInteropBaseTest() {
|
|||||||
this is AbstractNativeCInteropFModulesTest &&
|
this is AbstractNativeCInteropFModulesTest &&
|
||||||
targets.testTarget.family == Family.ANDROID
|
targets.testTarget.family == Family.ANDROID
|
||||||
)
|
)
|
||||||
Assumptions.assumeFalse(!fmodules && testPath.endsWith("FModules/"))
|
|
||||||
|
|
||||||
val testPathFull = getAbsoluteFile(testPath)
|
val testPathFull = getAbsoluteFile(testPath)
|
||||||
val testDataDir = testPathFull.parentFile.parentFile
|
val testDataDir = testPathFull.parentFile.parentFile
|
||||||
val includeFolder = testDataDir.resolve("include")
|
val includeFolder = testDataDir.resolve("include")
|
||||||
@@ -65,11 +66,19 @@ abstract class AbstractNativeCInteropTest : AbstractNativeCInteropBaseTest() {
|
|||||||
|
|
||||||
val testCase: TestCase = generateCInteropTestCaseWithSingleDef(defFile, includeArgs + fmodulesArgs)
|
val testCase: TestCase = generateCInteropTestCaseWithSingleDef(defFile, includeArgs + fmodulesArgs)
|
||||||
val testCompilationResult = testCase.cinteropToLibrary()
|
val testCompilationResult = testCase.cinteropToLibrary()
|
||||||
val klibContents = testCompilationResult.resultingArtifact.getContents(kotlinNativeClassLoader.classLoader)
|
// If we are running fmodules-specific test without -fmodules then we want to be sure that cinterop fails the way we want it to.
|
||||||
|
if (!fmodules && testPath.endsWith("FModules/")) {
|
||||||
val expectedContents = goldenFile.readText()
|
val loggedData = (testCompilationResult as TestCompilationResult.CompilationToolFailure).loggedData
|
||||||
assertEquals(StringUtilRt.convertLineSeparators(expectedContents), StringUtilRt.convertLineSeparators(klibContents)) {
|
val prettyMessage = CInteropHints.fmodulesHint
|
||||||
"Test failed. CInterop compilation result was: $testCompilationResult"
|
assertTrue(loggedData.toString().contains(prettyMessage)) {
|
||||||
|
"Test failed. CInterop compilation result was: $testCompilationResult"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val klibContents = testCompilationResult.assertSuccess().resultingArtifact.getContents(kotlinNativeClassLoader.classLoader)
|
||||||
|
val expectedContents = goldenFile.readText()
|
||||||
|
assertEquals(StringUtilRt.convertLineSeparators(expectedContents), StringUtilRt.convertLineSeparators(klibContents)) {
|
||||||
|
"Test failed. CInterop compilation result was: $testCompilationResult"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+29
-19
@@ -17,6 +17,7 @@ import java.io.PrintStream
|
|||||||
import kotlin.time.Duration
|
import kotlin.time.Duration
|
||||||
import kotlin.time.ExperimentalTime
|
import kotlin.time.ExperimentalTime
|
||||||
import kotlin.time.measureTime
|
import kotlin.time.measureTime
|
||||||
|
import kotlin.time.measureTimedValue
|
||||||
import org.jetbrains.kotlin.konan.file.File as KonanFile
|
import org.jetbrains.kotlin.konan.file.File as KonanFile
|
||||||
|
|
||||||
internal data class CompilationToolCallResult(
|
internal data class CompilationToolCallResult(
|
||||||
@@ -73,6 +74,7 @@ internal fun callCompiler(compilerArgs: Array<String>, kotlinNativeClassLoader:
|
|||||||
return CompilationToolCallResult(exitCode, compilerOutput, messageCollector.hasErrors(), duration)
|
return CompilationToolCallResult(exitCode, compilerOutput, messageCollector.hasErrors(), duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalTime::class)
|
||||||
internal fun invokeCInterop(
|
internal fun invokeCInterop(
|
||||||
kotlinNativeClassLoader: ClassLoader,
|
kotlinNativeClassLoader: ClassLoader,
|
||||||
targets: KotlinNativeTargets,
|
targets: KotlinNativeTargets,
|
||||||
@@ -90,30 +92,38 @@ internal fun invokeCInterop(
|
|||||||
val interopClass = Class.forName("org.jetbrains.kotlin.native.interop.gen.jvm.Interop", true, kotlinNativeClassLoader)
|
val interopClass = Class.forName("org.jetbrains.kotlin.native.interop.gen.jvm.Interop", true, kotlinNativeClassLoader)
|
||||||
val entryPoint = interopClass.declaredMethods.single { it.name == "interopViaReflection" }
|
val entryPoint = interopClass.declaredMethods.single { it.name == "interopViaReflection" }
|
||||||
|
|
||||||
val possibleSubsequentCompilerInvocationArgs: Array<String>?
|
val (cinteropResult, duration) = measureTimedValue {
|
||||||
|
entryPoint.invoke(
|
||||||
@OptIn(ExperimentalTime::class)
|
|
||||||
val duration = measureTime {
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
possibleSubsequentCompilerInvocationArgs = entryPoint.invoke(
|
|
||||||
interopClass.getDeclaredConstructor().newInstance(),
|
interopClass.getDeclaredConstructor().newInstance(),
|
||||||
"native",
|
"native",
|
||||||
args + extraArgs,
|
args + extraArgs,
|
||||||
false,
|
false,
|
||||||
generatedDir.absolutePath, nativesDir.absolutePath, manifest.path, cstubsName // args for InternalInteropOptions()
|
generatedDir.absolutePath, nativesDir.absolutePath, manifest.path, cstubsName // args for InternalInteropOptions()
|
||||||
) as? Array<String>?
|
|
||||||
}
|
|
||||||
// In currently tested usecases, cinterop must return no args for the subsequent compiler call
|
|
||||||
return if (possibleSubsequentCompilerInvocationArgs == null) {
|
|
||||||
// TODO There is no technical ability to extract `toolOutput` and `toolOutputHasErrors`
|
|
||||||
// from C-interop tool invocation at the moment. This should be fixed in the future.
|
|
||||||
CompilationToolCallResult(exitCode = ExitCode.OK, toolOutput = "", toolOutputHasErrors = false, duration)
|
|
||||||
} else {
|
|
||||||
CompilationToolCallResult(
|
|
||||||
exitCode = ExitCode.COMPILATION_ERROR,
|
|
||||||
toolOutput = possibleSubsequentCompilerInvocationArgs.joinToString(" "),
|
|
||||||
toolOutputHasErrors = true,
|
|
||||||
duration
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
return when {
|
||||||
|
// cinterop has failed with a known error that was returned as a result.
|
||||||
|
cinteropResult is Exception -> {
|
||||||
|
CompilationToolCallResult(
|
||||||
|
exitCode = ExitCode.COMPILATION_ERROR,
|
||||||
|
toolOutput = cinteropResult.message ?: "",
|
||||||
|
toolOutputHasErrors = true,
|
||||||
|
duration
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// In currently tested usecases, cinterop must return no args for the subsequent compiler call
|
||||||
|
cinteropResult is Array<*> -> {
|
||||||
|
CompilationToolCallResult(
|
||||||
|
exitCode = ExitCode.COMPILATION_ERROR,
|
||||||
|
toolOutput = cinteropResult.joinToString(" "),
|
||||||
|
toolOutputHasErrors = true,
|
||||||
|
duration
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
// TODO There is no technical ability to extract `toolOutput` and `toolOutputHasErrors`
|
||||||
|
// from C-interop tool invocation at the moment. This should be fixed in the future.
|
||||||
|
CompilationToolCallResult(exitCode = ExitCode.OK, toolOutput = "", toolOutputHasErrors = false, duration)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user