From ac95ca12cf398e878d17539dd9642e2e40769eb0 Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Thu, 9 Feb 2023 18:16:18 +0100 Subject: [PATCH] [K/N][tests] Support running the compiler without altering its output --- .../support/ConfigurationProperties.kt | 5 ++- .../blackboxtest/support/NativeTestSupport.kt | 9 +++++ .../compilation/CompilationToolCall.kt | 33 +++++++++++++++++++ .../support/compilation/TestCompilation.kt | 22 ++++++++++--- .../support/settings/TestProcessSettings.kt | 5 +++ 5 files changed, 69 insertions(+), 5 deletions(-) diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/ConfigurationProperties.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/ConfigurationProperties.kt index 39325886402..4e5e2872ac0 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/ConfigurationProperties.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/ConfigurationProperties.kt @@ -53,7 +53,10 @@ internal enum class ClassLevelProperty(shortName: String) { GC_SCHEDULER("gcScheduler"), CACHE_MODE("cacheMode"), EXECUTION_TIMEOUT("executionTimeout"), - SANITIZER("sanitizer"); + SANITIZER("sanitizer"), + COMPILER_OUTPUT_INTERCEPTOR("compilerOutputInterceptor"), + + ; internal val propertyName = fullPropertyName(shortName) diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/NativeTestSupport.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/NativeTestSupport.kt index 77a989bcf54..f9b761df3d6 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/NativeTestSupport.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/NativeTestSupport.kt @@ -200,6 +200,8 @@ private object NativeTestSupport { // Parse annotations of current class, since there's no way to put annotations to upper-level enclosing class output += computePipelineType(testClass.get()) + output += computeCompilerOutputInterceptor(enforcedProperties) + return nativeTargets } @@ -222,6 +224,13 @@ private object NativeTestSupport { private fun computeSanitizer(enforcedProperties: EnforcedProperties): Sanitizer = ClassLevelProperty.SANITIZER.readValue(enforcedProperties, Sanitizer.values(), default = Sanitizer.NONE) + private fun computeCompilerOutputInterceptor(enforcedProperties: EnforcedProperties): CompilerOutputInterceptor = + ClassLevelProperty.COMPILER_OUTPUT_INTERCEPTOR.readValue( + enforcedProperties, + CompilerOutputInterceptor.values(), + default = CompilerOutputInterceptor.DEFAULT + ) + private fun computeGCType(enforcedProperties: EnforcedProperties): GCType = ClassLevelProperty.GC_TYPE.readValue(enforcedProperties, GCType.values(), default = GCType.UNSPECIFIED) diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/compilation/CompilationToolCall.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/compilation/CompilationToolCall.kt index ecd3794d323..4d7e0b1452a 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/compilation/CompilationToolCall.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/compilation/CompilationToolCall.kt @@ -74,6 +74,39 @@ internal fun callCompiler(compilerArgs: Array, kotlinNativeClassLoader: return CompilationToolCallResult(exitCode, compilerOutput, messageCollector.hasErrors(), duration) } +internal fun callCompilerWithoutOutputInterceptor( + compilerArgs: Array, + kotlinNativeClassLoader: ClassLoader +): CompilationToolCallResult { + val exitCode: ExitCode + val compilerOutput: String + + @OptIn(ExperimentalTime::class) + val duration = measureTime { + val compilerClass = Class.forName("org.jetbrains.kotlin.cli.bc.K2Native", true, kotlinNativeClassLoader) + val entryPoint = compilerClass.getMethod( + "exec", + PrintStream::class.java, + Array::class.java + ) + // TODO: we better use the same entry point as the actual compiler. + + val outputStream = ByteArrayOutputStream() + + exitCode = PrintStream(outputStream).use { printStream -> + val result = entryPoint.invoke(compilerClass.getDeclaredConstructor().newInstance(), printStream, compilerArgs) + ExitCode.valueOf(result.toString()) + } + + compilerOutput = outputStream.toString(Charsets.UTF_8.name()) + } + + val toolOutputHasErrors = exitCode != ExitCode.OK // An approximation, good enough. + // Alternatively, we can look for 'error:' and 'exception:' in the output. + + return CompilationToolCallResult(exitCode, compilerOutput, toolOutputHasErrors = toolOutputHasErrors, duration) +} + @OptIn(ExperimentalTime::class) internal fun invokeCInterop( kotlinNativeClassLoader: ClassLoader, diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/compilation/TestCompilation.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/compilation/TestCompilation.kt index 3b972c8448c..61e4e3e1225 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/compilation/TestCompilation.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/compilation/TestCompilation.kt @@ -31,6 +31,7 @@ internal abstract class BasicCompilation( protected val home: KotlinNativeHome, private val classLoader: KotlinNativeClassLoader, private val optimizationMode: OptimizationMode, + private val compilerOutputInterceptor: CompilerOutputInterceptor, protected val freeCompilerArgs: TestCompilerArgs, protected val dependencies: CategorizedDependencies, protected val expectedArtifact: A @@ -82,10 +83,18 @@ internal abstract class BasicCompilation( val loggedCompilerParameters = LoggedData.CompilerParameters(home, compilerArgs, sourceModules) val (loggedCompilerCall: LoggedData, result: TestCompilationResult.ImmediateResult) = try { - val (exitCode, compilerOutput, compilerOutputHasErrors, duration) = callCompiler( - compilerArgs = compilerArgs, - kotlinNativeClassLoader = classLoader.classLoader - ) + val compilerToolCallResult = when (compilerOutputInterceptor) { + CompilerOutputInterceptor.DEFAULT -> callCompiler( + compilerArgs = compilerArgs, + kotlinNativeClassLoader = classLoader.classLoader + ) + CompilerOutputInterceptor.NONE -> callCompilerWithoutOutputInterceptor( + compilerArgs = compilerArgs, + kotlinNativeClassLoader = classLoader.classLoader + ) + } + + val (exitCode, compilerOutput, compilerOutputHasErrors, duration) = compilerToolCallResult val loggedCompilationToolCall = LoggedData.CompilationToolCall("COMPILER", loggedCompilerParameters, exitCode, compilerOutput, compilerOutputHasErrors, duration) @@ -116,6 +125,7 @@ internal abstract class SourceBasedCompilation( home: KotlinNativeHome, classLoader: KotlinNativeClassLoader, optimizationMode: OptimizationMode, + compilerOutputInterceptor: CompilerOutputInterceptor, private val memoryModel: MemoryModel, private val threadStateChecker: ThreadStateChecker, private val sanitizer: Sanitizer, @@ -131,6 +141,7 @@ internal abstract class SourceBasedCompilation( home = home, classLoader = classLoader, optimizationMode = optimizationMode, + compilerOutputInterceptor = compilerOutputInterceptor, freeCompilerArgs = freeCompilerArgs, dependencies = dependencies, expectedArtifact = expectedArtifact @@ -165,6 +176,7 @@ internal class LibraryCompilation( home = settings.get(), classLoader = settings.get(), optimizationMode = settings.get(), + compilerOutputInterceptor = settings.get(), memoryModel = settings.get(), threadStateChecker = settings.get(), sanitizer = settings.get(), @@ -249,6 +261,7 @@ internal class ExecutableCompilation( home = settings.get(), classLoader = settings.get(), optimizationMode = settings.get(), + compilerOutputInterceptor = settings.get(), memoryModel = settings.get(), threadStateChecker = settings.get(), sanitizer = settings.get(), @@ -332,6 +345,7 @@ internal class StaticCacheCompilation( home = settings.get(), classLoader = settings.get(), optimizationMode = settings.get(), + compilerOutputInterceptor = settings.get(), freeCompilerArgs = freeCompilerArgs, dependencies = CategorizedDependencies(dependencies), expectedArtifact = expectedArtifact diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/settings/TestProcessSettings.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/settings/TestProcessSettings.kt index 2be873c8223..a45ed2aa557 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/settings/TestProcessSettings.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/settings/TestProcessSettings.kt @@ -246,3 +246,8 @@ internal enum class PipelineType(val mutedOption: MutedOption, val compilerFlags override fun toString() = if (compilerFlags.isEmpty()) "" else compilerFlags.joinToString(prefix = "(", postfix = ")", separator = " ") } + +internal enum class CompilerOutputInterceptor { + DEFAULT, + NONE +}