447c0fb618
^KT-61259
2724 lines
100 KiB
Groovy
2724 lines
100 KiB
Groovy
/*
|
|
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
|
* that can be found in the LICENSE file.
|
|
*/
|
|
|
|
|
|
import org.codehaus.groovy.runtime.IOGroovyMethods
|
|
import org.jetbrains.kotlin.*
|
|
import org.jetbrains.kotlin.gradle.plugin.tasks.KonanCompileNativeBinary
|
|
import org.jetbrains.kotlin.konan.target.Architecture
|
|
import org.jetbrains.kotlin.konan.target.Family
|
|
import org.jetbrains.kotlin.konan.target.HostManager
|
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
|
|
|
import java.util.regex.Pattern
|
|
|
|
buildscript {
|
|
repositories {
|
|
mavenCentral()
|
|
|
|
maven {
|
|
url project.bootstrapKotlinRepo
|
|
}
|
|
}
|
|
}
|
|
|
|
apply plugin: 'konan'
|
|
apply plugin: 'kotlin'
|
|
apply plugin: 'kotlin.native.build-tools-conventions'
|
|
apply plugin: 'native-dependencies'
|
|
|
|
configurations {
|
|
cli_bc
|
|
update_tests
|
|
|
|
nopPluginApi
|
|
api.extendsFrom nopPluginApi
|
|
}
|
|
|
|
dependencies {
|
|
// TODO: upgrade coroutines to common version
|
|
api RepoDependencies.commonDependency(project, "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7")
|
|
}
|
|
ext.testOutputRoot = rootProject.file("test.output").absolutePath
|
|
|
|
ext.platformManager = project.project(":kotlin-native").platformManager
|
|
ext.target = platformManager.targetManager(project.testTarget).target
|
|
|
|
ext.buildNumber = rootProject.property("kotlinVersion")
|
|
|
|
// Add executor to run tests depending on a target
|
|
// NOTE: If this persists in a gradle daemon, environment update (e.g. an Xcode update) may lead to execution failures.
|
|
project.extensions.executor = ExecutorServiceKt.create(project)
|
|
|
|
ext.useCustomDist = UtilsKt.getUseCustomDist(project)
|
|
ext.kotlinNativeDist = UtilsKt.getKotlinNativeDist(project)
|
|
if (!useCustomDist) {
|
|
ext.setProperty("kotlin.native.home", kotlinNativeDist.absolutePath)
|
|
ext.setProperty("org.jetbrains.kotlin.native.home", kotlinNativeDist.absolutePath)
|
|
ext.setProperty("konan.home", kotlinNativeDist.absolutePath)
|
|
}
|
|
|
|
compileTestKotlin {
|
|
kotlinOptions {
|
|
freeCompilerArgs += "-Xskip-prerelease-check"
|
|
}
|
|
}
|
|
|
|
// Do not generate run tasks for konan built artifacts
|
|
ext.konanNoRun = true
|
|
|
|
final CacheTesting cacheTesting = CacheTestingKt.configureCacheTesting(project)
|
|
if (cacheTesting != null) {
|
|
// Check for debug build and set the -g option.
|
|
if (project.globalTestArgs.contains("-opt")) {
|
|
throw new IllegalArgumentException("Cache testing should be run with debug build. " +
|
|
"Remove -opt options from the test args")
|
|
}
|
|
if (!project.globalTestArgs.contains("-g")) {
|
|
project.globalTestArgs.add("-g")
|
|
}
|
|
|
|
// Note: can't do this in [CacheTesting.configure] since task classes aren't accessible there.
|
|
tasks.withType(KonanCompileNativeBinary.class).configureEach {
|
|
dependsOn cacheTesting.buildCacheTask
|
|
extraOpts cacheTesting.compilerArgs
|
|
}
|
|
}
|
|
|
|
// Enable two-stage test compilation if the test_two_stage property is set.
|
|
ext.twoStageEnabled = project.hasProperty("test_two_stage")
|
|
|
|
tasks.withType(KonanCompileNativeBinary.class).configureEach {
|
|
enableTwoStageCompilation = twoStageEnabled
|
|
}
|
|
|
|
ext.isNoopGC = project.globalTestArgs.contains("-Xbinary=gc=noop") || project.globalTestArgs.contains("-Xgc=noop")
|
|
ext.isSTWMSGC = project.globalTestArgs.contains("-Xbinary=gc=stwms") || project.globalTestArgs.contains("-Xgc=stms")
|
|
ext.isAggressiveGC = project.globalTestArgs.contains("-Xbinary=gcSchedulerType=aggressive")
|
|
ext.runtimeAssertionsPanic = false
|
|
|
|
// TODO: It also makes sense to test -g without asserts, and also to test -opt with asserts.
|
|
if (project.globalTestArgs.contains("-g") && (cacheTesting == null)) {
|
|
tasks.withType(KonanCompileNativeBinary.class).configureEach {
|
|
extraOpts "-Xbinary=runtimeAssertionsMode=panic"
|
|
}
|
|
ext.runtimeAssertionsPanic = true
|
|
}
|
|
|
|
tasks.withType(KonanCompileNativeBinary).configureEach {
|
|
extraOpts "-XXLanguage:+ImplicitSignedToUnsignedIntegerConversion"
|
|
extraOpts "-opt-in=kotlinx.cinterop.ExperimentalForeignApi"
|
|
}
|
|
|
|
allprojects {
|
|
// Root directories for test output (logs, compiled files, statistics etc). Only single path must be in each set.
|
|
// backend.native/tests
|
|
ext.testOutputLocal = rootProject.file("$testOutputRoot/local")
|
|
|
|
// backend.native/tests/external
|
|
ext.testOutputExternal = rootProject.file("$testOutputRoot/external")
|
|
|
|
// backend.native/tests/framework
|
|
ext.testOutputFramework = rootProject.file("$testOutputRoot/framework")
|
|
|
|
ext.testOutputFileCheck = rootProject.file("$testOutputRoot/filecheck")
|
|
}
|
|
testOutputExternal.mkdirs()
|
|
|
|
konanArtifacts {
|
|
library('baseTestClass', targets: [target]) {
|
|
srcFiles 'testing/library.kt'
|
|
}
|
|
UtilsKt.dependsOnDist(UtilsKt.findKonanBuildTask(project, "baseTestClass", target))
|
|
}
|
|
|
|
void konanc(String[] args) {
|
|
String kotlincNative = PlatformInfo.isWindows() ? "kotlinc-native.bat" : "kotlinc-native"
|
|
String allArgs = args.join(" ")
|
|
String commandWithArguments = "$kotlinNativeDist/bin/$kotlincNative $allArgs"
|
|
|
|
println(commandWithArguments)
|
|
|
|
Process process = commandWithArguments.execute()
|
|
int exitCode = process.waitFor()
|
|
|
|
if (exitCode != 0) {
|
|
String stdOut = IOGroovyMethods.getText(process.inputStream)
|
|
String stdErr = IOGroovyMethods.getText(process.errorStream)
|
|
|
|
StringBuilder builder = new StringBuilder()
|
|
builder.append("Error during execution of the command: $commandWithArguments\n")
|
|
builder.append("exitCode = $exitCode\n")
|
|
builder.append("=== STDOUT: BEGIN ===\n")
|
|
if (!stdOut.isEmpty()) {
|
|
builder.append(stdOut)
|
|
if (!stdOut.endsWith("\n")) builder.append("\n")
|
|
}
|
|
builder.append("=== STDOUT: END ===\n")
|
|
builder.append("=== STDERR: BEGIN ===\n")
|
|
if (!stdErr.isEmpty()) {
|
|
builder.append(stdErr)
|
|
if (!stdErr.endsWith("\n")) builder.append("\n")
|
|
}
|
|
builder.append("=== STDERR: END ===\n")
|
|
|
|
throw new GradleException(builder.toString())
|
|
}
|
|
}
|
|
|
|
tasks.named("clean", Delete.class) {
|
|
doLast {
|
|
delete(project(":kotlin-native").file(testOutputRoot))
|
|
}
|
|
}
|
|
|
|
tasks.named("run") {
|
|
dependsOn(tasks.withType(KonanTest).matching { it.enabled })
|
|
// Add framework tests
|
|
dependsOn(tasks.withType(FrameworkTest).matching { it.enabled })
|
|
dependsOn(tasks.withType(FileCheckTest).matching { it.enabled })
|
|
dependsOn(tasks.withType(KonanTest).matching { it.enabled })
|
|
// Add framework tests
|
|
dependsOn(tasks.withType(FrameworkTest).matching { it.enabled })
|
|
// Add regular gradle test tasks
|
|
dependsOn(tasks.withType(Test).matching { it.enabled })
|
|
dependsOn(tasks.withType(FileCheckTest).matching { it.enabled })
|
|
dependsOn(":kotlin-native:Interop:Indexer:check")
|
|
dependsOn(":kotlin-native:Interop:StubGenerator:check")
|
|
dependsOn(":native:kotlin-native-utils:check")
|
|
dependsOn(":native:objcexport-header-generator:check")
|
|
dependsOn(":kotlin-native:backend.native:check")
|
|
}
|
|
|
|
// Was a subset of tests.
|
|
tasks.register("sanity") {
|
|
dependsOn("run")
|
|
}
|
|
|
|
boolean isExcluded(String dir) {
|
|
// List of tests that fail due to unresolved compiler bugs
|
|
def excluded = [ ]
|
|
|
|
boolean result = false
|
|
excluded.forEach {
|
|
if (dir.endsWith(it.replace("/", File.separator))) {
|
|
result = true
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
/**
|
|
* Creates a task for a standalone test. Configures runner and adds building task.
|
|
*/
|
|
Task standaloneTest(String name, Closure configureClosure) {
|
|
return KotlinNativeTestKt.createTest(project, name, KonanStandaloneTest) { task ->
|
|
task.configure(configureClosure)
|
|
if (task.enabled) {
|
|
konanArtifacts {
|
|
program(name, targets: [target.name]) {
|
|
baseDir "$testOutputLocal/$name"
|
|
srcFiles task.getSources()
|
|
extraOpts task.flags
|
|
extraOpts project.globalTestArgs
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates a task for a dynamic test. Configures runner and adds library and test build tasks.
|
|
*/
|
|
Task dynamicTest(String name, Closure<KonanDynamicTest> configureClosure) {
|
|
return KotlinNativeTestKt.createTest(project, name, KonanDynamicTest) { KonanDynamicTest task ->
|
|
task.configure(configureClosure)
|
|
if (task.enabled) {
|
|
konanArtifacts {
|
|
def targetName = target.name
|
|
def lib = task.interop
|
|
if (lib != null) {
|
|
UtilsKt.dependsOnKonanBuildingTask(task, lib, target)
|
|
}
|
|
dynamic(name, targets: [targetName]) {
|
|
if (lib != null) {
|
|
libraries {
|
|
artifact lib
|
|
}
|
|
}
|
|
srcFiles task.getSources()
|
|
baseDir "$testOutputLocal/$name"
|
|
extraOpts task.flags
|
|
extraOpts project.globalTestArgs
|
|
if (targetName == "mingw_x64" || targetName == "mingw_x86") {
|
|
extraOpts "-linker-option", "-Wl,--out-implib,$testOutputLocal/$name/$targetName/${name}.dll.a"
|
|
}
|
|
}
|
|
}
|
|
def buildTask = UtilsKt.findKonanBuildTask(project, name, target)
|
|
UtilsKt.dependsOnDist(buildTask)
|
|
task.dependsOn(nativeDependencies.llvmDependency)
|
|
task.dependsOn(nativeDependencies.targetDependency(target))
|
|
}
|
|
}
|
|
}
|
|
|
|
// This test checks object layout can't be done in
|
|
// KonanLocalTest paradigm
|
|
//tasks.register("constructor", UnitKonanTest) {
|
|
// source = "codegen/object/constructor.kt"
|
|
//}
|
|
|
|
standaloneTest("runtime_basic_init") {
|
|
source = "runtime/basic/init.kt"
|
|
expectedExitStatus = 0
|
|
}
|
|
|
|
standaloneTest("cleaner_basic") {
|
|
enabled = !isNoopGC
|
|
source = "runtime/basic/cleaner_basic.kt"
|
|
flags = ['-tr', '-opt-in=kotlin.native.internal.InternalForKotlinNative']
|
|
}
|
|
|
|
standaloneTest("cleaner_workers") {
|
|
enabled = !isNoopGC
|
|
source = "runtime/basic/cleaner_workers.kt"
|
|
flags = ['-tr', '-opt-in=kotlin.native.internal.InternalForKotlinNative']
|
|
}
|
|
|
|
standaloneTest("cleaner_in_main_with_checker") {
|
|
enabled = !isNoopGC
|
|
source = "runtime/basic/cleaner_in_main_with_checker.kt"
|
|
useGoldenData = true
|
|
}
|
|
|
|
standaloneTest("cleaner_in_main_without_checker") {
|
|
source = "runtime/basic/cleaner_in_main_without_checker.kt"
|
|
useGoldenData = true
|
|
}
|
|
|
|
standaloneTest("cleaner_leak_without_checker") {
|
|
source = "runtime/basic/cleaner_leak_without_checker.kt"
|
|
useGoldenData = true
|
|
}
|
|
|
|
standaloneTest("cleaner_leak_with_checker") {
|
|
enabled = !isNoopGC
|
|
source = "runtime/basic/cleaner_leak_with_checker.kt"
|
|
expectedExitStatusChecker = { it != 0 }
|
|
outputChecker = { s -> (s =~ /Cleaner (0x)?[0-9a-fA-F]+ was disposed during program exit/).find() }
|
|
}
|
|
|
|
standaloneTest("cleaner_in_tls_main_without_checker") {
|
|
source = "runtime/basic/cleaner_in_tls_main_without_checker.kt"
|
|
}
|
|
|
|
standaloneTest("cleaner_in_tls_main_with_checker") {
|
|
enabled = !isNoopGC
|
|
source = "runtime/basic/cleaner_in_tls_main_with_checker.kt"
|
|
expectedExitStatusChecker = { it != 0 }
|
|
outputChecker = { s -> (s =~ /Cleaner (0x)?[0-9a-fA-F]+ was disposed during program exit/).find() }
|
|
}
|
|
|
|
standaloneTest("cleaner_in_tls_worker") {
|
|
enabled = !isNoopGC
|
|
source = "runtime/basic/cleaner_in_tls_worker.kt"
|
|
flags = ['-opt-in=kotlin.native.internal.InternalForKotlinNative']
|
|
}
|
|
|
|
standaloneTest('logging') {
|
|
outputChecker = { out ->
|
|
out.toLowerCase().contains("[logging]") && // loging reports configured log levels on info level
|
|
out.toLowerCase().contains("logging = debug") &&
|
|
out.toLowerCase().contains("gc = info") &&
|
|
out.toLowerCase().contains("mm = warning") &&
|
|
out.toLowerCase().contains("tls = error") &&
|
|
out.toLowerCase().contains("[gc]") // gc reports initialization on info level
|
|
}
|
|
source = "runtime/basic/logging.kt"
|
|
flags = ['-Xruntime-logs=gc=info,mm=warning,tls=error,logging=debug']
|
|
}
|
|
|
|
standaloneTest('logging_invalid') {
|
|
outputChecker = { it.isEmpty() }
|
|
source = "runtime/basic/logging.kt"
|
|
flags = ['-Xruntime-logs=invalid=unknown,logging=debug']
|
|
}
|
|
|
|
standaloneTest('logging_override') {
|
|
outputChecker = { it.isEmpty() }
|
|
source = "runtime/basic/logging.kt"
|
|
flags = ['-Xruntime-logs=logging=info,logging=debug,logging=none']
|
|
}
|
|
|
|
standaloneTest("worker_bound_reference0") {
|
|
source = "runtime/concurrent/worker_bound_reference0.kt"
|
|
flags = ['-tr']
|
|
|
|
if (isNoopGC) {
|
|
def exclude = [
|
|
"*.testCollect",
|
|
"*.testCollectFrozen",
|
|
"*.testCollectInWorkerFrozen",
|
|
"*.collectCyclicGarbage",
|
|
"*.collectCyclicGarbageWithAtomicsFrozen",
|
|
"*.collectCrossThreadCyclicGarbageWithAtomicsFrozen"
|
|
]
|
|
arguments += ["--ktest_filter=*-${exclude.join(":")}"]
|
|
}
|
|
}
|
|
|
|
// This tests changes main thread worker queue state, so better be executed alone.
|
|
standaloneTest("worker5") {
|
|
useGoldenData = true
|
|
source = "runtime/workers/worker5.kt"
|
|
}
|
|
|
|
tasks.register("worker10", KonanLocalTest) {
|
|
enabled = !isNoopGC
|
|
useGoldenData = true
|
|
source = "runtime/workers/worker10.kt"
|
|
}
|
|
|
|
standaloneTest("worker_exceptions") {
|
|
flags = ["-tr", "-Xworker-exception-handling=use-hook"]
|
|
outputChecker = {
|
|
!it.contains("testExecuteAfterStartQuiet error") && it.contains("testExecuteStart error") && !it.contains("testExecuteStartQuiet error")
|
|
}
|
|
source = "runtime/workers/worker_exceptions.kt"
|
|
}
|
|
|
|
standaloneTest("worker_exceptions_legacy") {
|
|
flags = ["-tr", "-Xworker-exception-handling=legacy"]
|
|
outputChecker = {
|
|
it.contains("testExecuteAfterStartLegacy error") && it.contains("testExecuteStartLegacy error")
|
|
}
|
|
source = "runtime/workers/worker_exceptions_legacy.kt"
|
|
}
|
|
|
|
standaloneTest("worker_exceptions_terminate") {
|
|
flags = ["-Xworker-exception-handling=use-hook"]
|
|
expectedExitStatusChecker = { it != 0 }
|
|
outputChecker = {
|
|
it.contains("some error") && !it.contains("Will not happen")
|
|
}
|
|
source = "runtime/workers/worker_exceptions_terminate.kt"
|
|
}
|
|
|
|
standaloneTest("worker_exceptions_terminate_legacy") {
|
|
flags = ["-Xworker-exception-handling=legacy"]
|
|
outputChecker = {
|
|
it.contains("some error") && it.contains("Will not happen")
|
|
}
|
|
source = "runtime/workers/worker_exceptions_terminate.kt"
|
|
}
|
|
|
|
standaloneTest("worker_exceptions_terminate_hook") {
|
|
flags = ["-Xworker-exception-handling=use-hook"]
|
|
outputChecker = {
|
|
it.contains("hook called") && !it.contains("some error") && it.contains("Will happen")
|
|
}
|
|
source = "runtime/workers/worker_exceptions_terminate_hook.kt"
|
|
}
|
|
|
|
standaloneTest("worker_exceptions_terminate_hook_legacy") {
|
|
flags = ["-Xworker-exception-handling=legacy"]
|
|
outputChecker = {
|
|
!it.contains("hook called") && it.contains("some error") && it.contains("Will happen")
|
|
}
|
|
source = "runtime/workers/worker_exceptions_terminate_hook.kt"
|
|
}
|
|
|
|
standaloneTest("worker_exceptions_terminate_current") {
|
|
flags = ["-Xworker-exception-handling=use-hook"]
|
|
expectedExitStatusChecker = { it != 0 }
|
|
outputChecker = {
|
|
it.contains("some error") && !it.contains("Will not happen")
|
|
}
|
|
source = "runtime/workers/worker_exceptions_terminate_current.kt"
|
|
}
|
|
|
|
standaloneTest("worker_exceptions_terminate_current_legacy") {
|
|
flags = ["-Xworker-exception-handling=legacy"]
|
|
outputChecker = {
|
|
it.contains("some error") && it.contains("Will not happen")
|
|
}
|
|
source = "runtime/workers/worker_exceptions_terminate_current.kt"
|
|
}
|
|
|
|
standaloneTest("worker_exceptions_terminate_hook_current") {
|
|
flags = ["-Xworker-exception-handling=use-hook"]
|
|
outputChecker = {
|
|
it.contains("hook called") && !it.contains("some error") && it.contains("Will happen")
|
|
}
|
|
source = "runtime/workers/worker_exceptions_terminate_hook_current.kt"
|
|
}
|
|
|
|
standaloneTest("worker_exceptions_terminate_hook_current_legacy") {
|
|
flags = ["-Xworker-exception-handling=legacy"]
|
|
outputChecker = {
|
|
!it.contains("hook called") && it.contains("some error") && it.contains("Will happen")
|
|
}
|
|
source = "runtime/workers/worker_exceptions_terminate_hook_current.kt"
|
|
}
|
|
|
|
standaloneTest("worker_threadlocal_no_leak") {
|
|
source = "runtime/workers/worker_threadlocal_no_leak.kt"
|
|
}
|
|
|
|
standaloneTest("freeze_disabled") {
|
|
enabled = !isNoopGC
|
|
flags = ["-tr"]
|
|
source = "runtime/workers/freeze_disabled.kt"
|
|
testLogger = KonanTest.Logger.SILENT
|
|
}
|
|
|
|
standaloneTest("lazy2") {
|
|
useGoldenData = true
|
|
source = "runtime/workers/lazy2.kt"
|
|
}
|
|
|
|
standaloneTest("lazy3") {
|
|
enabled = !isNoopGC
|
|
source = "runtime/workers/lazy3.kt"
|
|
}
|
|
|
|
tasks.register("mutableData1", KonanLocalTest) {
|
|
source = "runtime/workers/mutableData1.kt"
|
|
}
|
|
|
|
tasks.register("enumIdentity", KonanLocalTest) {
|
|
useGoldenData = true
|
|
source = "runtime/workers/enum_identity.kt"
|
|
}
|
|
|
|
standaloneTest("leakWorker") {
|
|
source = "runtime/workers/leak_worker.kt"
|
|
expectedExitStatusChecker = { it != 0 }
|
|
outputChecker = { s -> s.contains("Unfinished workers detected, 1 workers leaked!") }
|
|
}
|
|
|
|
standaloneTest("leakMemoryWithWorkerTermination") {
|
|
source = "runtime/workers/leak_memory_with_worker_termination.kt"
|
|
}
|
|
|
|
standaloneTest("initializers_testInfrastructure") {
|
|
source = "codegen/initializers/testInfrastructure.kt"
|
|
flags = ["-tr"]
|
|
}
|
|
|
|
tasks.register("sanity_assertions_enabled_for_local_tests", KonanLocalTest) {
|
|
source = "sanity/assertions_enabled_for_local_tests.kt"
|
|
}
|
|
|
|
tasks.register("immutable_binary_blob_in_lambda", KonanLocalTest) {
|
|
source = "lower/immutable_blob_in_lambda.kt"
|
|
useGoldenData = true
|
|
}
|
|
|
|
tasks.register("abstract_super", KonanLocalTest) {
|
|
source = "datagen/rtti/abstract_super.kt"
|
|
}
|
|
|
|
tasks.register("vtable1", KonanLocalTest) {
|
|
source = "datagen/rtti/vtable1.kt"
|
|
}
|
|
|
|
tasks.register("vtable_any", KonanLocalTest) {
|
|
source = "datagen/rtti/vtable_any.kt"
|
|
useGoldenData = true
|
|
}
|
|
|
|
tasks.register("empty_string", KonanLocalTest) {
|
|
useGoldenData = true
|
|
source = "datagen/literals/empty_string.kt"
|
|
}
|
|
|
|
standaloneTest("link_default_libs") {
|
|
useGoldenData = true
|
|
source = "link/default/default.kt"
|
|
UtilsKt.dependsOnPlatformLibs(it)
|
|
}
|
|
|
|
standaloneTest("check_stacktrace_format_coresymbolication") {
|
|
disabled = !PlatformInfo.supportsCoreSymbolication(project) || project.globalTestArgs.contains('-opt')
|
|
flags = ['-g', '-Xbinary=sourceInfoType=coresymbolication']
|
|
arguments = ['coresymbolication']
|
|
source = "runtime/exceptions/check_stacktrace_format.kt"
|
|
}
|
|
|
|
standaloneTest("stack_trace_inline") {
|
|
disabled = !PlatformInfo.supportsCoreSymbolication(project) || project.globalTestArgs.contains('-opt')
|
|
flags = ['-g', '-Xg-generate-debug-trampoline=enable', '-Xbinary=sourceInfoType=coresymbolication']
|
|
source = "runtime/exceptions/stack_trace_inline.kt"
|
|
arguments = ['coresymbolication']
|
|
}
|
|
|
|
standaloneTest("kt-49240-stack-trace-completeness") {
|
|
disabled = !PlatformInfo.supportsExceptions(project) || project.globalTestArgs.contains('-opt')
|
|
source = "runtime/exceptions/kt-49240-stack-trace-completeness.kt"
|
|
}
|
|
|
|
standaloneTest("kt-37572") {
|
|
disabled = !PlatformInfo.supportsCoreSymbolication(project) || project.globalTestArgs.contains('-opt')
|
|
flags = ['-g', '-Xbinary=sourceInfoType=coresymbolication']
|
|
arguments = ['coresymbolication']
|
|
source = "runtime/exceptions/kt-37572.kt"
|
|
}
|
|
|
|
standaloneTest("check_stacktrace_format_libbacktrace") {
|
|
disabled = !PlatformInfo.supportsLibBacktrace(project)|| project.globalTestArgs.contains('-opt')
|
|
flags = ['-g', '-Xbinary=sourceInfoType=libbacktrace']
|
|
arguments = ['libbacktrace']
|
|
source = "runtime/exceptions/check_stacktrace_format.kt"
|
|
}
|
|
|
|
standaloneTest("stack_trace_inline_libbacktrace") {
|
|
disabled = !PlatformInfo.supportsLibBacktrace(project) || project.globalTestArgs.contains('-opt')
|
|
flags = ['-g', '-Xbinary=sourceInfoType=libbacktrace']
|
|
arguments = ['libbacktrace']
|
|
source = "runtime/exceptions/stack_trace_inline.kt"
|
|
}
|
|
|
|
standaloneTest("kt-37572-libbacktrace") {
|
|
disabled = !PlatformInfo.supportsLibBacktrace(project) || project.globalTestArgs.contains('-opt')
|
|
flags = ['-g', '-Xbinary=sourceInfoType=libbacktrace']
|
|
arguments = ['libbacktrace']
|
|
source = "runtime/exceptions/kt-37572.kt"
|
|
}
|
|
|
|
standaloneTest("except_constr_w_default") {
|
|
disabled = !PlatformInfo.supportsLibBacktrace(project) || project.globalTestArgs.contains('-opt')
|
|
flags = ['-g', '-Xbinary=sourceInfoType=libbacktrace']
|
|
source = "runtime/exceptions/except_constr_w_default.kt"
|
|
}
|
|
|
|
standaloneTest("throw_from_except_constr") {
|
|
disabled = !PlatformInfo.supportsLibBacktrace(project) || project.globalTestArgs.contains('-opt')
|
|
flags = ['-g', '-Xbinary=sourceInfoType=libbacktrace']
|
|
source = "runtime/exceptions/throw_from_except_constr.kt"
|
|
}
|
|
|
|
tasks.register("initializers6", KonanLocalTest) {
|
|
source = "runtime/basic/initializers6.kt"
|
|
}
|
|
|
|
tasks.register("memory_var1", KonanLocalTest) {
|
|
source = "runtime/memory/var1.kt"
|
|
}
|
|
|
|
tasks.register("memory_var2", KonanLocalTest) {
|
|
source = "runtime/memory/var2.kt"
|
|
}
|
|
|
|
tasks.register("memory_var3", KonanLocalTest) {
|
|
source = "runtime/memory/var3.kt"
|
|
}
|
|
|
|
tasks.register("memory_var4", KonanLocalTest) {
|
|
source = "runtime/memory/var4.kt"
|
|
}
|
|
|
|
tasks.register("memory_throw_cleanup", KonanLocalTest) {
|
|
useGoldenData = true
|
|
source = "runtime/memory/throw_cleanup.kt"
|
|
}
|
|
|
|
tasks.register("memory_escape0", KonanLocalTest) {
|
|
source = "runtime/memory/escape0.kt"
|
|
}
|
|
|
|
tasks.register("memory_escape1", KonanLocalTest) {
|
|
useGoldenData = true
|
|
source = "runtime/memory/escape1.kt"
|
|
}
|
|
|
|
tasks.register("memory_cycles0", KonanLocalTest) {
|
|
useGoldenData = true
|
|
source = "runtime/memory/cycles0.kt"
|
|
}
|
|
|
|
tasks.register("memory_cycles1", KonanLocalTest) {
|
|
enabled = !isNoopGC
|
|
source = "runtime/memory/cycles1.kt"
|
|
}
|
|
|
|
tasks.register("memory_basic0", KonanLocalTest) {
|
|
source = "runtime/memory/basic0.kt"
|
|
}
|
|
|
|
tasks.register("memory_escape2", KonanLocalTest) {
|
|
useGoldenData = true
|
|
source = "runtime/memory/escape2.kt"
|
|
}
|
|
|
|
tasks.register("memory_weak0", KonanLocalTest) {
|
|
enabled = !isNoopGC
|
|
useGoldenData = true
|
|
source = "runtime/memory/weak0.kt"
|
|
}
|
|
|
|
tasks.register("memory_weak1", KonanLocalTest) {
|
|
useGoldenData = true
|
|
source = "runtime/memory/weak1.kt"
|
|
}
|
|
|
|
standaloneTest("memory_only_gc") {
|
|
source = "runtime/memory/only_gc.kt"
|
|
}
|
|
|
|
standaloneTest("leakMemory") {
|
|
source = "runtime/memory/leak_memory.kt"
|
|
}
|
|
|
|
standaloneTest("leakMemoryWithTestRunner") {
|
|
source = "runtime/memory/leak_memory_test_runner.kt"
|
|
flags = ['-tr']
|
|
}
|
|
|
|
standaloneTest("gcStats") {
|
|
source = "runtime/memory/gcStats.kt"
|
|
flags = ['-tr', "-Xbinary=gcSchedulerType=disabled"]
|
|
enabled = !isNoopGC && !isAggressiveGC
|
|
}
|
|
|
|
standaloneTest("stress_gc_allocations") {
|
|
// TODO: Support obtaining peak RSS on more platforms.
|
|
enabled =
|
|
(project.testTarget != "watchos_arm32") &&
|
|
(project.testTarget != "watchos_arm64") &&
|
|
(project.testTarget != "watchos_x86") &&
|
|
(project.testTarget != "watchos_x64") &&
|
|
(project.testTarget != "watchos_simulator_arm64") &&
|
|
!isNoopGC && // Requires some GC.
|
|
!isAggressiveGC && // No need to check with aggressive GC at all
|
|
!runtimeAssertionsPanic // New allocator with assertions makes this test very slow.
|
|
source = "runtime/memory/stress_gc_allocations.kt"
|
|
flags = [
|
|
'-opt-in=kotlin.native.internal.InternalForKotlinNative', // MemoryUsageInfo is internal
|
|
'-Xdisable-phases=EscapeAnalysis', // The test checks GC, we need to allocate everything on the heap.
|
|
]
|
|
}
|
|
|
|
standaloneTest("array_out_of_memory") {
|
|
// This test allocs a large array that may make Linux
|
|
// kill any process inlcuding Gradle with OOM-killer
|
|
enabled = project.target.family != Family.LINUX
|
|
source = "runtime/memory/array_out_of_memory.kt"
|
|
flags = ['-tr']
|
|
switch(project.target.architecture) {
|
|
case Architecture.X64:
|
|
case Architecture.ARM64:
|
|
break;
|
|
case Architecture.X86:
|
|
case Architecture.ARM32:
|
|
case Architecture.MIPS32:
|
|
case Architecture.MIPSEL32:
|
|
case Architecture.WASM32:
|
|
expectedExitStatusChecker = { it != 0 }
|
|
outputChecker = { s -> s.contains("Out of memory trying to allocate") }
|
|
break;
|
|
}
|
|
}
|
|
|
|
tasks.register("vararg0", KonanLocalTest) {
|
|
source = "lower/vararg.kt"
|
|
}
|
|
|
|
tasks.register("vararg_of_literals", KonanLocalTest) {
|
|
enabled = false
|
|
useGoldenData = true
|
|
source = "lower/vararg_of_literals.kt"
|
|
}
|
|
|
|
standaloneTest('tailrec') {
|
|
disabled = isAggressiveGC // TODO: Investigate why too slow
|
|
useGoldenData = true
|
|
source = "lower/tailrec.kt"
|
|
flags = ['-XXLanguage:-ProhibitTailrecOnVirtualMember', '-e', 'lower.tailrec.main']
|
|
}
|
|
|
|
tasks.register("deserialized_inline0", KonanLocalTest) {
|
|
source = "serialization/deserialized_inline0.kt"
|
|
}
|
|
|
|
tasks.register("deserialized_listof0", KonanLocalTest) {
|
|
source = "serialization/deserialized_listof0.kt"
|
|
}
|
|
|
|
tasks.register("deserialized_fields", KonanLocalTest) {
|
|
source = "serialization/deserialized_fields.kt"
|
|
}
|
|
|
|
KotlinNativeTestKt.createTest(project, "kt39548", KonanStandaloneTest) { task ->
|
|
// Test infrastructure doesn't support generated source;
|
|
// workaround by specifying dummy source:
|
|
task.source = "does/not/exist/kt39548.dummy.kt"
|
|
task.enabled = PlatformInfo.isWindowsTarget(project)
|
|
|
|
if (task.enabled) {
|
|
def ktFile = project.layout.buildDirectory.file("kt39548/kt39548.kt").get().asFile
|
|
konanArtifacts {
|
|
program(name, targets: [target.name]) {
|
|
baseDir "$testOutputLocal/$name"
|
|
srcFiles ktFile.toString() // Generated by doBeforeBuild task.
|
|
extraOpts task.flags
|
|
extraOpts project.globalTestArgs
|
|
}
|
|
}
|
|
doBeforeBuild {
|
|
GenTestKT39548Kt.genTestKT39548(ktFile)
|
|
}
|
|
}
|
|
}
|
|
|
|
standaloneTest("serialized_no_typemap") {
|
|
source = "serialization/regression/no_type_map.kt"
|
|
useGoldenData = true
|
|
}
|
|
|
|
standaloneTest("testing_annotations") {
|
|
source = "testing/annotations.kt"
|
|
flags = ['-tr']
|
|
arguments = ['--ktest_logger=SIMPLE']
|
|
useGoldenData = true
|
|
}
|
|
|
|
standaloneTest("testing_assertions") {
|
|
source = "testing/assertions.kt"
|
|
flags = ['-tr']
|
|
expectedExitStatus = 0
|
|
}
|
|
|
|
standaloneTest("testing_custom_main") {
|
|
source = "testing/custom_main.kt"
|
|
flags = ['-tr', '-e', 'kotlin.test.tests.main']
|
|
arguments = ['--ktest_logger=SIMPLE', '--ktest_repeat=2']
|
|
useGoldenData = true
|
|
}
|
|
|
|
standaloneTest("testing_library_usage") {
|
|
def target = project.testTarget ?: 'host'
|
|
dependsOn konanArtifacts.baseTestClass.getByTarget(target)
|
|
def klib = konanArtifacts.baseTestClass.getArtifactByTarget(target)
|
|
source = 'testing/library_user.kt'
|
|
flags = ['-tr', '-e', 'main', '-l', klib.absolutePath]
|
|
arguments = ['--ktest_logger=SILENT']
|
|
}
|
|
|
|
class Filter {
|
|
List<String> positive
|
|
List<String> negative
|
|
List<String> expectedTests
|
|
|
|
Filter(List<String> positive, List<String> negative, List<String> expectedTests) {
|
|
this.positive = positive
|
|
this.negative = negative
|
|
this.expectedTests = expectedTests
|
|
}
|
|
|
|
List<String> args() {
|
|
List<String> result = []
|
|
if (positive != null && !positive.isEmpty()) {
|
|
result += "--ktest_gradle_filter=${asListOfPatterns(positive)}"
|
|
}
|
|
if (negative != null && !negative.isEmpty()) {
|
|
result += "--ktest_negative_gradle_filter=${asListOfPatterns(negative)}"
|
|
}
|
|
return result
|
|
}
|
|
|
|
static private String asListOfPatterns(List<String> input) {
|
|
return input.collect { "kotlin.test.tests.$it" }.join(",")
|
|
}
|
|
}
|
|
|
|
standaloneTest("testing_filters") {
|
|
source = "testing/filters.kt"
|
|
flags = ['-tr', '-ea']
|
|
def filters = [
|
|
new Filter(["A.foo1", "B", "FiltersKt.foo1"], [], ["A.foo1", "B.foo1", "B.foo2", "B.bar", "FiltersKt.foo1"]),
|
|
new Filter([], ["A.foo1", "B", "FiltersKt.foo1"], ["A.foo2", "A.bar", "FiltersKt.foo2", "FiltersKt.bar"]),
|
|
new Filter(["A", "FiltersKt"], ["A.foo1", "FiltersKt.foo1"], ["A.foo2", "A.bar", "FiltersKt.foo2", "FiltersKt.bar"]),
|
|
new Filter(["A.foo*", "B.*"], [], ["A.foo1", "A.foo2", "B.foo1", "B.foo2", "B.bar"]),
|
|
new Filter([], ["A.foo*", "B.*"], ["A.bar", "FiltersKt.foo1", "FiltersKt.foo2", "FiltersKt.bar"]),
|
|
new Filter(["*.foo*"], ["B"], ["A.foo1", "A.foo2", "FiltersKt.foo1", "FiltersKt.foo2"]),
|
|
new Filter(["A"], ["*.foo*"], ["A.bar"])
|
|
]
|
|
multiRuns = true
|
|
multiArguments = filters.collect { it.args() + '--ktest_logger=SIMPLE' }
|
|
outputChecker = { String output ->
|
|
// The first chunk is empty - drop it.
|
|
def outputs = output.split("Starting testing\n").drop(1)
|
|
if (outputs.size() != filters.size()) {
|
|
println("Incorrect number of test runs. Expected: ${filters.size()}, actual: ${outputs.size()}")
|
|
return false
|
|
}
|
|
|
|
// Check the correct set of tests was executed in each run.
|
|
for (int i = 0; i < outputs.size(); i++) {
|
|
def actualMessages = outputs[i].split('\n').findAll { it.startsWith("Passed: ") }
|
|
def expectedMessages = filters[i].expectedTests.collect { String test ->
|
|
def method = test.substring(test.lastIndexOf('.') + 1)
|
|
def suite = test.substring(0, test.lastIndexOf('.'))
|
|
"Passed: $method (kotlin.test.tests.$suite)".toString()
|
|
}
|
|
|
|
if (actualMessages.size() != expectedMessages.size()) {
|
|
println("Incorrect number of tests executed for filters[$i]. Expected: ${expectedMessages.size()}. Actual: ${actualMessages.size()}")
|
|
return false
|
|
}
|
|
|
|
for (message in expectedMessages) {
|
|
if (!actualMessages.contains(message)) {
|
|
println("Test run output for filters[$i] doesn't contain the expected message '$message'")
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
}
|
|
|
|
standaloneTest("testing_filtered_suites") {
|
|
source = "testing/filtered_suites.kt"
|
|
flags = ["-tr", "-ea"]
|
|
|
|
def filters = [
|
|
["Filtered_suitesKt.*"], // filter out a class.
|
|
["A.*"], // filter out a top-level suite.
|
|
["*.common"], // run a test from all suites -> all hooks executed.
|
|
["Ignored.*"], // an ignored suite -> no hooks executed.
|
|
["A.ignored"] // a suite with only ignored tests -> no hooks executed.
|
|
]
|
|
def expectedHooks = [
|
|
["Filtered_suitesKt.before", "Filtered_suitesKt.after"],
|
|
["A.before", "A.after"],
|
|
["A.before", "A.after", "Filtered_suitesKt.before", "Filtered_suitesKt.after"],
|
|
[],
|
|
[]
|
|
]
|
|
|
|
multiRuns = true
|
|
multiArguments = filters.collect {
|
|
def filter = it.collect { "kotlin.test.tests.$it" }.join(",")
|
|
["--ktest_gradle_filter=$filter", "--ktest_logger=SIMPLE"]
|
|
}
|
|
outputChecker = { String output ->
|
|
// The first chunk is empty - drop it.
|
|
def outputs = output.split("Starting testing\n").drop(1)
|
|
if (outputs.size() != expectedHooks.size()) {
|
|
println("Incorrect number of test runs. Expected: ${expectedHooks.size()}, actual: ${outputs.size()}")
|
|
return false
|
|
}
|
|
|
|
// Check the correct set of hooks was executed on each run.
|
|
for (int i = 0; i < outputs.size(); i++) {
|
|
def actual = outputs[i].split('\n')
|
|
.findAll { it.startsWith("Hook:") }
|
|
.collect { it.replace("Hook: ", "") }
|
|
def expected = expectedHooks[i]
|
|
|
|
if (actual.size() != expected.size()) {
|
|
println("Incorrect number of executed hooks for run #$i. Expected: ${expected.size()}. Actual: ${actual.size()}")
|
|
println("Expected hooks: $expected")
|
|
println("Actual hooks: $actual")
|
|
return false
|
|
}
|
|
|
|
for (expectedHook in expected) {
|
|
if (!actual.contains(expectedHook)) {
|
|
println("Expected hook wasn't executed for run #$i: $expectedHook")
|
|
println("Expected hooks: $expected")
|
|
println("Actual hooks: $actual")
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
}
|
|
|
|
// Check that stacktraces and ignored suite are correctly reported in the TC logger.
|
|
standaloneTest("testing_stacktrace") {
|
|
source = "testing/stacktrace.kt"
|
|
flags = ['-tr', '-ea']
|
|
arguments = ["--ktest_logger=TEAMCITY", "--ktest_no_exit_code"]
|
|
// This test prints TeamCity service messages about failed test causing false negative failure at CI.
|
|
// So we need to suppress printing these messages to stdout.
|
|
// printOutput = false
|
|
outputChecker = { String output ->
|
|
def ignoredOutput = """\
|
|
|##teamcity[testSuiteStarted name='kotlin.test.tests.Ignored' locationHint='ktest:suite://kotlin.test.tests.Ignored']
|
|
|##teamcity[testIgnored name='foo']
|
|
|##teamcity[testSuiteFinished name='kotlin.test.tests.Ignored']""".stripMargin()
|
|
def failedOutput = """\
|
|
|##teamcity[testSuiteStarted name='kotlin.test.tests.Failed' locationHint='ktest:suite://kotlin.test.tests.Failed']
|
|
|##teamcity[testStarted name='bar' locationHint='ktest:test://kotlin.test.tests.Failed.bar']
|
|
|##teamcity[testFailed name='bar' message='Bar' details='kotlin.Exception: Bar|n""".stripMargin()
|
|
|
|
def shownInnerException = output.readLines()
|
|
.find { it.startsWith("##teamcity[testFailed name='bar'") }
|
|
?.contains("Caused by: kotlin.Exception: Baz") ?: false
|
|
|
|
return output.contains(ignoredOutput) && output.contains(failedOutput) && shownInnerException
|
|
}
|
|
}
|
|
|
|
// Just check that the driver is able to produce runnable binaries.
|
|
tasks.register("driver0", KonanDriverTest) {
|
|
disabled = isAggressiveGC // No need to test with different GC schedulers
|
|
useGoldenData = true
|
|
source = "runtime/basic/driver0.kt"
|
|
}
|
|
|
|
tasks.register("driver_opt", KonanDriverTest) {
|
|
disabled = (cacheTesting != null) // Cache is not compatible with -opt.
|
|
|| isAggressiveGC // No need to test with different GC schedulers
|
|
useGoldenData = true
|
|
source = "runtime/basic/driver_opt.kt"
|
|
flags = ["-opt"]
|
|
}
|
|
|
|
def generateWithSpaceDefFile() {
|
|
def buildDirectory = project.layout.buildDirectory.get().asFile
|
|
def mapOption = "--Map \"$buildDirectory/cutom map.map\""
|
|
if (PlatformInfo.isAppleTarget(project)) {
|
|
mapOption = "-map \"$buildDirectory/cutom map.map\""
|
|
} else if (PlatformInfo.isWindowsTarget(project)) {
|
|
mapOption = "\"-Wl,--Map,$buildDirectory/cutom map.map\""
|
|
}
|
|
|
|
buildDirectory.mkdirs()
|
|
def file = new File("${buildDirectory}/withSpaces.def")
|
|
file.write """
|
|
headers = stdio.h "${projectDir}/interop/basics/custom headers/custom.h"
|
|
linkerOpts = $mapOption
|
|
---
|
|
|
|
int customCompare(const char* str1, const char* str2) {
|
|
return custom_strcmp(str1, str2);
|
|
}
|
|
"""
|
|
return file.absolutePath
|
|
}
|
|
|
|
// A helper method to create interop artifacts
|
|
void createInterop(String name, Closure conf) {
|
|
konanArtifacts {
|
|
interop(name, targets: [target.name]) {
|
|
dependsOn(nativeDependencies.llvmDependency)
|
|
dependsOn(nativeDependencies.targetDependency(target))
|
|
conf(it)
|
|
noDefaultLibs(true)
|
|
noEndorsedLibs(true)
|
|
baseDir "$testOutputLocal/$name"
|
|
}
|
|
}
|
|
}
|
|
|
|
createInterop("sockets") {
|
|
it.defFile 'interop/basics/sockets.def'
|
|
}
|
|
|
|
createInterop("embedStaticLibraries") {
|
|
it.defFile 'interop/embedStaticLibraries/embedStaticLibraries.def'
|
|
it.headers "$projectDir/interop/embedStaticLibraries/embedStaticLibraries.h"
|
|
|
|
// Note: also hardcoded in def file.
|
|
final File libDir = project.layout.buildDirectory.dir("embedStaticLibraries").get().asFile
|
|
|
|
it.getByTarget(target.name).configure {
|
|
doFirst {
|
|
1.upto(4) {
|
|
UtilsKt.buildStaticLibrary(
|
|
project,
|
|
[file("$projectDir/interop/embedStaticLibraries/${it}.c")],
|
|
file("$libDir/${it}.a"),
|
|
file("$libDir/${it}.objs"),
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
it.extraOpts '-staticLibrary', "1.a"
|
|
it.extraOpts '-staticLibrary', "2.a"
|
|
}
|
|
|
|
createInterop("kt43502") {
|
|
it.defFile 'interop/kt43502/kt43502.def'
|
|
it.headers "$projectDir/interop/kt43502/kt43502.h"
|
|
// Note: also hardcoded in def file.
|
|
final File libDir = project.layout.buildDirectory.dir("kt43502").get().asFile
|
|
// Construct library that contains actual symbol definition.
|
|
it.getByTarget(target.name).configure {
|
|
doFirst {
|
|
UtilsKt.buildStaticLibrary(
|
|
project,
|
|
[file("$projectDir/interop/kt43502/kt43502.c")],
|
|
file("$libDir/kt43502.a"),
|
|
file("$libDir/kt43502.objs"),
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
createInterop("leakMemoryWithRunningThread") {
|
|
it.defFile 'interop/leakMemoryWithRunningThread/leakMemory.def'
|
|
it.headers "$projectDir/interop/leakMemoryWithRunningThread/leakMemory.h"
|
|
it.extraOpts "-Xcompile-source", "$projectDir/interop/leakMemoryWithRunningThread/leakMemory.cpp"
|
|
}
|
|
|
|
createInterop("cppClass") {
|
|
it.defFile 'interop/cpp/cppClass.def'
|
|
}
|
|
|
|
createInterop("cppTypes") {
|
|
it.defFile 'interop/cpp/types.def'
|
|
}
|
|
|
|
createInterop("cppSkia") {
|
|
it.defFile 'interop/cpp/skia.def'
|
|
}
|
|
|
|
createInterop("cppSkiaSignature") {
|
|
it.defFile 'interop/cpp/skiaSignature.def'
|
|
}
|
|
|
|
createInterop("threadStates") {
|
|
it.defFile "interop/threadStates/threadStates.def"
|
|
it.extraOpts "-Xcompile-source", "$projectDir/interop/threadStates/threadStates.cpp"
|
|
}
|
|
|
|
createInterop("workerSignals") {
|
|
it.defFile "interop/workerSignals/workerSignals.def"
|
|
it.headers "$projectDir/interop/workerSignals/workerSignals.h"
|
|
it.extraOpts "-Xcompile-source", "$projectDir/interop/workerSignals/workerSignals.cpp"
|
|
}
|
|
|
|
createInterop("cForwardDeclarationsTwoLibs1") {
|
|
it.defFile "interop/forwardDeclarationsTwoLibs/cForwardDeclarationsTwoLibs1.def"
|
|
}
|
|
|
|
createInterop("cForwardDeclarationsTwoLibs2") {
|
|
it.defFile "interop/forwardDeclarationsTwoLibs/cForwardDeclarationsTwoLibs2.def"
|
|
}
|
|
|
|
if (PlatformInfo.isAppleTarget(project)) {
|
|
createInterop("forwardDeclarationsCastA") {
|
|
it.defFile "interop/forwardDeclarationsCast/a.def"
|
|
}
|
|
|
|
createInterop("forwardDeclarationsCastB") {
|
|
it.defFile "interop/forwardDeclarationsCast/b.def"
|
|
it.headers "$projectDir/interop/forwardDeclarationsCast/b.h"
|
|
it.extraOpts "-Xcompile-source", "$projectDir/interop/forwardDeclarationsCast/b.m"
|
|
}
|
|
|
|
createInterop("objcSmoke") {
|
|
it.defFile 'interop/objc/objcSmoke.def'
|
|
it.headers "$projectDir/interop/objc/smoke.h"
|
|
}
|
|
|
|
createInterop("objcTests") {
|
|
it.defFile 'interop/objc/objcTests.def'
|
|
it.headers fileTree("$projectDir/interop/objc/tests") { include '**/*.h' }
|
|
}
|
|
|
|
createInterop("objcMisc") {
|
|
it.defFile 'interop/objc_with_initializer/objc_misc.def'
|
|
it.headers "$projectDir/interop/objc_with_initializer/objc_misc.h"
|
|
}
|
|
|
|
createInterop("objcMessaging") {
|
|
it.defFile 'interop/objc/msg_send/messaging.def'
|
|
it.headers "$projectDir/interop/objc/msg_send/messaging.h"
|
|
}
|
|
|
|
createInterop("objcDirect") {
|
|
it.defFile 'interop/objc/direct/direct.def'
|
|
it.headers "$projectDir/interop/objc/direct/direct.h"
|
|
it.extraOpts "-Xcompile-source", "$projectDir/interop/objc/direct/direct.m", "-Xsource-compiler-option", "-DNS_FORMAT_ARGUMENT(A)="
|
|
it.compilerOpts '-DNS_FORMAT_ARGUMENT(A)='
|
|
}
|
|
|
|
createInterop("foreignException") {
|
|
it.defFile 'interop/objc/foreignException/objc_wrap.def'
|
|
it.headers "$projectDir/interop/objc/foreignException/objc_wrap.h"
|
|
}
|
|
|
|
createInterop("foreignExceptionMode_default") {
|
|
it.defFile 'interop/objc/foreignException/objcExceptionMode.def'
|
|
it.headers "$projectDir/interop/objc/foreignException/objc_wrap.h"
|
|
}
|
|
|
|
createInterop("foreignExceptionMode_wrap") {
|
|
it.defFile 'interop/objc/foreignException/objcExceptionMode.def'
|
|
it.headers "$projectDir/interop/objc/foreignException/objc_wrap.h"
|
|
it.extraOpts '-Xforeign-exception-mode', "objc-wrap"
|
|
}
|
|
|
|
createInterop("objcGh3343") {
|
|
it.defFile 'framework/gh3343/objclib.def'
|
|
it.headers "$projectDir/framework/gh3343/objclib.h"
|
|
it.linkerOpts "-lobjcgh3343"
|
|
}
|
|
createInterop("objc_illegal_sharing_with_weak") {
|
|
it.defFile 'interop/objc/illegal_sharing_with_weak/objclib.def'
|
|
it.headers "$projectDir/interop/objc/illegal_sharing_with_weak/objclib.h"
|
|
}
|
|
createInterop("objcKt43517") {
|
|
it.defFile 'framework/kt43517/kt43517.def'
|
|
}
|
|
createInterop("objc_kt42172") {
|
|
it.defFile 'interop/objc/kt42172/objclib.def'
|
|
it.headers "$projectDir/interop/objc/kt42172/objclib.h"
|
|
}
|
|
createInterop("objc_kt48816") {
|
|
it.defFile 'interop/objc/kt48816/objclib.def'
|
|
it.headers "$projectDir/interop/objc/kt48816/objclib.h"
|
|
}
|
|
createInterop("objc_kt55938") {
|
|
it.defFile 'interop/objc/kt55938/objclib.def'
|
|
it.headers "$projectDir/interop/objc/kt55938/objclib.h"
|
|
}
|
|
|
|
createInterop("kt49034_struct") {
|
|
it.defFile 'interop/objc/kt49034/struct/kt49034.def'
|
|
it.headers "$projectDir/interop/objc/kt49034/struct/kt49034.h"
|
|
it.extraOpts "-Xcompile-source", "$projectDir/interop/objc/kt49034/struct/impl.c"
|
|
}
|
|
|
|
createInterop("kt49034_objcclass") {
|
|
it.defFile 'interop/objc/kt49034/objcclass/kt49034.def'
|
|
it.headers "$projectDir/interop/objc/kt49034/objcclass/kt49034.h"
|
|
}
|
|
createInterop("kt49034_objcprotocol") {
|
|
it.defFile 'interop/objc/kt49034/objcprotocol/kt49034.def'
|
|
it.headers "$projectDir/interop/objc/kt49034/objcprotocol/kt49034.h"
|
|
}
|
|
createInterop("objc_include_categories") {
|
|
it.defFile 'interop/objc/include_categories/objc_include_categories.def'
|
|
it.headers "$projectDir/interop/objc/include_categories/objc_include_categories.h"
|
|
}
|
|
createInterop("frameworkForwardDeclarations") {
|
|
it.defFile 'framework/forwardDeclarations/clib.def'
|
|
}
|
|
createInterop("objc_kt56402") {
|
|
it.defFile 'interop/objc/kt56402/objclib.def'
|
|
it.headers "$projectDir/interop/objc/kt56402/objclib.h"
|
|
}
|
|
createInterop("objc_friendly_dealloc") {
|
|
it.defFile 'interop/objc/objc_friendly_dealloc/objclib.def'
|
|
it.headers "$projectDir/interop/objc/objc_friendly_dealloc/objclib.h"
|
|
}
|
|
createInterop("objCAction") {
|
|
it.defFile 'interop/objc/objCAction/objclib.def'
|
|
it.headers "$projectDir/interop/objc/objCAction/objclib.h"
|
|
}
|
|
createInterop("overridabilityCondition") {
|
|
it.defFile 'interop/objc/overridabilityCondition/lib.def'
|
|
it.headers "$projectDir/interop/objc/overridabilityCondition/lib.h"
|
|
it.extraOpts "-Xcompile-source", "$projectDir/interop/objc/overridabilityCondition/lib.m"
|
|
}
|
|
createInterop("kt63423_dispose_on_main_stress") {
|
|
it.defFile 'interop/objc/kt63423_dispose_on_main_stress/objclib.def'
|
|
it.headers "$projectDir/interop/objc/kt63423_dispose_on_main_stress/objclib.h"
|
|
it.extraOpts "-Xcompile-source", "$projectDir/interop/objc/kt63423_dispose_on_main_stress/objclib.m"
|
|
it.extraOpts "-Xsource-compiler-option", "-DNS_FORMAT_ARGUMENT(A)="
|
|
it.extraOpts "-Xsource-compiler-option", "-fobjc-arc"
|
|
it.extraOpts "-Xsource-compiler-option", "-ObjC++"
|
|
}
|
|
}
|
|
|
|
createInterop("withSpaces") {
|
|
it.defFile generateWithSpaceDefFile()
|
|
}
|
|
|
|
createInterop("exceptions_throwThroughBridge") {
|
|
it.defFile "interop/exceptions/throwThroughBridge.def"
|
|
it.extraOpts "-Xcompile-source", "$projectDir/interop/exceptions/throwThroughBridgeInterop.cpp"
|
|
}
|
|
|
|
/**
|
|
* Creates a task for the interop test. Configures runner and adds library and test build tasks.
|
|
*/
|
|
Task interopTestBase(String name, boolean multiFile, boolean interop2ForMainOnly, Closure<KonanInteropTest> configureClosure) {
|
|
return KotlinNativeTestKt.createTest(project, name, KonanInteropTest) { KonanInteropTest task ->
|
|
task.configure(configureClosure)
|
|
if (task.enabled) {
|
|
konanArtifacts {
|
|
def targetName = target.name
|
|
def interopLib = task.interop
|
|
def interopLib2 = task.interop2
|
|
UtilsKt.dependsOnKonanBuildingTask(task, interopLib, target)
|
|
if (interopLib2 != null) UtilsKt.dependsOnKonanBuildingTask(task, interopLib2, target)
|
|
|
|
def lib = "lib$name"
|
|
def hasIntermediateLib = task.lib != null
|
|
if (hasIntermediateLib) {
|
|
// build a library from KonanInteropTest::lib property
|
|
library(lib, targets: [targetName]) {
|
|
libraries {
|
|
artifact interopLib
|
|
if (interopLib2 != null && !interop2ForMainOnly) artifact interopLib2
|
|
}
|
|
srcFiles task.lib
|
|
baseDir "$testOutputLocal/$name"
|
|
extraOpts task.flags
|
|
extraOpts project.globalTestArgs.findAll { !it.contains("-Xpartial-linkage") }
|
|
}
|
|
UtilsKt.dependsOnKonanBuildingTask(task, lib, target)
|
|
}
|
|
|
|
program(name, targets: [targetName]) {
|
|
libraries {
|
|
artifact interopLib
|
|
if (interopLib2 != null) artifact interopLib2
|
|
if (hasIntermediateLib)
|
|
klibFile file("$testOutputLocal/$name/$targetName/${lib}.klib")
|
|
}
|
|
srcFiles multiFile ? fileTree(task.source) { include '**/*.kt' } : task.getSources()
|
|
baseDir "$testOutputLocal/$name"
|
|
linkerOpts "-L${project.layout.buildDirectory.get().asFile}"
|
|
extraOpts task.flags
|
|
extraOpts project.globalTestArgs
|
|
}
|
|
}
|
|
task.dependsOn(nativeDependencies.llvmDependency)
|
|
task.dependsOn(nativeDependencies.targetDependency(target))
|
|
}
|
|
}
|
|
}
|
|
|
|
Task interopTest(String name, Closure<KonanInteropTest> configureClosure) {
|
|
return interopTestBase(name, false, false, configureClosure)
|
|
}
|
|
|
|
Task interopTestMultifile(String name, Closure<KonanInteropTest> configureClosure) {
|
|
return interopTestBase(name, true, false, configureClosure)
|
|
}
|
|
|
|
standaloneTest("interop_objc_allocException") {
|
|
disabled = !PlatformInfo.isAppleTarget(project)
|
|
expectedExitStatus = 0
|
|
source = "interop/objc/allocException.kt"
|
|
UtilsKt.dependsOnPlatformLibs(it)
|
|
}
|
|
|
|
interopTest("interop_embedStaticLibraries") {
|
|
source = "interop/embedStaticLibraries/main.kt"
|
|
interop = 'embedStaticLibraries'
|
|
}
|
|
|
|
interopTest("interop_withSpaces") {
|
|
interop ='withSpaces'
|
|
source = "interop/basics/withSpaces.kt"
|
|
|
|
doLast {
|
|
assert project.layout.buildDirectory.file("cutom map.map").get().asFile.exists()
|
|
}
|
|
}
|
|
|
|
interopTestBase("interop_forwardDeclarationsCast", false, true) {
|
|
enabled = PlatformInfo.isAppleTarget(project)
|
|
interop = 'forwardDeclarationsCastA'
|
|
interop2 = 'forwardDeclarationsCastB'
|
|
lib = 'interop/forwardDeclarationsCast/lib.kt'
|
|
source = 'interop/forwardDeclarationsCast/main.kt'
|
|
}
|
|
|
|
dynamicTest("interop_kt43502") {
|
|
interop = "kt43502"
|
|
source = "interop/kt43502/main.kt"
|
|
cSource = "$projectDir/interop/kt43502/main.c"
|
|
useGoldenData = true
|
|
}
|
|
|
|
interopTest("interop_leakMemoryWithRunningThreadChecked") {
|
|
interop = 'leakMemoryWithRunningThread'
|
|
source = "interop/leakMemoryWithRunningThread/checked.kt"
|
|
expectedExitStatusChecker = { it != 0 }
|
|
outputChecker = { s -> s.contains("Cannot run checkers when there are 1 alive runtimes at the shutdown") }
|
|
}
|
|
|
|
interopTest("interop_cppClass") {
|
|
disabled = PlatformInfo.isAppleTarget(project) // KT-58422
|
|
source = "interop/cpp/cppClass.kt"
|
|
interop = 'cppClass'
|
|
}
|
|
|
|
interopTest("interop_cppTypes") {
|
|
disabled = PlatformInfo.isAppleTarget(project) // KT-58422
|
|
source = "interop/cpp/types.kt"
|
|
interop = 'cppTypes'
|
|
}
|
|
|
|
interopTest("interop_cppSkia") {
|
|
disabled = true // KT-58422
|
|
source = "interop/cpp/skia.kt"
|
|
interop = 'cppSkia'
|
|
useGoldenData = true
|
|
UtilsKt.dependsOnPlatformLibs(it)
|
|
}
|
|
|
|
interopTest("interop_cppSkiaSignature") {
|
|
disabled = PlatformInfo.isAppleTarget(project) // KT-58422
|
|
source = "interop/cpp/skiaSignature.kt"
|
|
interop = "cppSkiaSignature"
|
|
useGoldenData = true
|
|
UtilsKt.dependsOnPlatformLibs(it)
|
|
}
|
|
|
|
interopTest("interop_workerSignals") {
|
|
disabled = project.testTarget == 'mingw_x64' // cross-thread signalling does not work on Windows
|
|
source = "interop/workerSignals/workerSignals.kt"
|
|
interop = "workerSignals"
|
|
}
|
|
|
|
interopTest("interop_forwardDeclarationsTwoLibs") {
|
|
source = "interop/forwardDeclarationsTwoLibs/forwardDeclarationsTwoLibs.kt"
|
|
interop = "cForwardDeclarationsTwoLibs1"
|
|
interop2 = "cForwardDeclarationsTwoLibs2"
|
|
}
|
|
|
|
/*
|
|
TODO: This test isn't run automatically
|
|
tasks.register("interop_echo_server", RunInteropKonanTest) {
|
|
disabled = PlatformInfo.isWasmTarget(project) || PlatformInfo.isWindowsTarget(project)
|
|
run = false
|
|
source = "interop/basics/echo_server.kt"
|
|
interop = 'sockets'
|
|
}
|
|
*/
|
|
|
|
/*
|
|
TODO: This test isn't run automatically
|
|
standaloneTest("interop_opengl_teapot") {
|
|
enabled = PlatformInfo.isAppleTarget(project) && project.testTarget != 'ios_x64' // No GLUT in iOS
|
|
dependsOnPlatformLibs(it as Task)
|
|
run = false
|
|
source = "interop/basics/opengl_teapot.kt"
|
|
}
|
|
*/
|
|
|
|
if (PlatformInfo.isAppleTarget(project)) {
|
|
interopTest("interop_objc_smoke") {
|
|
enabled = !isNoopGC
|
|
source = "interop/objc/smoke.kt"
|
|
interop = 'objcSmoke'
|
|
doBeforeBuild {
|
|
def dylibFile = project.layout.buildDirectory.file("libobjcsmoke.dylib").get().asFile
|
|
mkdir(dylibFile.parentFile)
|
|
project.extensions.execClang.execClangForCompilerTests(project.target) {
|
|
args "$projectDir/interop/objc/smoke.m"
|
|
args "-lobjc", '-fobjc-arc'
|
|
args '-fPIC', '-shared', '-o', dylibFile.toString()
|
|
// Enable ARC optimizations to prevent some objects from leaking in Obj-C code due to exceptions:
|
|
args '-O2'
|
|
}
|
|
if (UtilsKt.isSimulatorTarget(project, project.target)) {
|
|
UtilsKt.codesign(project, dylibFile.toString())
|
|
}
|
|
|
|
copy {
|
|
from("interop/objc/Localizable.stringsdict")
|
|
into("$testOutputLocal/$name/$target/en.lproj/")
|
|
}
|
|
}
|
|
useGoldenData = true
|
|
}
|
|
|
|
interopTest("interop_objc_smoke_noopgc") {
|
|
enabled = isNoopGC
|
|
source = "interop/objc/smoke_noopgc.kt"
|
|
interop = 'objcSmoke'
|
|
verifyIr = false // KT-57716
|
|
doBeforeBuild {
|
|
def dylibFile = project.layout.buildDirectory.file("libobjcsmoke.dylib").get().asFile
|
|
mkdir(dylibFile.parentFile)
|
|
project.extensions.execClang.execClangForCompilerTests(project.target) {
|
|
args "$projectDir/interop/objc/smoke.m"
|
|
args "-lobjc", '-fobjc-arc'
|
|
args '-fPIC', '-shared', '-o', dylibFile.toString()
|
|
// Enable ARC optimizations to prevent some objects from leaking in Obj-C code due to exceptions:
|
|
args '-O2'
|
|
}
|
|
if (UtilsKt.isSimulatorTarget(project, project.target)) {
|
|
UtilsKt.codesign(project, dylibFile.toString())
|
|
}
|
|
|
|
copy {
|
|
from("interop/objc/Localizable.stringsdict")
|
|
into("$testOutputLocal/$name/$target/en.lproj/")
|
|
}
|
|
}
|
|
// No deallocations for the no-op GC.
|
|
useGoldenData = true
|
|
}
|
|
|
|
interopTestMultifile("interop_objc_tests") {
|
|
source = "interop/objc/tests/"
|
|
interop = 'objcTests'
|
|
flags = ['-tr', '-e', 'main', '-opt-in=kotlin.native.internal.InternalForKotlinNative']
|
|
|
|
if (isNoopGC) {
|
|
def exclude = [
|
|
"Kt41811Kt.*",
|
|
"CustomStringKt.testCustomString",
|
|
"Kt42482Kt.testKT42482",
|
|
"ObjcWeakRefsKt.testObjCWeakRef",
|
|
"WeakRefsKt.testWeakRefs"
|
|
]
|
|
arguments += ["--ktest_filter=*-${exclude.join(":")}"]
|
|
}
|
|
|
|
doBeforeBuild {
|
|
def dylibFile = project.layout.buildDirectory.file("libobjctests.dylib").get().asFile
|
|
mkdir(dylibFile.parentFile)
|
|
project.extensions.execClang.execClangForCompilerTests(project.target) {
|
|
args fileTree("$projectDir/interop/objc/tests/") { include '**/*.m' }
|
|
args "-lobjc", '-fobjc-arc'
|
|
args '-fPIC', '-shared', '-o', dylibFile.toString()
|
|
// Enable ARC optimizations to prevent some objects from leaking in Obj-C code due to exceptions:
|
|
args '-O2'
|
|
}
|
|
if (UtilsKt.isSimulatorTarget(project, project.target)) {
|
|
UtilsKt.codesign(project, dylibFile.toString())
|
|
}
|
|
}
|
|
}
|
|
|
|
// KT-49034 tests don't need whole compilation pipeline (only frontend) or platform libraries. Consider simplifying them when porting
|
|
// to the new test infra.
|
|
interopTest("interop_kt49034_struct") {
|
|
interop = 'kt49034_struct'
|
|
source = 'interop/objc/kt49034/struct/main.kt'
|
|
|
|
// The test depends on collision between kt49034.JSContext and platform.JavaScriptCore.JSContext
|
|
UtilsKt.dependsOnPlatformLibs(it)
|
|
}
|
|
|
|
interopTest("interop_kt49034_objcclass") {
|
|
interop = 'kt49034_objcclass'
|
|
source = 'interop/objc/kt49034/objcclass/main.kt'
|
|
|
|
// The test depends on collision between kt49034.__darwin_fp_control and platform.darwin.__darwin_fp_control
|
|
UtilsKt.dependsOnPlatformLibs(it)
|
|
}
|
|
|
|
standaloneTest("interop_objc_kt61441") {
|
|
source = "interop/objc/kt61441.kt"
|
|
UtilsKt.dependsOnPlatformLibs(it)
|
|
}
|
|
|
|
|
|
interopTest("interop_objc_global_initializer") {
|
|
useGoldenData = true
|
|
source = "interop/objc_with_initializer/objc_test.kt"
|
|
interop = 'objcMisc'
|
|
|
|
doBeforeBuild {
|
|
def dylibFile = project.layout.buildDirectory.file("libobjcmisc.dylib").get().asFile
|
|
mkdir(dylibFile.parentFile)
|
|
project.extensions.execClang.execClangForCompilerTests(project.target) {
|
|
args "$projectDir/interop/objc_with_initializer/objc_misc.m"
|
|
args "-lobjc", '-fobjc-arc'
|
|
args '-fPIC', '-shared', '-o', dylibFile.toString()
|
|
}
|
|
if (UtilsKt.isSimulatorTarget(project, project.target)) {
|
|
UtilsKt.codesign(project, dylibFile.toString())
|
|
}
|
|
}
|
|
}
|
|
|
|
interopTest("interop_objc_msg_send") {
|
|
source = "interop/objc/msg_send/main.kt"
|
|
interop = 'objcMessaging'
|
|
|
|
doBeforeBuild {
|
|
def dylibFile = project.layout.buildDirectory.file("libobjcmessaging.dylib").get().asFile
|
|
mkdir(dylibFile.parentFile)
|
|
project.extensions.execClang.execClangForCompilerTests(project.target) {
|
|
args "$projectDir/interop/objc/msg_send/messaging.m"
|
|
args "-lobjc", '-fobjc-arc'
|
|
args '-fPIC', '-shared', '-o', dylibFile.toString()
|
|
}
|
|
if (UtilsKt.isSimulatorTarget(project, project.target)) {
|
|
UtilsKt.codesign(project, dylibFile.toString())
|
|
}
|
|
}
|
|
}
|
|
|
|
interopTest("interop_objc_direct") {
|
|
source = "interop/objc/direct/main.kt"
|
|
interop = "objcDirect"
|
|
}
|
|
|
|
interopTest("interop_objc_overridabilityCondition") {
|
|
interop = "overridabilityCondition"
|
|
source = "interop/objc/overridabilityCondition/main.kt"
|
|
flags = [ "-Xuse-ir-fake-override-builder" ]
|
|
}
|
|
|
|
interopTest("interop_objc_foreignException") {
|
|
source = "interop/objc/foreignException/objc_wrap.kt"
|
|
interop = 'foreignException'
|
|
UtilsKt.dependsOnPlatformLibs(it)
|
|
|
|
doBeforeBuild {
|
|
def dylibFile = project.layout.buildDirectory.file("libobjcexception.dylib").get().asFile
|
|
mkdir(dylibFile.parentFile)
|
|
project.extensions.execClang.execClangForCompilerTests(project.target) {
|
|
args "$projectDir/interop/objc/foreignException/objc_wrap.m"
|
|
args "-lobjc", '-fobjc-arc'
|
|
args '-fPIC', '-shared', '-o', dylibFile.toString()
|
|
}
|
|
if (UtilsKt.isSimulatorTarget(project, project.target)) {
|
|
UtilsKt.codesign(project, dylibFile.toString())
|
|
}
|
|
}
|
|
}
|
|
|
|
interopTest("interop_objc_foreignExceptionMode_wrap") {
|
|
source = "interop/objc/foreignException/objcExceptionMode_wrap.kt"
|
|
interop = 'foreignExceptionMode_wrap'
|
|
useGoldenData = true
|
|
UtilsKt.dependsOnPlatformLibs(it)
|
|
|
|
doBeforeBuild {
|
|
def dylibFile = project.layout.buildDirectory.file("libobjcexception.dylib").get().asFile
|
|
mkdir(dylibFile.parentFile)
|
|
project.extensions.execClang.execClangForCompilerTests(project.target) {
|
|
args "$projectDir/interop/objc/foreignException/objc_wrap.m"
|
|
args "-lobjc", '-fobjc-arc'
|
|
args '-fPIC', '-shared', '-o', dylibFile.toString()
|
|
}
|
|
if (UtilsKt.isSimulatorTarget(project, project.target)) {
|
|
UtilsKt.codesign(project, dylibFile.toString())
|
|
}
|
|
}
|
|
}
|
|
|
|
interopTest("interop_objc_foreignExceptionMode_default") {
|
|
source = "interop/objc/foreignException/objcExceptionMode_default.kt"
|
|
interop = 'foreignExceptionMode_default'
|
|
useGoldenData = true
|
|
UtilsKt.dependsOnPlatformLibs(it)
|
|
|
|
doBeforeBuild {
|
|
def dylibFile = project.layout.buildDirectory.file("libobjcexception.dylib").get().asFile
|
|
mkdir(dylibFile.parentFile)
|
|
project.extensions.execClang.execClangForCompilerTests(project.target) {
|
|
args "$projectDir/interop/objc/foreignException/objc_wrap.m"
|
|
args "-lobjc", '-fobjc-arc'
|
|
args '-fPIC', '-shared', '-o', dylibFile.toString()
|
|
}
|
|
if (UtilsKt.isSimulatorTarget(project, project.target)) {
|
|
UtilsKt.codesign(project, dylibFile.toString())
|
|
}
|
|
}
|
|
}
|
|
|
|
interopTest("interop_objc_illegal_sharing_with_weak") {
|
|
source = "interop/objc/illegal_sharing_with_weak/main.kt"
|
|
interop = 'objc_illegal_sharing_with_weak'
|
|
// Experimental MM supports arbitrary object sharing.
|
|
outputChecker = { it == "Before\nAfter true\n" }
|
|
}
|
|
|
|
interopTest("interop_objc_kt42172") {
|
|
enabled = !isNoopGC
|
|
source = "interop/objc/kt42172/main.kt"
|
|
interop = "objc_kt42172"
|
|
flags = ['-opt-in=kotlin.native.internal.InternalForKotlinNative']
|
|
useGoldenData = true
|
|
|
|
doBeforeBuild {
|
|
def dylibFile = project.layout.buildDirectory.file("libobjc_kt42172.dylib").get().asFile
|
|
mkdir(dylibFile.parentFile)
|
|
project.extensions.execClang.execClangForCompilerTests(project.target) {
|
|
args "$projectDir/interop/objc/kt42172/objclib.m"
|
|
args "-lobjc", '-fobjc-arc'
|
|
args '-fPIC', '-shared', '-o', dylibFile.toString()
|
|
}
|
|
if (UtilsKt.isSimulatorTarget(project, project.target)) {
|
|
UtilsKt.codesign(project, dylibFile.toString())
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
interopTest("interop_objc_kt48816_without_lazy_ir_for_caches") {
|
|
// Without a fix, fails in two-stage mode.
|
|
source = "interop/objc/kt48816/main.kt"
|
|
interop = "objc_kt48816"
|
|
// The bug was accidentally fixed with lazy IR for caches, so testing it with this feature disabled:
|
|
flags = ["-Xlazy-ir-for-caches=disable"]
|
|
}
|
|
|
|
interopTest("interop_objc_kt48816_with_lazy_ir_for_caches") {
|
|
source = "interop/objc/kt48816/main.kt"
|
|
interop = "objc_kt48816"
|
|
flags = ["-Xlazy-ir-for-caches=enable"]
|
|
}
|
|
|
|
interopTest("interop_objc_kt55938") {
|
|
source = "interop/objc/kt55938/main.kt"
|
|
lib = "interop/objc/kt55938/lib.kt"
|
|
interop = "objc_kt55938"
|
|
useGoldenData = true
|
|
enabled = cacheTesting != null
|
|
flags = [
|
|
"-Xauto-cache-from=$testOutputRoot/local/objc_kt55938",
|
|
"-Xauto-cache-from=$testOutputRoot/local/interop_objc_kt55938",
|
|
"-Xauto-cache-dir=$testOutputRoot/local/interop_objc_kt55938/cache",
|
|
"-Xsuppress-version-warnings", // suppresses warning about experimental language version, otherwise test fails with K2 due to -Werror
|
|
"-Werror" // to forbid retry with auto-cache disabled
|
|
]
|
|
|
|
UtilsKt.findKonanBuildTask(project, "objc_kt55938", target).configure {
|
|
it.doFirst {
|
|
def cacheDir = new File("$testOutputRoot/local/interop_objc_kt55938/cache")
|
|
cacheDir.deleteDir()
|
|
mkdir(cacheDir)
|
|
}
|
|
}
|
|
|
|
doBeforeBuild {
|
|
def dylibFile = project.layout.buildDirectory.file("libobjc_kt55938.dylib").get().asFile
|
|
mkdir(dylibFile.parentFile)
|
|
project.extensions.execClang.execClangForCompilerTests(project.target) {
|
|
args "$projectDir/interop/objc/kt55938/objclib.m"
|
|
args "-lobjc", '-fobjc-arc'
|
|
args '-fPIC', '-shared', '-o', dylibFile.toString()
|
|
}
|
|
if (UtilsKt.isSimulatorTarget(project, project.target)) {
|
|
UtilsKt.codesign(project, dylibFile.toString())
|
|
}
|
|
}
|
|
}
|
|
|
|
standaloneTest("objc_arc_contract") {
|
|
def bcFile = project.layout.buildDirectory.file("objc_arc_contract.bc").get().asFile
|
|
doBeforeBuild {
|
|
mkdir(bcFile.parentFile)
|
|
ExecLlvmKt.execLlvmUtility(project, "llvm-as") {
|
|
args "$projectDir/interop/objc_arc_contract/main.ll"
|
|
args "-o", bcFile.toString()
|
|
}
|
|
}
|
|
source = "interop/objc_arc_contract/main.kt"
|
|
useGoldenData = true
|
|
flags = ["-native-library", bcFile.toString()]
|
|
}
|
|
|
|
interopTest("interop_objc_include_categories") {
|
|
useGoldenData = true
|
|
source = "interop/objc/include_categories/main.kt"
|
|
interop = "objc_include_categories"
|
|
doBeforeBuild {
|
|
def dylibFile = project.layout.buildDirectory.file("libobjcincludecategories.dylib").get().asFile
|
|
mkdir(dylibFile.parentFile)
|
|
project.extensions.execClang.execClangForCompilerTests(project.target) {
|
|
args "$projectDir/interop/objc/include_categories/objc_include_categories.m"
|
|
args "-lobjc", '-fobjc-arc'
|
|
args '-fPIC', '-shared', '-o', dylibFile.toString()
|
|
}
|
|
if (UtilsKt.isSimulatorTarget(project, project.target)) {
|
|
UtilsKt.codesign(project, dylibFile.toString())
|
|
}
|
|
}
|
|
}
|
|
|
|
standaloneTest("interop_kt55653") {
|
|
// Test depends on macOS-specific AppKit
|
|
enabled = (project.testTarget == 'macos_x64' || project.testTarget == 'macos_arm64' || project.testTarget == null)
|
|
source = "interop/objc/kt55653/main.kt"
|
|
useGoldenData = true
|
|
UtilsKt.dependsOnPlatformLibs(it)
|
|
}
|
|
|
|
standaloneTest("interop_kt40426") {
|
|
// Test depends on iOS-specific UIKit
|
|
enabled = (project.testTarget == 'ios_x64' || project.testTarget == 'ios_simulator_arm64' || project.testTarget == 'ios_arm64')
|
|
source = "interop/objc/kt40426/main.kt"
|
|
useGoldenData = true
|
|
UtilsKt.dependsOnPlatformLibs(it)
|
|
}
|
|
|
|
interopTest("interop_objc_kt56402") {
|
|
// Test depends on macOS-specific AppKit
|
|
enabled = (project.testTarget == 'macos_x64' || project.testTarget == 'macos_arm64' || project.testTarget == null)
|
|
&& !isNoopGC // requires some GC
|
|
source = 'interop/objc/kt56402/main.kt'
|
|
interop = "objc_kt56402"
|
|
flags = ["-tr", "-e", "runAllTests"] // Generate test suites, but use custom entrypoint.
|
|
|
|
doBeforeBuild {
|
|
def dylibFile = project.layout.buildDirectory.file("libobjc_kt56402.dylib").get().asFile
|
|
mkdir(dylibFile.parentFile)
|
|
project.extensions.execClang.execClangForCompilerTests(project.target) {
|
|
args "$projectDir/interop/objc/kt56402/objclib.m"
|
|
args "-g"
|
|
args "-lobjc", '-fobjc-arc'
|
|
args '-fPIC', '-shared', '-o', dylibFile.toString()
|
|
args '-framework', 'AppKit'
|
|
}
|
|
if (UtilsKt.isSimulatorTarget(project, project.target)) {
|
|
UtilsKt.codesign(project, dylibFile.toString())
|
|
}
|
|
}
|
|
}
|
|
|
|
interopTest("interop_objc_friendly_dealloc") {
|
|
enabled = !isNoopGC // requires some GC
|
|
source = 'interop/objc/objc_friendly_dealloc/main.kt'
|
|
interop = "objc_friendly_dealloc"
|
|
flags = ["-tr"]
|
|
|
|
doBeforeBuild {
|
|
def dylibFile = project.layout.buildDirectory.file("libobjc_friendly_dealloc.dylib").get().asFile
|
|
mkdir(dylibFile.parentFile)
|
|
project.extensions.execClang.execClangForCompilerTests(project.target) {
|
|
args "$projectDir/interop/objc/objc_friendly_dealloc/objclib.m"
|
|
args "-lobjc", '-fno-objc-arc'
|
|
args '-fPIC', '-shared', '-o', dylibFile.toString()
|
|
}
|
|
if (UtilsKt.isSimulatorTarget(project, project.target)) {
|
|
UtilsKt.codesign(project, dylibFile.toString())
|
|
}
|
|
}
|
|
UtilsKt.dependsOnPlatformLibs(it)
|
|
}
|
|
|
|
interopTest("interop_objCAction") {
|
|
source = 'interop/objc/objCAction/main.kt'
|
|
interop = "objCAction"
|
|
flags = ["-tr"]
|
|
doBeforeBuild {
|
|
def dylibFile = project.layout.buildDirectory.file("libobjCAction.dylib").get().asFile
|
|
mkdir(dylibFile.parentFile)
|
|
project.extensions.execClang.execClangForCompilerTests(project.target) {
|
|
args "$projectDir/interop/objc/objCAction/objclib.m"
|
|
args "-lobjc", '-fobjc-arc'
|
|
args '-fPIC', '-shared', '-o', dylibFile.toString()
|
|
}
|
|
if (UtilsKt.isSimulatorTarget(project, project.target)) {
|
|
UtilsKt.codesign(project, dylibFile.toString())
|
|
}
|
|
}
|
|
UtilsKt.dependsOnPlatformLibs(it)
|
|
}
|
|
|
|
interopTest("interop_objc_kt63423_dispose_on_main_stress") {
|
|
// Test depends on macOS-specific AppKit
|
|
enabled = (project.testTarget == 'macos_x64' || project.testTarget == 'macos_arm64' || project.testTarget == null)
|
|
&& !isNoopGC // requires some GC
|
|
&& !isAggressiveGC // requires careful timing of GC
|
|
source = 'interop/objc/kt63423_dispose_on_main_stress/main.kt'
|
|
interop = "kt63423_dispose_on_main_stress"
|
|
flags = [
|
|
'-opt-in=kotlin.native.internal.InternalForKotlinNative', // MemoryUsageInfo is internal
|
|
'-Xbinary=gcSchedulerType=manual', // This test requires very careful timing when GC can happen
|
|
]
|
|
}
|
|
}
|
|
|
|
tasks.register("KT-50983", KonanDriverTest) {
|
|
// The test is not working on Windows Server 2019-based TeamCity agents for the unknown reason.
|
|
// TODO: Re-enable it after LLVM update where llvm-windres will be added.
|
|
enabled = false
|
|
def resFile = project.layout.buildDirectory.file("File.res").get().asFile
|
|
doBeforeBuild {
|
|
mkdir(resFile.parentFile)
|
|
exec {
|
|
commandLine UtilsKt.binaryFromToolchain(project, "windres")
|
|
args "$projectDir/windows/KT-50983/File.rc", "-O", "coff", "-o", resFile.toString()
|
|
}
|
|
}
|
|
source = "windows/KT-50983/main.kt"
|
|
flags = ['-linker-option', resFile.toString()]
|
|
}
|
|
|
|
standaloneTest("interop_libiconv") {
|
|
enabled = (project.testTarget == null)
|
|
source = "interop/libiconv.kt"
|
|
useGoldenData = true
|
|
UtilsKt.dependsOnPlatformLibs(it)
|
|
}
|
|
|
|
standaloneTest("interop_zlib") {
|
|
enabled = (project.testTarget == null)
|
|
source = "interop/platform_zlib.kt"
|
|
useGoldenData = true
|
|
UtilsKt.dependsOnPlatformLibs(it)
|
|
}
|
|
|
|
standaloneTest("interop_objc_illegal_sharing") {
|
|
disabled = !PlatformInfo.isAppleTarget(project)
|
|
source = "interop/objc/illegal_sharing.kt"
|
|
UtilsKt.dependsOnPlatformLibs(it)
|
|
outputChecker = {
|
|
it.startsWith("Before") && it.contains("After")
|
|
}
|
|
}
|
|
|
|
standaloneTest("interop_kt62262") {
|
|
enabled = project.testTarget == 'ios_x64' || project.testTarget == 'ios_arm64' || project.testTarget == 'ios_simulator_arm64'
|
|
source = "interop/objc/kt62262.kt"
|
|
UtilsKt.dependsOnPlatformLibs(it)
|
|
}
|
|
|
|
dynamicTest("produce_dynamic") {
|
|
source = "produce_dynamic/simple/hello.kt"
|
|
cSource = "$projectDir/produce_dynamic/simple/main.c"
|
|
useGoldenData = true
|
|
}
|
|
|
|
dynamicTest("kt36878") {
|
|
source = "produce_dynamic/kt-36878/hello.kt"
|
|
cSource = "$projectDir/produce_dynamic/kt-36878/main.c"
|
|
useGoldenData = true
|
|
}
|
|
|
|
dynamicTest("kt39015") {
|
|
source = "produce_dynamic/kt-39015/hello.kt"
|
|
cSource = "$projectDir/produce_dynamic/kt-39015/main.c"
|
|
useGoldenData = true
|
|
}
|
|
|
|
dynamicTest("kt39496") {
|
|
source = "produce_dynamic/kt-39496/hello.kt"
|
|
cSource = "$projectDir/produce_dynamic/kt-39496/main.c"
|
|
useGoldenData = true
|
|
}
|
|
|
|
dynamicTest("kt41904") {
|
|
source = "produce_dynamic/kt-41904/hello.kt"
|
|
cSource = "$projectDir/produce_dynamic/kt-41904/main.c"
|
|
useGoldenData = true
|
|
}
|
|
|
|
for (i in 0..2) {
|
|
dynamicTest("kt42796_$i") {
|
|
clangTool = "clang++"
|
|
source = "produce_dynamic/kt-42796/main-${i}.kt"
|
|
cSource = "$projectDir/produce_dynamic/kt-42796/main.cpp"
|
|
useGoldenData = true
|
|
clangFlags = ["-DTEST=$i", "-Werror"]
|
|
}
|
|
}
|
|
|
|
dynamicTest("kt42830") {
|
|
source = "produce_dynamic/kt-42830/box_unbox.kt"
|
|
cSource = "$projectDir/produce_dynamic/kt-42830/main.c"
|
|
useGoldenData = true
|
|
}
|
|
|
|
dynamicTest("kt64508") {
|
|
source = "produce_dynamic/kt-64508/hello.kt"
|
|
cSource = "$projectDir/produce_dynamic/kt-64508/main.c"
|
|
useGoldenData = true
|
|
}
|
|
|
|
dynamicTest("produce_dynamic_unhandledException") {
|
|
disabled = (cacheTesting != null) // Disabled due to KT-47828.
|
|
source = "produce_dynamic/unhandledException/unhandled.kt"
|
|
cSource = "$projectDir/produce_dynamic/unhandledException/main.cpp"
|
|
clangTool = "clang++"
|
|
expectedExitStatusChecker = { it != 0 }
|
|
outputChecker = { str -> str.startsWith("Kotlin hook: Exception. Runnable state: true") }
|
|
flags = ['-opt-in=kotlin.native.internal.InternalForKotlinNative']
|
|
}
|
|
|
|
dynamicTest("interop_concurrentRuntime") {
|
|
source = "interop/concurrentTerminate/reverseInterop.kt"
|
|
cSource = "$projectDir/interop/concurrentTerminate/main.cpp"
|
|
clangTool = "clang++"
|
|
if (project.testTarget == 'mingw_x64') {
|
|
// Our sysroot for mingw_x64 still requires -femulated-tls. For C++ code as well. See KT-46612.
|
|
clangFlags += "-femulated-tls"
|
|
}
|
|
outputChecker = { str -> str.startsWith("Uncaught Kotlin exception: kotlin.RuntimeException: Example") }
|
|
expectedExitStatus = 99
|
|
}
|
|
|
|
for (i in ["kt42397", "kt56182_root", "kt56182_package1lvl", "kt56182_subpackage2lvl", "kt56182_root_package1lvl", "kt56182_root_subpackage2lvl"]) {
|
|
// note: kt56182_package1lvl is same as kt42397
|
|
// note: kt56182_root_package1lvl is similar as kt41904
|
|
// note: kt56182_subpackage2lvl is similar as kt42796_1
|
|
dynamicTest("interop_$i") {
|
|
source = "interop/$i/knlibrary.kt"
|
|
cSource = "$projectDir/interop/$i/test.cpp"
|
|
clangTool = "clang++"
|
|
}
|
|
}
|
|
|
|
dynamicTest("interop_cleaners_main_thread") {
|
|
disabled = isNoopGC
|
|
source = "interop/cleaners/cleaners.kt"
|
|
cSource = "$projectDir/interop/cleaners/main_thread.cpp"
|
|
clangTool = "clang++"
|
|
useGoldenData = true
|
|
flags = ['-opt-in=kotlin.native.internal.InternalForKotlinNative']
|
|
}
|
|
|
|
dynamicTest("interop_cleaners_second_thread") {
|
|
disabled = isNoopGC
|
|
source = "interop/cleaners/cleaners.kt"
|
|
cSource = "$projectDir/interop/cleaners/second_thread.cpp"
|
|
clangTool = "clang++"
|
|
useGoldenData = true
|
|
flags = ['-opt-in=kotlin.native.internal.InternalForKotlinNative']
|
|
}
|
|
|
|
dynamicTest("interop_cleaners_leak") {
|
|
source = "interop/cleaners/cleaners.kt"
|
|
cSource = "$projectDir/interop/cleaners/leak.cpp"
|
|
clangTool = "clang++"
|
|
useGoldenData = true
|
|
flags = ['-opt-in=kotlin.native.internal.InternalForKotlinNative']
|
|
}
|
|
|
|
dynamicTest("interop_migrating_main_thread") {
|
|
source = "interop/migrating_main_thread/lib.kt"
|
|
clangFlags = ['-DEXPERIMENTAL_MM']
|
|
cSource = "$projectDir/interop/migrating_main_thread/main.cpp"
|
|
clangTool = "clang++"
|
|
}
|
|
|
|
dynamicTest("interop_exceptions_throwThroughBridge") {
|
|
source = "interop/exceptions/throwThroughBridge.kt"
|
|
cSource = "$projectDir/interop/exceptions/throwThroughBridge.cpp"
|
|
clangTool = "clang++"
|
|
expectedExitStatusChecker = { it != 0 }
|
|
outputChecker = { s -> !s.contains("Should not happen") }
|
|
interop = "exceptions_throwThroughBridge"
|
|
}
|
|
|
|
dynamicTest("interop_kotlin_exception_hook") {
|
|
source = "interop/exceptions/exceptionHook.kt"
|
|
cSource = "$projectDir/interop/exceptions/exceptionHook.cpp"
|
|
clangTool = "clang++"
|
|
expectedExitStatusChecker = { it != 0 }
|
|
outputChecker = { s -> s.contains("OK. Kotlin unhandled exception hook") }
|
|
}
|
|
|
|
standaloneTest("library_ir_provider_mismatch") {
|
|
enabled = !isAggressiveGC // No need to test with different GC schedulers
|
|
|
|
String librarySource = "$projectDir/link/ir_providers/library/empty.kt"
|
|
String invalidManifest = "$projectDir/link/ir_providers/library/manifest.properties"
|
|
String mainSource = "$projectDir/link/ir_providers/hello.kt"
|
|
|
|
File outputDir = project.layout.buildDirectory.dir(name).get().asFile
|
|
String currentTarget = project.target.name
|
|
|
|
inputs.files(librarySource, invalidManifest)
|
|
inputs.property("target", currentTarget)
|
|
outputs.dir(outputDir)
|
|
source = mainSource
|
|
|
|
doBeforeBuild {
|
|
konanc("$librarySource -target $currentTarget -p library -o $outputDir/unsupported_ir_provider/empty.klib -manifest $invalidManifest")
|
|
konanc("$librarySource -target $currentTarget -p library -o $outputDir/supported_ir_provider/empty.klib ")
|
|
|
|
// Should not be successful:
|
|
boolean failed = false
|
|
String command = "$mainSource -target $currentTarget -p program -o $outputDir/failed.kexe -l $outputDir/unsupported_ir_provider/empty.klib"
|
|
try {
|
|
konanc(command)
|
|
} catch (Throwable t) {
|
|
String exceptionText = t.message
|
|
exceptionText = PlatformInfo.isWindows() ? exceptionText.replace("\\", "/") : exceptionText
|
|
|
|
String expectedText = "warning: KLIB resolver: Skipping '$outputDir/unsupported_ir_provider/empty.klib'. The library requires unknown IR provider: UNSUPPORTED"
|
|
expectedText = PlatformInfo.isWindows() ? expectedText.replace("\\", "/") : expectedText
|
|
|
|
if (t instanceof GradleException && exceptionText.contains(expectedText)) {
|
|
failed = true
|
|
} else {
|
|
throw t
|
|
}
|
|
}
|
|
|
|
if (!failed) {
|
|
throw new GradleException("Kotlin/Natice invocation is successful but should fail:\n$command")
|
|
}
|
|
}
|
|
|
|
flags = ["-l", "$outputDir/supported_ir_provider/empty.klib"]
|
|
}
|
|
|
|
standaloneTest("kt51302") {
|
|
enabled = project.target.name == project.hostName
|
|
source = "serialization/KT-51302/main.kt"
|
|
flags = ["-l", "$projectDir/serialization/KT-51302/kt51302_dependency"]
|
|
}
|
|
|
|
standaloneTest("fake_override_0") {
|
|
def sources = "$projectDir/link/fake_overrides"
|
|
doBeforeBuild {
|
|
konanc("$sources/base.kt -p library -target ${target.name} -o $outputDirectory/base.klib")
|
|
konanc("$sources/move.kt -p library -target ${target.name} -o $outputDirectory/move.klib -l $outputDirectory/base.klib")
|
|
konanc("$sources/use.kt -p library -target ${target.name} -o $outputDirectory/use.klib -l $outputDirectory/move.klib -l $outputDirectory/base.klib")
|
|
konanc("$sources/move2.kt -p library -target ${target.name} -o $outputDirectory/move.klib -l $outputDirectory/base.klib")
|
|
}
|
|
source = "$sources/main.kt"
|
|
flags = ["-l", "$outputDirectory/use.klib", "-l", "$outputDirectory/move.klib", "-l", "$outputDirectory/base.klib"]
|
|
useGoldenData = true
|
|
}
|
|
|
|
standaloneTest("split_compilation_pipeline") {
|
|
// Test infrastructure does not support passing flags only to the second stage,
|
|
// and we can't pass -Xcompile-from-bitcode when producing library. Thus, this test
|
|
// does not support 2-stage compilation for now.
|
|
// Also, it is failing for some reason on Windows CI, but since MinGW targets are not inteneded
|
|
// to use this mode, we can disable it for these targets.
|
|
enabled = !twoStageEnabled && project.target.name != "mingw_x64" && project.target.name != "mingw_x86"
|
|
def dir = project.layout.buildDirectory.get().asFile.absolutePath
|
|
source = "link/private_fake_overrides/override_main.kt"
|
|
doBeforeBuild {
|
|
konanc("$projectDir/link/private_fake_overrides/override_lib.kt -p library -target ${target.name} -o $dir/lib.klib")
|
|
konanc("$projectDir/$source -target ${target.name} -o $dir/out.klib -l $dir/lib.klib " +
|
|
"-Xtemporary-files-dir=$dir/tmp/split " +
|
|
"-Xwrite-dependencies-to=${dir}/split_compilation_pipeline.deps")
|
|
}
|
|
flags = ["-Xread-dependencies-from=${dir}/split_compilation_pipeline.deps", "-Xcompile-from-bitcode=${dir}/tmp/split/out.bc"]
|
|
useGoldenData = true
|
|
}
|
|
|
|
Task frameworkTest(String name, Closure<FrameworkTest> configurator) {
|
|
return KotlinNativeTestKt.createTest(project, name, FrameworkTest) { task ->
|
|
configurator.delegate = task
|
|
UtilsKt.dependsOnDist(task)
|
|
configurator()
|
|
if (task.enabled) {
|
|
konanArtifacts {
|
|
task.frameworks.forEach { fr ->
|
|
framework(fr.name, targets: [target.name]) {
|
|
fr.sources.forEach { src ->
|
|
srcFiles src
|
|
}
|
|
baseDir "$testOutputFramework/${task.name}"
|
|
|
|
fr.libraries.forEach { library ->
|
|
dependsOn konanArtifacts[library].getByTarget(target.name)
|
|
libraries {
|
|
klibFile konanArtifacts[library].getArtifactByTarget(target.name)
|
|
}
|
|
linkerOpts "-L${project.layout.buildDirectory.get().asFile}"
|
|
UtilsKt.dependsOnKonanBuildingTask(task, library, target)
|
|
}
|
|
|
|
if (fr.isStatic) extraOpts "-Xstatic-framework"
|
|
extraOpts fr.opts
|
|
extraOpts project.globalTestArgs
|
|
|
|
artifactName fr.artifact
|
|
}
|
|
UtilsKt.dependsOnDist(project.tasks.findByName("compileKonan${fr.name.capitalize()}${UtilsKt.getTestTargetSuffix(project)}"))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Task objcExportTest(
|
|
Task allTask,
|
|
String suffix,
|
|
List<String> frameworkOpts,
|
|
List<String> swiftOpts,
|
|
Boolean isStaticFramework,
|
|
Boolean needLazyHeaderCheck
|
|
) {
|
|
needLazyHeaderCheck = needLazyHeaderCheck && !PlatformInfo.isK2(project) // generating lazy headers is NYI in K2
|
|
final String name = "testObjCExport$suffix"
|
|
final String frameworkName = "Kt$suffix"
|
|
final String expectedLazyHeaderName = "expectedLazy${suffix}.h"
|
|
final Task task = frameworkTest(name) {
|
|
final String dir = "$testOutputFramework/$name"
|
|
final File lazyHeader = file("$dir/$target-lazy.h")
|
|
lazyHeader.delete() // Clean up after previous runs
|
|
|
|
doLast {
|
|
// Check lazy header.
|
|
if (needLazyHeaderCheck) {
|
|
final String expectedLazyHeaderDir = file("objcexport/")
|
|
final File expectedLazyHeader = new File(expectedLazyHeaderDir, expectedLazyHeaderName)
|
|
|
|
if (!expectedLazyHeader.exists() || expectedLazyHeader.readLines() != lazyHeader.readLines()) {
|
|
exec {
|
|
commandLine 'diff', '-u', expectedLazyHeader, lazyHeader
|
|
ignoreExitValue = true
|
|
}
|
|
|
|
copy {
|
|
from(lazyHeader)
|
|
into(expectedLazyHeaderDir)
|
|
rename { expectedLazyHeaderName }
|
|
}
|
|
|
|
throw new Error("$expectedLazyHeader file patched;\nRun gradlew ${allTask.path} --continue and don't forget to commit the patch")
|
|
}
|
|
}
|
|
|
|
// Check bundle ID.
|
|
final String frameworkPath = "$dir/$target/Kt.framework"
|
|
final Pattern pattern = ~"<key>CFBundleIdentifier</key>\n\\s*<string>foo.bar</string>"
|
|
final String plistPath = (target.family == Family.OSX) ?
|
|
"$frameworkPath/Resources/Info.plist" :
|
|
"$frameworkPath/Info.plist"
|
|
final String plistContent = file(plistPath).text
|
|
if (!pattern.matcher(plistContent).find()) {
|
|
throw new Error("Unexpected Info.plist content:\n$plistContent")
|
|
}
|
|
}
|
|
|
|
def libraryName = frameworkName + "Library"
|
|
def noEnumEntriesLibraryName = frameworkName + "NoEnumEntriesLibrary"
|
|
File exportedKlibArtifact = null
|
|
konanArtifacts {
|
|
library(libraryName, targets: [target.name]) {
|
|
srcDir "objcexport/library"
|
|
artifactName "test-$libraryName"
|
|
delegate.getByTarget(target.name).configure{
|
|
UtilsKt.dependsOnDist(it)
|
|
}
|
|
|
|
extraOpts "-Xshort-module-name=MyLibrary"
|
|
extraOpts "-module-name", "org.jetbrains.kotlin.native.test-library"
|
|
}
|
|
library(noEnumEntriesLibraryName, targets: [target.name]) {
|
|
srcDir "objcexport/noEnumEntries"
|
|
artifactName "test-no-enum-entries-$libraryName"
|
|
delegate.getByTarget(target.name).configure{
|
|
UtilsKt.dependsOnDist(it)
|
|
}
|
|
|
|
exportedKlibArtifact = getArtifactByTarget(target.name)
|
|
extraOpts "-Xshort-module-name=NoEnumEntriesLibrary"
|
|
extraOpts "-module-name", "org.jetbrains.kotlin.native.test-no-enum-entries-library"
|
|
extraOpts "-XXLanguage:-EnumEntries"
|
|
}
|
|
}
|
|
codesign = !isStaticFramework
|
|
framework(frameworkName) {
|
|
sources = ['objcexport']
|
|
libraries = [libraryName, noEnumEntriesLibraryName]
|
|
artifact = 'Kt'
|
|
isStatic = isStaticFramework
|
|
if (needLazyHeaderCheck) {
|
|
opts += "-Xemit-lazy-objc-header=$lazyHeader"
|
|
}
|
|
opts += [
|
|
"-Xexport-kdoc",
|
|
"-Xbinary=bundleId=foo.bar",
|
|
"-Xexport-library=$exportedKlibArtifact",
|
|
"-module-name", "Kt"
|
|
]
|
|
opts += frameworkOpts
|
|
}
|
|
swiftSources = ['objcexport']
|
|
swiftExtraOpts = swiftOpts
|
|
if (isNoopGC) {
|
|
swiftExtraOpts += ["-D", "NOOP_GC"]
|
|
}
|
|
if (isAggressiveGC) {
|
|
swiftExtraOpts += ["-D", "AGGRESSIVE_GC"]
|
|
}
|
|
}
|
|
allTask.dependsOn(task)
|
|
return task
|
|
}
|
|
|
|
|
|
|
|
if (PlatformInfo.isAppleTarget(project)) {
|
|
final Task ObjCExportAllTask = tasks.create("testObjCExportAll")
|
|
objcExportTest(
|
|
ObjCExportAllTask,
|
|
'',
|
|
[],
|
|
[],
|
|
false,
|
|
true
|
|
)
|
|
objcExportTest(
|
|
ObjCExportAllTask,
|
|
'NoGenerics',
|
|
["-Xno-objc-generics"],
|
|
[ '-D', 'NO_GENERICS' ],
|
|
false,
|
|
true
|
|
)
|
|
objcExportTest(
|
|
ObjCExportAllTask,
|
|
'LegacySuspendUnit',
|
|
["-Xbinary=unitSuspendFunctionObjCExport=legacy"],
|
|
[ '-D', 'LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT' ],
|
|
false,
|
|
true
|
|
)
|
|
objcExportTest(
|
|
ObjCExportAllTask,
|
|
'NoSwiftMemberNameMangling',
|
|
["-Xbinary=objcExportDisableSwiftMemberNameMangling=true"],
|
|
[ '-D', 'DISABLE_MEMBER_NAME_MANGLING' ],
|
|
false,
|
|
false
|
|
)
|
|
objcExportTest(
|
|
ObjCExportAllTask,
|
|
'NoInterfaceMemberNameMangling',
|
|
["-Xbinary=objcExportIgnoreInterfaceMethodCollisions=true"],
|
|
[ '-D', 'DISABLE_INTERFACE_METHOD_NAME_MANGLING' ],
|
|
false,
|
|
false
|
|
)
|
|
|
|
objcExportTest(
|
|
ObjCExportAllTask,
|
|
'Static',
|
|
["-Xbinary=objcExportSuspendFunctionLaunchThreadRestriction=none"],
|
|
[ '-D', 'ALLOW_SUSPEND_ANY_THREAD' ],
|
|
true,
|
|
false
|
|
)
|
|
|
|
|
|
frameworkTest('testValuesGenericsFramework') {
|
|
framework('ValuesGenerics') {
|
|
sources = ['objcexport/values.kt', 'framework/values_generics']
|
|
}
|
|
swiftSources = ['framework/values_generics/']
|
|
}
|
|
|
|
frameworkTest("testStdlibFramework") {
|
|
framework('Stdlib') {
|
|
sources = ['framework/stdlib']
|
|
}
|
|
swiftSources = ['framework/stdlib/']
|
|
}
|
|
|
|
if (cacheTesting != null && cacheTesting.isDynamic) {
|
|
// testMultipleFrameworks disabled until https://youtrack.jetbrains.com/issue/KT-34262 is fixed.
|
|
} else frameworkTest("testMultipleFrameworks") {
|
|
framework('First') {
|
|
sources = ['framework/multiple/framework1', 'framework/multiple/shared']
|
|
}
|
|
framework('Second') {
|
|
sources = ['framework/multiple/framework2', 'framework/multiple/shared']
|
|
}
|
|
swiftSources = ['framework/multiple']
|
|
}
|
|
|
|
frameworkTest("testMultipleFrameworksStatic") {
|
|
// this test doesn't work with caches.
|
|
if (cacheTesting != null && !runtimeAssertionsPanic) {
|
|
// See https://youtrack.jetbrains.com/issue/KT-34261.
|
|
expectedExitStatus = 134
|
|
}
|
|
|
|
framework('FirstStatic') {
|
|
artifact = 'First'
|
|
sources = ['framework/multiple/framework1', 'framework/multiple/shared']
|
|
isStatic = true
|
|
opts = ['-Xstatic-framework', "-Xpre-link-caches=enable"]
|
|
}
|
|
framework('SecondStatic') {
|
|
artifact = 'Second'
|
|
sources = ['framework/multiple/framework2', 'framework/multiple/shared']
|
|
isStatic = true
|
|
opts = ['-Xstatic-framework', "-Xpre-link-caches=enable"]
|
|
}
|
|
codesign = false
|
|
swiftSources = ['framework/multiple']
|
|
}
|
|
|
|
frameworkTest("testGh3343Framework") {
|
|
framework('Gh3343') {
|
|
sources = ['framework/gh3343']
|
|
libraries = ['objcGh3343']
|
|
}
|
|
swiftSources = ['framework/gh3343/']
|
|
}
|
|
|
|
frameworkTest("testKt42397Framework") {
|
|
enabled = !project.globalTestArgs.contains('-opt')
|
|
framework("Kt42397") {
|
|
sources = ['framework/kt42397']
|
|
}
|
|
swiftSources = ['framework/kt42397']
|
|
}
|
|
|
|
frameworkTest("testKt43517Framework") {
|
|
framework('Kt43517') {
|
|
sources = ['framework/kt43517']
|
|
libraries = ['objcKt43517']
|
|
}
|
|
swiftSources = ['framework/kt43517/']
|
|
}
|
|
|
|
frameworkTest("testStackTraceFramework") {
|
|
enabled = !project.globalTestArgs.contains('-opt')
|
|
framework('Stacktrace') {
|
|
sources = ['framework/stacktrace']
|
|
opts = ['-g']
|
|
}
|
|
swiftSources = ['framework/stacktrace/']
|
|
}
|
|
|
|
frameworkTest("testStackTraceBridgesFramework") {
|
|
enabled = !project.globalTestArgs.contains('-opt')
|
|
framework('StacktraceBridges') {
|
|
sources = ['framework/stacktraceBridges']
|
|
opts = ['-g']
|
|
}
|
|
swiftSources = ['framework/stacktraceBridges/']
|
|
}
|
|
|
|
|
|
frameworkTest("testStackTraceByLibbacktraceFramework") {
|
|
enabled = !project.globalTestArgs.contains('-opt')
|
|
framework('StacktraceByLibbacktrace') {
|
|
sources = ['framework/stacktraceByLibbacktrace']
|
|
opts = ['-g', '-Xbinary=sourceInfoType=libbacktrace']
|
|
}
|
|
swiftSources = ['framework/stacktraceByLibbacktrace/']
|
|
}
|
|
|
|
frameworkTest("testAbstractInstantiationFramework") {
|
|
framework('AbstractInstantiation') {
|
|
sources = ['framework/abstractInstantiation']
|
|
}
|
|
swiftSources = ['framework/abstractInstantiation/']
|
|
expectedExitStatus = 134
|
|
}
|
|
|
|
frameworkTest("testFrameworkBundleId") {
|
|
def currentTarget = project.target.name
|
|
enabled = currentTarget.startsWith("mac")
|
|
|
|
framework("Foo") {
|
|
sources = ["framework/bundle_id/main.kt", "framework/bundle_id/lib.kt"]
|
|
opts = ["-Xbinary=bundleVersion=FooBundleVersion", "-Xbinary=bundleShortVersionString=FooBundleShortVersionString"]
|
|
}
|
|
swiftSources = []
|
|
|
|
doLast {
|
|
def frameworkPath = "$testOutputFramework/testFrameworkBundleId/$target/Foo.framework"
|
|
def bundleIdPattern = ~"<key>CFBundleIdentifier</key>\n\\s*<string>Foo</string>"
|
|
def bundleShortVersionStringPattern = ~"<key>CFBundleShortVersionString</key>\n\\s*<string>FooBundleShortVersionString</string>"
|
|
def bundleVersionPattern = ~"<key>CFBundleVersion</key>\n\\s*<string>FooBundleVersion</string>"
|
|
def plistContent = file("$frameworkPath/Resources/Info.plist").text
|
|
if (!bundleIdPattern.matcher(plistContent).find()) {
|
|
throw new Error("Unexpected CFBundleIdentifier in Info.plist:\n$plistContent")
|
|
}
|
|
if (!bundleShortVersionStringPattern.matcher(plistContent).find()) {
|
|
throw new Error("Unexpected CFBundleShortVersionString in Info.plist:\n$plistContent")
|
|
}
|
|
if (!bundleVersionPattern.matcher(plistContent).find()) {
|
|
throw new Error("Unexpected CFBundleVersion in Info.plist:\n$plistContent")
|
|
}
|
|
}
|
|
}
|
|
|
|
frameworkTest("testForwardDeclarationsFramework") {
|
|
framework('ForwardDeclarations') {
|
|
sources = ['framework/forwardDeclarations']
|
|
libraries = ['frameworkForwardDeclarations']
|
|
}
|
|
swiftSources = ['framework/forwardDeclarations/']
|
|
}
|
|
|
|
frameworkTest("testFrameworkUsesFoundationModule") {
|
|
framework("Bar") {
|
|
sources = ["framework/use_foundation_module/framework.kt"]
|
|
}
|
|
swiftSources = []
|
|
doLast {
|
|
def frameworkPath = "$testOutputFramework/testFrameworkUsesFoundationModule/$target/Bar.framework"
|
|
def moduleMapContent = file("$frameworkPath/Modules/module.modulemap").text
|
|
def useFoundationPattern = ~"use Foundation"
|
|
if (!useFoundationPattern.matcher(moduleMapContent).find()) {
|
|
throw new Error("Expected use of Foundation module:\n$moduleMapContent")
|
|
}
|
|
}
|
|
}
|
|
|
|
frameworkTest("testKt56233Framework") {
|
|
framework("Kt56233") {
|
|
sources = ['framework/kt56233']
|
|
}
|
|
swiftSources = ['framework/kt56233']
|
|
if (isAggressiveGC) {
|
|
swiftExtraOpts += ["-D", "AGGRESSIVE_GC"]
|
|
}
|
|
}
|
|
|
|
frameworkTest("testKt57791Framework") {
|
|
framework("Kt57791") {
|
|
sources = ['framework/kt57791']
|
|
}
|
|
swiftSources = ['framework/kt57791']
|
|
}
|
|
|
|
frameworkTest("testPermanentObjectsFramework") {
|
|
enabled = !isNoopGC // Requires gc to actually happen.
|
|
framework("PermanentObjects") {
|
|
sources = ['framework/permanentObjects']
|
|
opts = ['-opt-in=kotlin.native.internal.InternalForKotlinNative']
|
|
}
|
|
swiftSources = ['framework/permanentObjects']
|
|
}
|
|
}
|
|
|
|
tasks.register("override_konan_properties0", KonanDriverTest) {
|
|
disabled = isAggressiveGC // No need to test with different GC schedulers
|
|
def overrides = PlatformInfo.isWindows()
|
|
? '-Xoverride-konan-properties="llvmInlineThreshold=76"'
|
|
: '-Xoverride-konan-properties=llvmInlineThreshold=76'
|
|
flags = [
|
|
"-opt",
|
|
"-Xverbose-phases=MandatoryBitcodeLLVMPostprocessingPhase",
|
|
overrides
|
|
]
|
|
compilerMessages = true
|
|
source = "link/ir_providers/hello.kt"
|
|
def messages = "inline_threshold: 76\nhello\n"
|
|
outputChecker = { out ->
|
|
messages.split("\n")
|
|
.collect { line -> out.contains(line) }
|
|
.every { it == true }
|
|
}
|
|
}
|
|
|
|
tasks.register("llvm_variant_dev", KonanDriverTest) {
|
|
// We use clang from Xcode on macOS for apple targets,
|
|
// so it is hard to reliably detect LLVM variant for these targets.
|
|
disabled = PlatformInfo.isAppleTarget(project)
|
|
|| isAggressiveGC // No need to test with different GC schedulers
|
|
flags = [
|
|
"-Xllvm-variant=dev",
|
|
"-Xverbose-phases=ObjectFiles"
|
|
]
|
|
compilerMessages = true
|
|
source = "link/ir_providers/hello.kt"
|
|
// User LLVM variant has "essentials" suffix.
|
|
def message = "-essentials"
|
|
outputChecker = { out -> !out.contains(message) }
|
|
}
|
|
|
|
/**
|
|
* Builds tests into a single binary with TestRunner
|
|
*/
|
|
task buildKonanTests { t ->
|
|
def compileList = [ "codegen", "datagen", "lower", "runtime", "serialization", "sanity" ]
|
|
|
|
// These tests should not be built into the TestRunner's test executable
|
|
def excludeList = [ "codegen/inline/returnLocalClassFromBlock.kt" ]
|
|
project.tasks
|
|
.withType(KonanStandaloneTest.class)
|
|
.each {
|
|
// add library and source files
|
|
if (it.source != null) {
|
|
excludeList += it.source
|
|
}
|
|
}
|
|
def sources = UtilsKt.getFilesToCompile(project, compileList, excludeList)
|
|
|
|
konanArtifacts {
|
|
program('localTest', targets: [target.name]) {
|
|
srcFiles sources
|
|
baseDir testOutputLocal
|
|
extraOpts '-ea' // Without this option assertions would remain inactive.
|
|
extraOpts '-tr'
|
|
extraOpts '-Xverify-ir=error'
|
|
extraOpts project.globalTestArgs
|
|
}
|
|
}
|
|
|
|
// Set build dependencies.
|
|
dependsOn compileKonanLocalTest
|
|
def buildTask = UtilsKt.findKonanBuildTask(project, "localTest", target)
|
|
UtilsKt.dependsOnDist(buildTask)
|
|
|
|
// Local tests build into a single binary should depend on this task
|
|
project.tasks
|
|
.withType(KonanLocalTest.class)
|
|
.matching { !(it instanceof KonanStandaloneTest) }
|
|
.configureEach { it.dependsOn(t) }
|
|
}
|
|
|
|
|
|
sourceSets {
|
|
nopPlugin {
|
|
kotlin {
|
|
srcDir 'extensions/nop/src/main/kotlin'
|
|
}
|
|
}
|
|
}
|
|
|
|
compileNopPluginKotlin {
|
|
kotlinOptions.freeCompilerArgs += ['-Xskip-prerelease-check']
|
|
}
|
|
|
|
Task pluginTest(String name, String pluginName, Closure configureClosure) {
|
|
def jarTask = project.tasks.register("jar-$pluginName", Jar) {
|
|
it.dependsOn("compile${pluginName.capitalize()}Kotlin")
|
|
from {
|
|
sourceSets[pluginName].output
|
|
}
|
|
archiveBaseName = pluginName
|
|
destinationDirectory = project.layout.buildDirectory.get().asFile
|
|
}
|
|
def taskName = "$name-with-$pluginName"
|
|
return KotlinNativeTestKt.createTest(project, taskName, KonanStandaloneTest) { task ->
|
|
task.configure(configureClosure)
|
|
task.dependsOn(jarTask)
|
|
if (task.enabled) {
|
|
konanArtifacts {
|
|
program(taskName, targets: [target.name]) {
|
|
baseDir "$testOutputLocal/$taskName"
|
|
srcFiles task.getSources()
|
|
extraOpts task.flags + "-Xplugin=${project.layout.buildDirectory.file("nop-plugin.jar").get().asFile}"
|
|
extraOpts project.globalTestArgs
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pluginTest("runtime_basic_init", "nopPlugin") {
|
|
source = "runtime/basic/runtime_basic_init.kt"
|
|
flags = ["-tr"]
|
|
}
|
|
|
|
|
|
Task fileCheckTest(String name, Closure<FileCheckTest> configureClosure) {
|
|
return project.tasks.create(name, FileCheckTest) { FileCheckTest task ->
|
|
task.configure(configureClosure)
|
|
task.llvmIr = project.file("$testOutputFileCheck/$name/$target/out.${task.phaseToCheck}.ll")
|
|
|
|
KonanTarget target = task.target
|
|
boolean isCrossCompiling = target != project.target
|
|
|
|
// Bitcode that is generated in presence of caches or two-stage compilation differs from the "closed world"-generated,
|
|
// so disable these tests for now.
|
|
if (task.enabled && twoStageEnabled)
|
|
task.enabled = false
|
|
|
|
if (task.enabled) {
|
|
konanArtifacts {
|
|
def lib = task.interop
|
|
if (lib != null) {
|
|
UtilsKt.dependsOnKonanBuildingTask(task, lib, target)
|
|
}
|
|
if (!task.generateFramework) {
|
|
// We could use `bitcode` here to make things faster. But:
|
|
// 1. `bitcode` has no other usages.
|
|
// 2. Unification should help porting to the new test infra.
|
|
// 3. Compiler might behave differently when outputting bitcode instead of object files.
|
|
program(name, targets: [target]) {
|
|
srcFiles task.annotatedSource
|
|
baseDir "$testOutputFileCheck/$name"
|
|
if (!isCrossCompiling) {
|
|
extraOpts project.globalTestArgs
|
|
}
|
|
extraOpts task.extraOpts
|
|
extraOpts "-Xsave-llvm-ir-directory=$testOutputFileCheck/$name/$target"
|
|
extraOpts "-Xsave-llvm-ir-after=${task.phaseToCheck}"
|
|
if (lib != null) {
|
|
libraries {
|
|
artifact lib
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
// Framework support is much weakier than `frameworkTest`, but we don't need much.
|
|
framework(name, targets: [target]) {
|
|
srcFiles task.annotatedSource
|
|
baseDir "$testOutputFileCheck/$name"
|
|
if (!isCrossCompiling) {
|
|
extraOpts project.globalTestArgs
|
|
}
|
|
extraOpts "-Xsave-llvm-ir-directory=$testOutputFileCheck/$name/$target"
|
|
extraOpts "-Xsave-llvm-ir-after=${task.phaseToCheck}"
|
|
|
|
if (lib != null) {
|
|
libraries {
|
|
artifact lib
|
|
}
|
|
}
|
|
}
|
|
}
|
|
UtilsKt.dependsOnKonanBuildingTask(task, name, target)
|
|
}
|
|
task.dependsOn(nativeDependencies.llvmDependency)
|
|
}
|
|
}
|
|
}
|
|
|
|
createInterop("filecheck_signext_zeroext_interop_input") {
|
|
it.defFile 'filecheck/signext_zeroext_interop_input.def'
|
|
}
|
|
|
|
fileCheckTest("filecheck_signext_zeroext_interop") {
|
|
enabled = enabled && cacheTesting == null
|
|
annotatedSource = project.file('filecheck/signext_zeroext_interop.kt')
|
|
interop = "filecheck_signext_zeroext_interop_input"
|
|
if (project.testTarget == 'mingw_x64') {
|
|
checkPrefix = "CHECK-WINDOWSX64"
|
|
} else if (!target.family.appleFamily && target.architecture == Architecture.ARM64) {
|
|
checkPrefix = "CHECK-AAPCS"
|
|
}
|
|
}
|
|
|
|
fileCheckTest("filecheck_signext_zeroext_objc_export") {
|
|
annotatedSource = project.file('filecheck/signext_zeroext_objc_export.kt')
|
|
generateFramework = true
|
|
enabled = target.family.appleFamily
|
|
}
|
|
|
|
fileCheckTest("filecheck_objc_direct") {
|
|
enabled = enabled && cacheTesting == null
|
|
annotatedSource = project.file('filecheck/objc_direct.kt')
|
|
interop = "objcDirect"
|
|
enabled = target.family.appleFamily
|
|
}
|
|
|
|
|
|
dependencies {
|
|
nopPluginApi kotlinCompilerModule
|
|
nopPluginApi project(":native:kotlin-native-utils")
|
|
nopPluginApi project(":core:descriptors")
|
|
nopPluginApi project(":compiler:ir.tree")
|
|
nopPluginApi project(":compiler:ir.backend.common")
|
|
nopPluginApi project(":compiler:util")
|
|
nopPluginApi project(":native:frontend.native")
|
|
nopPluginApi project(":compiler:cli-common")
|
|
nopPluginApi project(":compiler:cli-base")
|
|
nopPluginApi project(":compiler:cli")
|
|
nopPluginApi project(":kotlin-util-klib")
|
|
nopPluginApi project(":kotlin-util-klib-metadata")
|
|
nopPluginApi project(":compiler:ir.serialization.common")
|
|
|
|
implementation kotlinCompilerModule
|
|
api project(path: ':kotlin-native:backend.native', configuration: 'cli_bcApiElements')
|
|
api libs.junit4
|
|
}
|
|
|
|
project.afterEvaluate {
|
|
// Don't treat any task as up-to-date, no matter what.
|
|
// Note: this project should contain only test tasks, including ones that build binaries,
|
|
// and ones that run binaries.
|
|
// So the configuration below mostly means "tests aren't up-to-date".
|
|
tasks.configureEach {
|
|
outputs.upToDateWhen { false }
|
|
}
|
|
}
|