diff --git a/kotlin-native/backend.native/tests/build.gradle b/kotlin-native/backend.native/tests/build.gradle index 904912ea842..12fc374701d 100644 --- a/kotlin-native/backend.native/tests/build.gradle +++ b/kotlin-native/backend.native/tests/build.gradle @@ -973,82 +973,11 @@ createInterop("kt43502") { } } -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" -} - 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 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 configureClosure) { - return interopTestBase(name, false, false, configureClosure) -} - -Task interopTestMultifile(String name, Closure configureClosure) { - return interopTestBase(name, true, false, configureClosure) -} - standaloneTest("interop_objc_allocException") { disabled = !PlatformInfo.isAppleTarget(project) expectedExitStatus = 0 @@ -1063,19 +992,6 @@ dynamicTest("interop_kt43502") { 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" -} - if (PlatformInfo.isAppleTarget(project)) { standaloneTest("interop_objc_kt61441") { source = "interop/objc/kt61441.kt" diff --git a/kotlin-native/backend.native/tests/interop/leakMemoryWithRunningThread/checked.kt b/kotlin-native/backend.native/tests/interop/leakMemoryWithRunningThread/checked.kt deleted file mode 100644 index 01a70a596a7..00000000000 --- a/kotlin-native/backend.native/tests/interop/leakMemoryWithRunningThread/checked.kt +++ /dev/null @@ -1,29 +0,0 @@ -@file:OptIn(kotlin.experimental.ExperimentalNativeApi::class, kotlin.native.runtime.NativeRuntimeApi::class) - -import leakMemory.* -import kotlin.concurrent.AtomicInt -import kotlin.native.concurrent.* -import kotlin.native.Platform -import kotlin.test.* -import kotlinx.cinterop.* - -val global = AtomicInt(0) - -fun ensureInititalized() { - // Only needed with the legacy MM. TODO: Remove when legacy MM is gone. - kotlin.native.initRuntimeIfNeeded() - // Leak memory - StableRef.create(Any()) - global.value = 1 -} - -fun main() { - Platform.isMemoryLeakCheckerActive = true - kotlin.native.runtime.Debugging.forceCheckedShutdown = true - assertTrue(global.value == 0) - // Created a thread, made sure Kotlin is initialized there. - test_RunInNewThread(staticCFunction(::ensureInititalized)) - assertTrue(global.value == 1) - // Now exiting. With checked shutdown we will fail, complaining there're - // unfinished threads with runtimes. -} diff --git a/kotlin-native/backend.native/tests/interop/leakMemoryWithRunningThread/leakMemory.cpp b/kotlin-native/backend.native/tests/interop/leakMemoryWithRunningThread/leakMemory.cpp deleted file mode 100644 index 7e213990ab3..00000000000 --- a/kotlin-native/backend.native/tests/interop/leakMemoryWithRunningThread/leakMemory.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "leakMemory.h" - -#include -#include - -extern "C" void test_RunInNewThread(void (*f)()) { - std::atomic haveRun(false); - std::thread t([f, &haveRun]() { - f(); - haveRun = true; - while (true) {} - }); - t.detach(); - while (!haveRun) {} -} diff --git a/kotlin-native/backend.native/tests/interop/leakMemoryWithRunningThread/leakMemory.def b/kotlin-native/backend.native/tests/interop/leakMemoryWithRunningThread/leakMemory.def deleted file mode 100644 index e487579d85a..00000000000 --- a/kotlin-native/backend.native/tests/interop/leakMemoryWithRunningThread/leakMemory.def +++ /dev/null @@ -1,5 +0,0 @@ -package leakMemory - ---- - -void test_RunInNewThread(void (*)()); diff --git a/kotlin-native/backend.native/tests/interop/leakMemoryWithRunningThread/leakMemory.h b/kotlin-native/backend.native/tests/interop/leakMemoryWithRunningThread/leakMemory.h deleted file mode 100644 index 2342ed9c920..00000000000 --- a/kotlin-native/backend.native/tests/interop/leakMemoryWithRunningThread/leakMemory.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifdef __cplusplus -extern "C" { -#endif - -void test_RunInNewThread(void (*)()); - -#ifdef __cplusplus -} -#endif diff --git a/kotlin-native/backend.native/tests/interop/workerSignals/workerSignals.cpp b/kotlin-native/backend.native/tests/interop/workerSignals/workerSignals.cpp deleted file mode 100644 index 383a58fe32a..00000000000 --- a/kotlin-native/backend.native/tests/interop/workerSignals/workerSignals.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "workerSignals.h" - -#include -#include -#include -#include - -namespace { - -int pendingValue = 0; -thread_local int value = 0; - -void signalHandler(int signal) { - value = pendingValue; -} - -} // namespace - -extern "C" void setupSignalHandler(void) { - signal(SIGUSR1, &signalHandler); -} - -extern "C" void signalThread(uint64_t thread, int value) { - pendingValue = value; - pthread_t t = {}; - memcpy(&t, &thread, sizeof(pthread_t)); - auto result = pthread_kill(t, SIGUSR1); - assert(result == 0); -} - -extern "C" int getValue(void) { - return value; -} diff --git a/kotlin-native/backend.native/tests/interop/workerSignals/workerSignals.def b/kotlin-native/backend.native/tests/interop/workerSignals/workerSignals.def deleted file mode 100644 index 4bf83f1d95c..00000000000 --- a/kotlin-native/backend.native/tests/interop/workerSignals/workerSignals.def +++ /dev/null @@ -1,2 +0,0 @@ -language = C -headerFilter = **/workerSignals.h diff --git a/kotlin-native/backend.native/tests/interop/workerSignals/workerSignals.h b/kotlin-native/backend.native/tests/interop/workerSignals/workerSignals.h deleted file mode 100644 index 0ce39b76e3f..00000000000 --- a/kotlin-native/backend.native/tests/interop/workerSignals/workerSignals.h +++ /dev/null @@ -1,13 +0,0 @@ -#include - -#ifdef __cplusplus -extern "C" { -#endif - -void setupSignalHandler(void); -void signalThread(uint64_t thread, int value); -int getValue(void); - -#ifdef __cplusplus -} -#endif diff --git a/kotlin-native/backend.native/tests/interop/workerSignals/workerSignals.kt b/kotlin-native/backend.native/tests/interop/workerSignals/workerSignals.kt deleted file mode 100644 index 7fd22ce7b9f..00000000000 --- a/kotlin-native/backend.native/tests/interop/workerSignals/workerSignals.kt +++ /dev/null @@ -1,27 +0,0 @@ -@file:OptIn(kotlin.ExperimentalStdlibApi::class, ObsoleteWorkersApi::class) - -import kotlin.native.concurrent.* -import kotlin.test.* -import workerSignals.* - -const val defaultValue = 0 -const val newValue = 42 - -fun main() { - setupSignalHandler() - - withWorker { - val before = execute(TransferMode.SAFE, {}) { - getValue() - }.result - assertEquals(defaultValue, getValue()) - assertEquals(defaultValue, before) - - signalThread(platformThreadId, newValue) - val after = execute(TransferMode.SAFE, {}) { - getValue() - }.result - assertEquals(defaultValue, getValue()) - assertEquals(newValue, after) - } -} diff --git a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/KotlinNativeTest.kt b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/KotlinNativeTest.kt index e712c60a0a5..e032295ef10 100644 --- a/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/KotlinNativeTest.kt +++ b/kotlin-native/build-tools/src/main/kotlin/org/jetbrains/kotlin/KotlinNativeTest.kt @@ -416,22 +416,6 @@ open class KonanDriverTest : KonanStandaloneTest() { } } -open class KonanInteropTest : KonanStandaloneTest() { - /** - * Name of the interop library - */ - @Input - lateinit var interop: String - - @Input - @Optional - var interop2: String? = null - - @Input - @Optional - var lib: String? = null -} - /** * Test task to check a library built by `-produce dynamic`. * C source code should contain `testlib` as a reference to a testing library. diff --git a/native/native.tests/testData/standalone/checkers/leakMemoryWithRunningThreadChecked.kt b/native/native.tests/testData/standalone/checkers/leakMemoryWithRunningThreadChecked.kt new file mode 100644 index 00000000000..80b3434cbf0 --- /dev/null +++ b/native/native.tests/testData/standalone/checkers/leakMemoryWithRunningThreadChecked.kt @@ -0,0 +1,68 @@ +// EXIT_CODE: !0 +// OUTPUT_REGEX: Cannot run checkers when there are 1 alive runtimes at the shutdown.* +// MODULE: cinterop +// FILE: leakMemory.def +--- +void test_RunInNewThread(void (*)()); + +// FILE: leakMemory.h +#ifdef __cplusplus +extern "C" { +#endif + +void test_RunInNewThread(void (*)()); + +#ifdef __cplusplus +} +#endif + +// FILE: leakMemory.cpp +#include "leakMemory.h" + +#include +#include + +extern "C" void test_RunInNewThread(void (*f)()) { + std::atomic haveRun(false); + std::thread t([f, &haveRun]() { + f(); + haveRun = true; + while (true) {} + }); + t.detach(); + while (!haveRun) {} +} + +// MODULE: main(cinterop) +// FILE: main.kt +@file:OptIn( + kotlin.experimental.ExperimentalNativeApi::class, + kotlin.native.runtime.NativeRuntimeApi::class, + kotlinx.cinterop.ExperimentalForeignApi::class +) + +import leakMemory.* +import kotlin.concurrent.AtomicInt +import kotlin.native.concurrent.* +import kotlin.native.Platform +import kotlin.test.* +import kotlinx.cinterop.* + +val global = AtomicInt(0) + +fun ensureInititalized() { + // Leak memory + StableRef.create(Any()) + global.value = 1 +} + +fun main() { + Platform.isMemoryLeakCheckerActive = true + kotlin.native.runtime.Debugging.forceCheckedShutdown = true + assertTrue(global.value == 0) + // Created a thread, made sure Kotlin is initialized there. + test_RunInNewThread(staticCFunction(::ensureInititalized)) + assertTrue(global.value == 1) + // Now exiting. With checked shutdown we will fail, complaining there're + // unfinished threads with runtimes. +} diff --git a/native/native.tests/testData/codegen/cinterop/leakMemoryWithRunningThreadUnchecked.kt b/native/native.tests/testData/standalone/checkers/leakMemoryWithRunningThreadUnchecked.kt similarity index 89% rename from native/native.tests/testData/codegen/cinterop/leakMemoryWithRunningThreadUnchecked.kt rename to native/native.tests/testData/standalone/checkers/leakMemoryWithRunningThreadUnchecked.kt index ae507a31558..b185b5441ae 100644 --- a/native/native.tests/testData/codegen/cinterop/leakMemoryWithRunningThreadUnchecked.kt +++ b/native/native.tests/testData/standalone/checkers/leakMemoryWithRunningThreadUnchecked.kt @@ -1,4 +1,3 @@ -// TARGET_BACKEND: NATIVE // MODULE: cinterop // FILE: leakMemoryWithRunningThreadUnchecked.def --- @@ -51,14 +50,12 @@ import kotlinx.cinterop.* val global = AtomicInt(0) fun ensureInititalized() { - // Only needed with the legacy MM. TODO: Remove when legacy MM is gone. - kotlin.native.initRuntimeIfNeeded() // Leak memory StableRef.create(Any()) global.value = 1 } -fun box(): String { +fun main() { Platform.isMemoryLeakCheckerActive = true kotlin.native.runtime.Debugging.forceCheckedShutdown = false assertTrue(global.value == 0) @@ -67,6 +64,4 @@ fun box(): String { assertTrue(global.value == 1) // Now exiting. With unchecked shutdown, we exit quietly, even though there're // unfinished threads with runtimes. - - return "OK" } diff --git a/native/native.tests/testData/standalone/workerSignals.kt b/native/native.tests/testData/standalone/workerSignals.kt new file mode 100644 index 00000000000..b87e4d8a006 --- /dev/null +++ b/native/native.tests/testData/standalone/workerSignals.kt @@ -0,0 +1,73 @@ +// Cross-thread signalling does not work on Windows +// DISABLE_NATIVE: targetFamily=MINGW +// MODULE: cinterop +// FILE: workerSignals.def +--- +#include +void setupSignalHandler(void); +void signalThread(uint64_t thread, int value); +int getValue(void); + +// FILE: workerSignals.cpp +#include +#include +#include +#include +#include + +namespace { + +int pendingValue = 0; +thread_local int value = 0; + +void signalHandler(int signal) { + value = pendingValue; +} + +} // namespace + +extern "C" void setupSignalHandler(void) { + signal(SIGUSR1, &signalHandler); +} + +extern "C" void signalThread(uint64_t thread, int value) { + pendingValue = value; + pthread_t t = {}; + memcpy(&t, &thread, sizeof(pthread_t)); + auto result = pthread_kill(t, SIGUSR1); + assert(result == 0); +} + +extern "C" int getValue(void) { + return value; +} + +// MODULE: main(cinterop) +// FILE: main.kt +@file:OptIn(kotlin.ExperimentalStdlibApi::class, ObsoleteWorkersApi::class, kotlinx.cinterop.ExperimentalForeignApi::class) + +import kotlin.native.concurrent.* +import kotlin.test.* +import workerSignals.* + +const val defaultValue = 0 +const val newValue = 42 + +fun main() { + setupSignalHandler() + + withWorker { + val before = execute(TransferMode.SAFE, {}) { + getValue() + }.result + assertEquals(defaultValue, getValue()) + assertEquals(defaultValue, before) + + signalThread(platformThreadId, newValue) + val after = execute(TransferMode.SAFE, {}) { + getValue() + }.result + assertEquals(defaultValue, getValue()) + assertEquals(newValue, after) + } +} diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/FirNativeCodegenLocalTestGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/FirNativeCodegenLocalTestGenerated.java index 9b88eb2f9f4..8bfec7e35b4 100644 --- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/FirNativeCodegenLocalTestGenerated.java +++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/FirNativeCodegenLocalTestGenerated.java @@ -225,12 +225,6 @@ public class FirNativeCodegenLocalTestGenerated extends AbstractNativeCodegenBox runTest("native/native.tests/testData/codegen/cinterop/kt64105.kt"); } - @Test - @TestMetadata("leakMemoryWithRunningThreadUnchecked.kt") - public void testLeakMemoryWithRunningThreadUnchecked() { - runTest("native/native.tests/testData/codegen/cinterop/leakMemoryWithRunningThreadUnchecked.kt"); - } - @Test @TestMetadata("toKString.kt") public void testToKString() { diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/FirNativeStandaloneTestGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/FirNativeStandaloneTestGenerated.java index 3bc38bd52ac..1dead826fe6 100644 --- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/FirNativeStandaloneTestGenerated.java +++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/FirNativeStandaloneTestGenerated.java @@ -46,6 +46,39 @@ public class FirNativeStandaloneTestGenerated extends AbstractNativeBlackBoxTest runTest("native/native.tests/testData/standalone/kt56048.kt"); } + @Test + @TestMetadata("workerSignals.kt") + public void testWorkerSignals() { + runTest("native/native.tests/testData/standalone/workerSignals.kt"); + } + + @Nested + @TestMetadata("native/native.tests/testData/standalone/checkers") + @TestDataPath("$PROJECT_ROOT") + @Tag("standalone") + @EnforcedProperty(property = ClassLevelProperty.TEST_KIND, propertyValue = "STANDALONE_NO_TR") + @UseStandardTestCaseGroupProvider() + @Tag("frontend-fir") + @FirPipeline() + public class Checkers { + @Test + public void testAllFilesPresentInCheckers() { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("native/native.tests/testData/standalone/checkers"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("leakMemoryWithRunningThreadChecked.kt") + public void testLeakMemoryWithRunningThreadChecked() { + runTest("native/native.tests/testData/standalone/checkers/leakMemoryWithRunningThreadChecked.kt"); + } + + @Test + @TestMetadata("leakMemoryWithRunningThreadUnchecked.kt") + public void testLeakMemoryWithRunningThreadUnchecked() { + runTest("native/native.tests/testData/standalone/checkers/leakMemoryWithRunningThreadUnchecked.kt"); + } + } + @Nested @TestMetadata("native/native.tests/testData/standalone/console") @TestDataPath("$PROJECT_ROOT") diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/NativeCodegenLocalTestGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/NativeCodegenLocalTestGenerated.java index a1dc32fb933..c7b837db42c 100644 --- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/NativeCodegenLocalTestGenerated.java +++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/NativeCodegenLocalTestGenerated.java @@ -215,12 +215,6 @@ public class NativeCodegenLocalTestGenerated extends AbstractNativeCodegenBoxTes runTest("native/native.tests/testData/codegen/cinterop/kt64105.kt"); } - @Test - @TestMetadata("leakMemoryWithRunningThreadUnchecked.kt") - public void testLeakMemoryWithRunningThreadUnchecked() { - runTest("native/native.tests/testData/codegen/cinterop/leakMemoryWithRunningThreadUnchecked.kt"); - } - @Test @TestMetadata("toKString.kt") public void testToKString() { diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/NativeStandaloneTestGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/NativeStandaloneTestGenerated.java index 2a1f9cb6050..4a95d5cb703 100644 --- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/NativeStandaloneTestGenerated.java +++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/test/blackbox/NativeStandaloneTestGenerated.java @@ -43,6 +43,37 @@ public class NativeStandaloneTestGenerated extends AbstractNativeBlackBoxTest { runTest("native/native.tests/testData/standalone/kt56048.kt"); } + @Test + @TestMetadata("workerSignals.kt") + public void testWorkerSignals() { + runTest("native/native.tests/testData/standalone/workerSignals.kt"); + } + + @Nested + @TestMetadata("native/native.tests/testData/standalone/checkers") + @TestDataPath("$PROJECT_ROOT") + @Tag("standalone") + @EnforcedProperty(property = ClassLevelProperty.TEST_KIND, propertyValue = "STANDALONE_NO_TR") + @UseStandardTestCaseGroupProvider() + public class Checkers { + @Test + public void testAllFilesPresentInCheckers() { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("native/native.tests/testData/standalone/checkers"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("leakMemoryWithRunningThreadChecked.kt") + public void testLeakMemoryWithRunningThreadChecked() { + runTest("native/native.tests/testData/standalone/checkers/leakMemoryWithRunningThreadChecked.kt"); + } + + @Test + @TestMetadata("leakMemoryWithRunningThreadUnchecked.kt") + public void testLeakMemoryWithRunningThreadUnchecked() { + runTest("native/native.tests/testData/standalone/checkers/leakMemoryWithRunningThreadUnchecked.kt"); + } + } + @Nested @TestMetadata("native/native.tests/testData/standalone/console") @TestDataPath("$PROJECT_ROOT")