[Native][tests] Log environment variables and JVM properties

This commit is contained in:
Dmitriy Dolovov
2021-12-06 13:51:48 +03:00
parent a81c44301d
commit 3d8fce4edb
2 changed files with 118 additions and 1 deletions
@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.konan.blackboxtest.support
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.konan.blackboxtest.support.runner.RunResult
import org.jetbrains.kotlin.konan.blackboxtest.support.util.SafeEnvVars
import org.jetbrains.kotlin.konan.blackboxtest.support.util.SafeProperties
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import java.io.File
import kotlin.time.Duration
@@ -29,9 +31,26 @@ internal abstract class LoggedData {
appendLine(this@LoggedData)
}
class JVMEnvironment : LoggedData() {
private val properties = SafeProperties()
override fun computeText() = buildString {
appendLine("ENVIRONMENT VARIABLES:")
SafeEnvVars.forEach { (name, safeValue) ->
append("- ").append(name).append(" = ").appendLine(safeValue)
}
appendLine()
appendLine("JVM PROPERTIES:")
properties.forEach { (name, safeValue) ->
append("- ").append(name).append(" = ").appendLine(safeValue)
}
}
}
class CompilerParameters(
private val compilerArgs: Array<String>,
private val sourceModules: Collection<TestModule>
private val sourceModules: Collection<TestModule>,
private val environment: JVMEnvironment = JVMEnvironment() // Capture environment.
) : LoggedData() {
private val testDataFiles: List<File>
get() = buildList {
@@ -44,6 +63,8 @@ internal abstract class LoggedData {
override fun computeText() = buildString {
appendArguments("COMPILER ARGUMENTS:", listOf("\$\$kotlinc-native\$\$") + compilerArgs)
appendLine()
appendLine(environment)
val testDataFiles = testDataFiles
if (testDataFiles.isNotEmpty()) {
@@ -0,0 +1,96 @@
/*
* Copyright 2010-2021 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.util
import com.intellij.openapi.util.text.StringUtil.containsLineBreak
import com.intellij.openapi.util.text.StringUtil.escapeLineBreak
import java.util.*
internal data class NameAndSafeValue(val name: String, val safeValue: String)
internal object SafeEnvVars : Iterable<NameAndSafeValue> {
private val environment: List<NameAndSafeValue> by lazy {
buildList {
System.getenv().forEach { (name, value) ->
val safeValue = if (isSafeEnvVar(name)) doEscape(value) else HIDDEN_VALUE
this += NameAndSafeValue(name, safeValue)
}
sortBy { it.name }
}
}
override fun iterator() = environment.iterator()
private fun isSafeEnvVar(name: String): Boolean {
if (name in SAFE_ENV_VARS) return true
if (isUnsafeVariableName(name)) return false
return KONAN_WORD in name
|| SAFE_ENV_VAR_PREFIXES.any { prefix -> name.startsWith(prefix, ignoreCase = true) }
|| SAFE_ENV_VAR_SUFFIXES.any { suffix -> name.endsWith(suffix, ignoreCase = true) }
}
private const val KONAN_WORD = "KONAN"
private val SAFE_ENV_VARS = setOf("PATH", "USER", "LANG", "PWD", "TEMP", "TMP")
private val SAFE_ENV_VAR_PREFIXES = listOf("JAVA_", "JDK_")
private val SAFE_ENV_VAR_SUFFIXES = listOf("DIR", "DIRS", "HOME", "ROOT", "PATH", "FILE")
}
internal class SafeProperties : Iterable<NameAndSafeValue> {
// Properties are mutable. So, need to capture the current values.
private val properties: Map<String, String> = TreeMap<String, String>().apply {
System.getProperties().forEach { (name, value) ->
this[name.toString()] = value.toString()
}
}
override fun iterator() = properties.map { (name, value) ->
val safeValue = if (isSafeProperty(name)) doEscape(value) else HIDDEN_VALUE
NameAndSafeValue(name, safeValue)
}.iterator()
companion object {
private fun isSafeProperty(name: String): Boolean {
if (name in SUPPRESSED_PROPERTIES || isUnsafeVariableName(name)) return false
return SAFE_PROPERTY_PREFIXES.any { prefix -> name.startsWith(prefix) }
|| SAFE_PROPERTY_SUFFIXES.any { suffix -> name.endsWith(suffix) }
}
private val SUPPRESSED_PROPERTIES = setOf("java.class.path") // Too long. Makes logs poorly readable.
private val SAFE_PROPERTY_PREFIXES = listOf(
"ast.",
"file.",
"ide.",
"idea.",
"java.",
"jdk.",
"kotlin.",
"org.gradle.",
"org.jetbrains.",
"os.",
"psi.",
"user."
)
private val SAFE_PROPERTY_SUFFIXES = listOf(".separator")
}
}
private const val HIDDEN_VALUE = "<hidden>"
private val UNSAFE_VARIABLE_PARTS = listOf("key", "token", "secret", "private", "pass", "password", "passphrase")
private fun isUnsafeVariableName(name: String) = name
.splitToSequence('.', '_')
.any { namePart ->
UNSAFE_VARIABLE_PARTS.any { unsafeVariableNamePart ->
namePart.startsWith(unsafeVariableNamePart, ignoreCase = true)
|| namePart.endsWith(unsafeVariableNamePart, ignoreCase = true)
}
}
private fun doEscape(value: String) = if (containsLineBreak(value)) escapeLineBreak(value) else value