[K/N][tests] Support running the compiler without altering its output

This commit is contained in:
Svyatoslav Scherbina
2023-02-09 18:16:18 +01:00
committed by Space Team
parent e0c7d72cee
commit ac95ca12cf
5 changed files with 69 additions and 5 deletions
@@ -53,7 +53,10 @@ internal enum class ClassLevelProperty(shortName: String) {
GC_SCHEDULER("gcScheduler"), GC_SCHEDULER("gcScheduler"),
CACHE_MODE("cacheMode"), CACHE_MODE("cacheMode"),
EXECUTION_TIMEOUT("executionTimeout"), EXECUTION_TIMEOUT("executionTimeout"),
SANITIZER("sanitizer"); SANITIZER("sanitizer"),
COMPILER_OUTPUT_INTERCEPTOR("compilerOutputInterceptor"),
;
internal val propertyName = fullPropertyName(shortName) internal val propertyName = fullPropertyName(shortName)
@@ -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 // Parse annotations of current class, since there's no way to put annotations to upper-level enclosing class
output += computePipelineType(testClass.get()) output += computePipelineType(testClass.get())
output += computeCompilerOutputInterceptor(enforcedProperties)
return nativeTargets return nativeTargets
} }
@@ -222,6 +224,13 @@ private object NativeTestSupport {
private fun computeSanitizer(enforcedProperties: EnforcedProperties): Sanitizer = private fun computeSanitizer(enforcedProperties: EnforcedProperties): Sanitizer =
ClassLevelProperty.SANITIZER.readValue(enforcedProperties, Sanitizer.values(), default = Sanitizer.NONE) 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 = private fun computeGCType(enforcedProperties: EnforcedProperties): GCType =
ClassLevelProperty.GC_TYPE.readValue(enforcedProperties, GCType.values(), default = GCType.UNSPECIFIED) ClassLevelProperty.GC_TYPE.readValue(enforcedProperties, GCType.values(), default = GCType.UNSPECIFIED)
@@ -74,6 +74,39 @@ internal fun callCompiler(compilerArgs: Array<String>, kotlinNativeClassLoader:
return CompilationToolCallResult(exitCode, compilerOutput, messageCollector.hasErrors(), duration) return CompilationToolCallResult(exitCode, compilerOutput, messageCollector.hasErrors(), duration)
} }
internal fun callCompilerWithoutOutputInterceptor(
compilerArgs: Array<String>,
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<String>::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) @OptIn(ExperimentalTime::class)
internal fun invokeCInterop( internal fun invokeCInterop(
kotlinNativeClassLoader: ClassLoader, kotlinNativeClassLoader: ClassLoader,
@@ -31,6 +31,7 @@ internal abstract class BasicCompilation<A : TestCompilationArtifact>(
protected val home: KotlinNativeHome, protected val home: KotlinNativeHome,
private val classLoader: KotlinNativeClassLoader, private val classLoader: KotlinNativeClassLoader,
private val optimizationMode: OptimizationMode, private val optimizationMode: OptimizationMode,
private val compilerOutputInterceptor: CompilerOutputInterceptor,
protected val freeCompilerArgs: TestCompilerArgs, protected val freeCompilerArgs: TestCompilerArgs,
protected val dependencies: CategorizedDependencies, protected val dependencies: CategorizedDependencies,
protected val expectedArtifact: A protected val expectedArtifact: A
@@ -82,10 +83,18 @@ internal abstract class BasicCompilation<A : TestCompilationArtifact>(
val loggedCompilerParameters = LoggedData.CompilerParameters(home, compilerArgs, sourceModules) val loggedCompilerParameters = LoggedData.CompilerParameters(home, compilerArgs, sourceModules)
val (loggedCompilerCall: LoggedData, result: TestCompilationResult.ImmediateResult<out A>) = try { val (loggedCompilerCall: LoggedData, result: TestCompilationResult.ImmediateResult<out A>) = try {
val (exitCode, compilerOutput, compilerOutputHasErrors, duration) = callCompiler( val compilerToolCallResult = when (compilerOutputInterceptor) {
compilerArgs = compilerArgs, CompilerOutputInterceptor.DEFAULT -> callCompiler(
kotlinNativeClassLoader = classLoader.classLoader compilerArgs = compilerArgs,
) kotlinNativeClassLoader = classLoader.classLoader
)
CompilerOutputInterceptor.NONE -> callCompilerWithoutOutputInterceptor(
compilerArgs = compilerArgs,
kotlinNativeClassLoader = classLoader.classLoader
)
}
val (exitCode, compilerOutput, compilerOutputHasErrors, duration) = compilerToolCallResult
val loggedCompilationToolCall = val loggedCompilationToolCall =
LoggedData.CompilationToolCall("COMPILER", loggedCompilerParameters, exitCode, compilerOutput, compilerOutputHasErrors, duration) LoggedData.CompilationToolCall("COMPILER", loggedCompilerParameters, exitCode, compilerOutput, compilerOutputHasErrors, duration)
@@ -116,6 +125,7 @@ internal abstract class SourceBasedCompilation<A : TestCompilationArtifact>(
home: KotlinNativeHome, home: KotlinNativeHome,
classLoader: KotlinNativeClassLoader, classLoader: KotlinNativeClassLoader,
optimizationMode: OptimizationMode, optimizationMode: OptimizationMode,
compilerOutputInterceptor: CompilerOutputInterceptor,
private val memoryModel: MemoryModel, private val memoryModel: MemoryModel,
private val threadStateChecker: ThreadStateChecker, private val threadStateChecker: ThreadStateChecker,
private val sanitizer: Sanitizer, private val sanitizer: Sanitizer,
@@ -131,6 +141,7 @@ internal abstract class SourceBasedCompilation<A : TestCompilationArtifact>(
home = home, home = home,
classLoader = classLoader, classLoader = classLoader,
optimizationMode = optimizationMode, optimizationMode = optimizationMode,
compilerOutputInterceptor = compilerOutputInterceptor,
freeCompilerArgs = freeCompilerArgs, freeCompilerArgs = freeCompilerArgs,
dependencies = dependencies, dependencies = dependencies,
expectedArtifact = expectedArtifact expectedArtifact = expectedArtifact
@@ -165,6 +176,7 @@ internal class LibraryCompilation(
home = settings.get(), home = settings.get(),
classLoader = settings.get(), classLoader = settings.get(),
optimizationMode = settings.get(), optimizationMode = settings.get(),
compilerOutputInterceptor = settings.get(),
memoryModel = settings.get(), memoryModel = settings.get(),
threadStateChecker = settings.get(), threadStateChecker = settings.get(),
sanitizer = settings.get(), sanitizer = settings.get(),
@@ -249,6 +261,7 @@ internal class ExecutableCompilation(
home = settings.get(), home = settings.get(),
classLoader = settings.get(), classLoader = settings.get(),
optimizationMode = settings.get(), optimizationMode = settings.get(),
compilerOutputInterceptor = settings.get(),
memoryModel = settings.get(), memoryModel = settings.get(),
threadStateChecker = settings.get(), threadStateChecker = settings.get(),
sanitizer = settings.get(), sanitizer = settings.get(),
@@ -332,6 +345,7 @@ internal class StaticCacheCompilation(
home = settings.get(), home = settings.get(),
classLoader = settings.get(), classLoader = settings.get(),
optimizationMode = settings.get(), optimizationMode = settings.get(),
compilerOutputInterceptor = settings.get(),
freeCompilerArgs = freeCompilerArgs, freeCompilerArgs = freeCompilerArgs,
dependencies = CategorizedDependencies(dependencies), dependencies = CategorizedDependencies(dependencies),
expectedArtifact = expectedArtifact expectedArtifact = expectedArtifact
@@ -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 = " ") override fun toString() = if (compilerFlags.isEmpty()) "" else compilerFlags.joinToString(prefix = "(", postfix = ")", separator = " ")
} }
internal enum class CompilerOutputInterceptor {
DEFAULT,
NONE
}