| /* |
| * 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.isWithStateChecker = project.globalTestArgs.contains("-Xbinary=checkStateAtExternalCalls=true") || project.globalTestArgs.contains("-Xcheck-state-at-external-calls") |
| 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") |
| } |
| 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 regular gradle test tasks |
| dependsOn(tasks.withType(Test).matching { it.enabled }) |
| // TODO(KTI-1571): This task should be run by Compiler Unit Tests (Native) configuration |
| dependsOn(":nativeCompilerUnitTest") |
| // TODO(KTI-1571): This should be run by Compiler Tests (Native) configuration |
| dependsOn(":native:objcexport-header-generator: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"] |
| outputChecker = { |
| !it.contains("testExecuteAfterStartQuiet error") && it.contains("testExecuteStart error") && !it.contains("testExecuteStartQuiet error") |
| } |
| source = "runtime/workers/worker_exceptions.kt" |
| } |
| |
| standaloneTest("worker_exceptions_terminate") { |
| expectedExitStatusChecker = { it != 0 } |
| outputChecker = { |
| it.contains("some error") && !it.contains("Will not happen") |
| } |
| source = "runtime/workers/worker_exceptions_terminate.kt" |
| } |
| |
| standaloneTest("worker_exceptions_terminate_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_current") { |
| 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_hook_current") { |
| 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"] |
| } |
| |
| // 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("workerSignals") { |
| it.defFile "interop/workerSignals/workerSignals.def" |
| it.headers "$projectDir/interop/workerSignals/workerSignals.h" |
| it.extraOpts "-Xcompile-source", "$projectDir/interop/workerSignals/workerSignals.cpp" |
| } |
| |
| if (PlatformInfo.isAppleTarget(project)) { |
| 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("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("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_kt55938") { |
| it.defFile 'interop/objc/kt55938/objclib.def' |
| it.headers "$projectDir/interop/objc/kt55938/objclib.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("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("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' |
| } |
| |
| 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_workerSignals") { |
| disabled = project.testTarget == 'mingw_x64' // cross-thread signalling does not work on Windows |
| source = "interop/workerSignals/workerSignals.kt" |
| interop = "workerSignals" |
| } |
| |
| /* |
| 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)) { |
| 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_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_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_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 |
| && !isWithStateChecker // TODO(KT-65261) |
| 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 |
| } |
| |
| 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"] |
| } |
| |
| 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 } |
| } |
| } |