[Native][tests] Fail tests on unexpected non-syntax/semantic warnings

This commit is contained in:
Dmitriy Dolovov
2022-06-17 12:40:17 +04:00
parent adf98770f3
commit c0cbd2e3ed
2 changed files with 122 additions and 7 deletions
@@ -6,10 +6,7 @@
package org.jetbrains.kotlin.konan.blackboxtest.support.compilation
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.common.messages.GroupingMessageCollector
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector
import org.jetbrains.kotlin.cli.common.messages.*
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
import org.jetbrains.kotlin.compilerRunner.processCompilerOutput
import org.jetbrains.kotlin.config.Services
@@ -48,9 +45,9 @@ internal fun callCompiler(compilerArgs: Array<String>, kotlinNativeClassLoader:
ByteArrayOutputStream().use { outputStream ->
PrintStream(outputStream).use { printStream ->
messageCollector = GroupingMessageCollector(
PrintingMessageCollector(printStream, MessageRenderer.SYSTEM_INDEPENDENT_RELATIVE_PATHS, true),
false
messageCollector = NativeTestGroupingMessageCollector(
compilerArgs = compilerArgs,
delegate = PrintingMessageCollector(printStream, MessageRenderer.SYSTEM_INDEPENDENT_RELATIVE_PATHS, /*verbose =*/ true),
)
processCompilerOutput(
messageCollector,
@@ -0,0 +1,118 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.konan.blackboxtest.support.compilation
import com.intellij.openapi.util.text.StringUtil.substringAfter
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation
import org.jetbrains.kotlin.cli.common.messages.GroupingMessageCollector
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
/**
* Special implementation of [GroupingMessageCollector] that raises the severity of unexpected
* compiler warnings to errors, this way failing the tests.
*/
internal class NativeTestGroupingMessageCollector(
compilerArgs: Array<String>,
delegate: MessageCollector
) : GroupingMessageCollector(
delegate,
/*treatWarningsAsErrors =*/ false
) {
private var hasWarningsWithRaisedSeverity: Boolean = false
private val languageFeaturesInCompilerArgs: Set<String> by lazy {
compilerArgs.mapNotNullTo(hashSetOf(), ::parseLanguageFeatureArg)
}
private val pathOfCachedLibraryWithTests: String? by lazy {
var isProducingStaticCache = false
var includedLibraryName: String? = null
var cachedLibraryName: String? = null
for ((index, arg) in compilerArgs.withIndex()) {
if ((arg == "-p" || arg == "-produce")
&& index < compilerArgs.size - 1
&& compilerArgs[index + 1] == "static_cache"
) {
isProducingStaticCache = true
} else {
includedLibraryName = includedLibraryName ?: substringAfter(arg, "-Xinclude=")
cachedLibraryName = cachedLibraryName ?: substringAfter(arg, "-Xadd-cache=")
}
if (isProducingStaticCache && includedLibraryName != null && cachedLibraryName != null)
return@lazy cachedLibraryName.takeIf { includedLibraryName == cachedLibraryName }
}
null
}
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageSourceLocation?) =
super.report(adjustSeverity(severity, message, location), message, location)
private fun adjustSeverity(severity: CompilerMessageSeverity, message: String, location: CompilerMessageSourceLocation?) =
when {
!severity.isWarning -> {
// Don't adjust severity for non-warnings.
severity
}
location != null -> {
// Don't adjust severity for any syntax and semantic warnings.
severity
}
isPreReleaseBinariesWarning(message)
|| isUnsafeCompilerArgumentsWarning(message)
|| isLibraryIncludedMoreThanOnceWarning(message) -> {
// These warnings are known and should not be reported as errors.
severity
}
else -> {
hasWarningsWithRaisedSeverity = true
CompilerMessageSeverity.ERROR
}
}
private fun isPreReleaseBinariesWarning(message: String): Boolean {
val languageFeatures = substringAfter(message, PRE_RELEASE_WARNING_PREFIX)
?.split(", ")
?.takeIf(Collection<String>::isNotEmpty)
?: return false
return languageFeaturesInCompilerArgs.containsAll(languageFeatures)
}
private fun isUnsafeCompilerArgumentsWarning(message: String): Boolean {
val languageFeatures = substringAfter(message, UNSAFE_COMPILER_ARGS_WARNING_PREFIX)
?.lineSequence()
?.takeWhile(String::isNotBlank)
?.map { parseLanguageFeatureArg(it) ?: "<non-parsable command line argument>" }
?.toList()
?.takeIf(Collection<String>::isNotEmpty)
?: return false
return languageFeaturesInCompilerArgs.containsAll(languageFeatures)
}
private fun isLibraryIncludedMoreThanOnceWarning(message: String): Boolean {
val libraryPath = substringAfter(message, LIBRARY_INCLUDED_MORE_THAN_ONCE_WARNING_PREFIX)
?.takeIf(String::isNotBlank)
?: return false
return libraryPath == pathOfCachedLibraryWithTests
}
override fun hasErrors() = hasWarningsWithRaisedSeverity || super.hasErrors()
companion object {
private const val PRE_RELEASE_WARNING_PREFIX = "Following manually enabled features will force generation of pre-release binaries: "
private const val UNSAFE_COMPILER_ARGS_WARNING_PREFIX = "ATTENTION!\nThis build uses unsafe internal compiler arguments:\n\n"
private const val LIBRARY_INCLUDED_MORE_THAN_ONCE_WARNING_PREFIX = "library included more than once: "
private fun parseLanguageFeatureArg(arg: String): String? =
substringAfter(arg, "-XXLanguage:-") ?: substringAfter(arg, "-XXLanguage:+")
}
}