From 7cb372e66f02941618a5de744c5ffa4a0e4bef60 Mon Sep 17 00:00:00 2001 From: Vladimir Sukharev Date: Wed, 7 Feb 2024 11:50:04 +0100 Subject: [PATCH] [K/N][Tests] Migrate test signext_zeroext_objc_export.kt ^KT-61259 --- .../backend.native/tests/build.gradle | 6 -- .../framework}/signext_zeroext_objc_export.kt | 0 .../konan/test/blackbox/FrameworkTest.kt | 42 +++++++++ .../blackbox/support/runner/ResultHandler.kt | 91 +++++++------------ .../blackbox/support/runner/TestRunChecks.kt | 40 +++++++- 5 files changed, 112 insertions(+), 67 deletions(-) rename {kotlin-native/backend.native/tests/filecheck => native/native.tests/testData/framework}/signext_zeroext_objc_export.kt (100%) diff --git a/kotlin-native/backend.native/tests/build.gradle b/kotlin-native/backend.native/tests/build.gradle index 810cfc348d9..e799acf00bc 100644 --- a/kotlin-native/backend.native/tests/build.gradle +++ b/kotlin-native/backend.native/tests/build.gradle @@ -2016,12 +2016,6 @@ Task fileCheckTest(String name, Closure configureClosure) { } } -fileCheckTest("filecheck_signext_zeroext_objc_export") { - annotatedSource = project.file('filecheck/signext_zeroext_objc_export.kt') - generateFramework = true - enabled = target.family.appleFamily -} - dependencies { nopPluginApi kotlinCompilerModule nopPluginApi project(":native:kotlin-native-utils") diff --git a/kotlin-native/backend.native/tests/filecheck/signext_zeroext_objc_export.kt b/native/native.tests/testData/framework/signext_zeroext_objc_export.kt similarity index 100% rename from kotlin-native/backend.native/tests/filecheck/signext_zeroext_objc_export.kt rename to native/native.tests/testData/framework/signext_zeroext_objc_export.kt diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/FrameworkTest.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/FrameworkTest.kt index cd4b38af731..8b5de04f501 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/FrameworkTest.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/FrameworkTest.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.konan.test.blackbox.support.group.FirPipeline import org.jetbrains.kotlin.konan.test.blackbox.support.runner.TestExecutable import org.jetbrains.kotlin.konan.test.blackbox.support.runner.TestRunCheck import org.jetbrains.kotlin.konan.test.blackbox.support.runner.TestRunChecks +import org.jetbrains.kotlin.konan.test.blackbox.support.runner.doFileCheck import org.jetbrains.kotlin.konan.test.blackbox.support.settings.* import org.jetbrains.kotlin.konan.test.blackbox.support.util.createTestProvider import org.jetbrains.kotlin.native.executors.runProcess @@ -39,6 +40,47 @@ abstract class FrameworkTestBase : AbstractNativeSimpleTest() { private val extras = TestCase.NoTestRunnerExtras("There's no entrypoint in Swift program") private val testCompilationFactory = TestCompilationFactory() + @Test + fun testSignextZeroext() { + Assumptions.assumeTrue(targets.testTarget.family.isAppleFamily) + val fileCheckStage = "CStubs" + val testDataFile = testSuiteDir.resolve("signext_zeroext_objc_export.kt") + val testCase = generateObjCFrameworkTestCase( + TestKind.STANDALONE_NO_TR, + extras, + "SignextZeroext", + listOf(testDataFile), + TestCompilerArgs( + listOf( + "-Xbinary=bundleId=signextZeroext", + "-Xsave-llvm-ir-after=$fileCheckStage", + "-Xsave-llvm-ir-directory=${buildDir.absolutePath}", + ) + ), + givenDependencies = emptySet(), + checks = TestRunChecks.Default(Duration.ZERO) + .copy(fileCheckMatcher = TestRunCheck.FileCheckMatcher(testRunSettings, testDataFile)) + ) + val objCFrameworkCompilation = testCompilationFactory.testCaseToObjCFrameworkCompilation(testCase, testRunSettings) + objCFrameworkCompilation.result.assertSuccess() + + val (result, outText, errText) = doFileCheck( + testCase.checks.fileCheckMatcher!!, + buildDir.resolve("out.$fileCheckStage.ll").also { assert(it.exists()) } + ) + if (!(result == 0 && errText.isEmpty() && outText.isEmpty())) { + val shortOutText = outText.lines().take(100) + val shortErrText = errText.lines().take(100) + assert(false) { + "FileCheck matching of ${buildDir.resolve("out.$fileCheckStage.ll").also { assert(it.exists()) }.absolutePath}\n" + + "with '--check-prefixes ${testCase.checks.fileCheckMatcher.prefixes}'\n" + + "failed with result=$result:\n" + + shortOutText.joinToString("\n") + "\n" + + shortErrText.joinToString("\n") + } + } + } + @Test fun testValuesGenerics() { Assumptions.assumeTrue(targets.testTarget.family.isAppleFamily) diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/support/runner/ResultHandler.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/support/runner/ResultHandler.kt index c601a9ea011..13c6d6bd5e9 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/support/runner/ResultHandler.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/support/runner/ResultHandler.kt @@ -7,19 +7,12 @@ package org.jetbrains.kotlin.konan.test.blackbox.support.runner import com.intellij.openapi.util.SystemInfo import com.intellij.openapi.util.text.StringUtilRt.convertLineSeparators -import org.jetbrains.kotlin.konan.target.Architecture -import org.jetbrains.kotlin.konan.target.KonanTarget -import org.jetbrains.kotlin.konan.target.needSmallBinary import org.jetbrains.kotlin.konan.test.blackbox.support.LoggedData import org.jetbrains.kotlin.konan.test.blackbox.support.TestName import org.jetbrains.kotlin.konan.test.blackbox.support.runner.TestRunCheck.ExecutionTimeout import org.jetbrains.kotlin.konan.test.blackbox.support.runner.TestRunCheck.ExitCode -import org.jetbrains.kotlin.konan.test.blackbox.support.settings.CacheMode -import org.jetbrains.kotlin.konan.test.blackbox.support.settings.KotlinNativeTargets -import org.jetbrains.kotlin.konan.test.blackbox.support.settings.OptimizationMode import org.jetbrains.kotlin.konan.test.blackbox.support.settings.configurables import org.jetbrains.kotlin.konan.test.blackbox.support.util.TestReport -import org.jetbrains.kotlin.util.capitalizeDecapitalize.toUpperCaseAsciiOnly import org.junit.jupiter.api.Assumptions import java.io.File @@ -85,57 +78,16 @@ internal class ResultHandler( } } is TestRunCheck.FileCheckMatcher -> { - val fileCheckExecutable = check.settings.configurables.absoluteLlvmHome + File.separator + "bin" + File.separator + - if (SystemInfo.isWindows) "FileCheck.exe" else "FileCheck" - require(File(fileCheckExecutable).exists()) { - "$fileCheckExecutable does not exist. Make sure Distribution for `settings.configurables` " + - "was created using `propertyOverrides` to specify development variant of LLVM instead of user variant." - } val fileCheckDump = runResult.testExecutable.executable.fileCheckDump!! - val fileCheckOut = File(fileCheckDump.absolutePath + ".out") - val fileCheckErr = File(fileCheckDump.absolutePath + ".err") - - val testTarget = check.settings.get().testTarget - val checkPrefixes = buildList { - add("CHECK") - add("CHECK-${testTarget.abiInfoString}") - add("CHECK-${testTarget.name.toUpperCaseAsciiOnly()}") - if (testTarget.family.isAppleFamily) { - add("CHECK-APPLE") - } - if (testTarget.needSmallBinary()) { - add("CHECK-SMALLBINARY") - } else { - add("CHECK-BIGBINARY") - } - } - val optimizationMode = check.settings.get().name - val checkPrefixesWithOptMode = checkPrefixes.map { "$it-$optimizationMode" } - val cacheMode = check.settings.get().alias - val checkPrefixesWithCacheMode = checkPrefixes.map { "$it-CACHE_$cacheMode" } - val commaSeparatedCheckPrefixes = (checkPrefixes + checkPrefixesWithOptMode + checkPrefixesWithCacheMode).joinToString(",") - - val result = ProcessBuilder( - fileCheckExecutable, - check.testDataFile.absolutePath, - "--input-file", - fileCheckDump.absolutePath, - "--check-prefixes", commaSeparatedCheckPrefixes, - "--allow-deprecated-dag-overlap" // TODO specify it via new test directive for `function_attributes_at_callsite.kt` - ).redirectOutput(fileCheckOut) - .redirectError(fileCheckErr) - .start() - .waitFor() - val errText = fileCheckErr.readText() - val outText = fileCheckOut.readText() - if(!(result == 0 && errText.isEmpty() && outText.isEmpty())) { + val (result, outText, errText) = doFileCheck(check, fileCheckDump) + if (!(result == 0 && errText.isEmpty() && outText.isEmpty())) { val shortOutText = outText.lines().take(100) val shortErrText = errText.lines().take(100) add("FileCheck matching of ${fileCheckDump.absolutePath}\n" + - "with '--check-prefixes $commaSeparatedCheckPrefixes'\n" + - "failed with result=$result:\n" + - shortOutText.joinToString("\n") + "\n" + - shortErrText.joinToString("\n") + "with '--check-prefixes ${check.prefixes}'\n" + + "failed with result=$result:\n" + + shortOutText.joinToString("\n") + "\n" + + shortErrText.joinToString("\n") ) } } @@ -195,10 +147,29 @@ internal class ResultHandler( } } -// Shameless borrowing `val KonanTarget.abiInfo` from module `:kotlin-native:backend.native`, which cannot be imported here for now. -private val KonanTarget.abiInfoString: String - get() = when { - this == KonanTarget.MINGW_X64 -> "WINDOWSX64" - !family.isAppleFamily && architecture == Architecture.ARM64 -> "AAPCS" - else -> "DEFAULTABI" +internal fun doFileCheck(check: TestRunCheck.FileCheckMatcher, fileCheckDump: File): Triple { + val fileCheckExecutable = check.settings.configurables.absoluteLlvmHome + File.separator + "bin" + File.separator + + if (SystemInfo.isWindows) "FileCheck.exe" else "FileCheck" + require(File(fileCheckExecutable).exists()) { + "$fileCheckExecutable does not exist. Make sure Distribution for `settings.configurables` " + + "was created using `propertyOverrides` to specify development variant of LLVM instead of user variant." } + val fileCheckOut = File(fileCheckDump.absolutePath + ".out") + val fileCheckErr = File(fileCheckDump.absolutePath + ".err") + + val result = ProcessBuilder( + fileCheckExecutable, + check.testDataFile.absolutePath, + "--input-file", + fileCheckDump.absolutePath, + "--check-prefixes", check.prefixes, + "--allow-deprecated-dag-overlap" // TODO specify it via new test directive for `function_attributes_at_callsite.kt` + ).redirectOutput(fileCheckOut) + .redirectError(fileCheckErr) + .start() + .waitFor() + val outText = fileCheckOut.readText() + val errText = fileCheckErr.readText() + + return Triple(result, outText, errText) +} diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/support/runner/TestRunChecks.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/support/runner/TestRunChecks.kt index 3cd12a62494..4f7a57c0e60 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/support/runner/TestRunChecks.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/test/blackbox/support/runner/TestRunChecks.kt @@ -5,8 +5,15 @@ package org.jetbrains.kotlin.konan.test.blackbox.support.runner +import org.jetbrains.kotlin.konan.target.Architecture +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.konan.target.needSmallBinary import org.jetbrains.kotlin.konan.test.blackbox.support.runner.TestRunCheck.* +import org.jetbrains.kotlin.konan.test.blackbox.support.settings.CacheMode +import org.jetbrains.kotlin.konan.test.blackbox.support.settings.KotlinNativeTargets +import org.jetbrains.kotlin.konan.test.blackbox.support.settings.OptimizationMode import org.jetbrains.kotlin.konan.test.blackbox.support.settings.Settings +import org.jetbrains.kotlin.util.capitalizeDecapitalize.toUpperCaseAsciiOnly import org.jetbrains.kotlin.utils.yieldIfNotNull import java.io.File import kotlin.time.Duration @@ -36,7 +43,30 @@ internal sealed interface TestRunCheck { class OutputMatcher(val output: Output = Output.ALL, val match: (String) -> Boolean): TestRunCheck - class FileCheckMatcher(val settings: Settings, val testDataFile: File): TestRunCheck + class FileCheckMatcher(val settings: Settings, val testDataFile: File) : TestRunCheck { + val prefixes: String + get() { + val testTarget = settings.get().testTarget + val checkPrefixes = buildList { + add("CHECK") + add("CHECK-${testTarget.abiInfoString}") + add("CHECK-${testTarget.name.toUpperCaseAsciiOnly()}") + if (testTarget.family.isAppleFamily) { + add("CHECK-APPLE") + } + if (testTarget.needSmallBinary()) { + add("CHECK-SMALLBINARY") + } else { + add("CHECK-BIGBINARY") + } + } + val optimizationMode = settings.get().name + val checkPrefixesWithOptMode = checkPrefixes.map { "$it-$optimizationMode" } + val cacheMode = settings.get().alias + val checkPrefixesWithCacheMode = checkPrefixes.map { "$it-CACHE_$cacheMode" } + return (checkPrefixes + checkPrefixesWithOptMode + checkPrefixesWithCacheMode).joinToString(",") + } + } } internal data class TestRunChecks( @@ -67,3 +97,11 @@ internal data class TestRunChecks( ) } } + +// Shameless borrowing `val KonanTarget.abiInfo` from module `:kotlin-native:backend.native`, which cannot be imported here for now. +private val KonanTarget.abiInfoString: String + get() = when { + this == KonanTarget.MINGW_X64 -> "WINDOWSX64" + !family.isAppleFamily && architecture == Architecture.ARM64 -> "AAPCS" + else -> "DEFAULTABI" + }