Skip to content

Commit 0dbb182

Browse files
DomonionAbdullinAM
authored andcommitted
Out of process bug fixes (UnitTestBot#1109)
1. added ability to set log level for EngineProcess and ChildProcess.kt. Look for related UtSettings.engineProcessLogLevel and UtSettings.childProcessLogLevels 2. opening additional packages to support jdk17+, see OpenModulesContainer 3. fixed using javaw on unix environments 4. fixed using readaction in dumb mode
1 parent 4d46f34 commit 0dbb182

File tree

11 files changed

+119
-80
lines changed

11 files changed

+119
-80
lines changed

utbot-core/src/main/kotlin/org/utbot/common/JvmUtil.kt

+2
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ package org.utbot.common
33
private val javaSpecificationVersion = System.getProperty("java.specification.version")
44
val isJvm8 = javaSpecificationVersion.equals("1.8")
55
val isJvm9Plus = !javaSpecificationVersion.contains(".") && javaSpecificationVersion.toInt() >= 9
6+
7+
fun osSpecificJavaExecutable() = if (isWindows) "javaw" else "java"

utbot-framework-api/build.gradle.kts

+3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ plugins {
1212
dependencies {
1313
api(project(":utbot-core"))
1414
api(project(":utbot-api"))
15+
api(project(":utbot-rd"))
16+
implementation(group ="com.jetbrains.rd", name = "rd-framework", version = "2022.3.1")
17+
implementation(group ="com.jetbrains.rd", name = "rd-core", version = "2022.3.1")
1518
implementation("com.github.UnitTestBot:soot:${sootCommitHash}")
1619
implementation(group = "io.github.microutils", name = "kotlin-logging", version = kotlinLoggingVersion)
1720
// TODO do we really need apache commons?

utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt

+12-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
package org.utbot.framework
22

3+
import com.jetbrains.rd.util.LogLevel
34
import mu.KotlinLogging
45
import org.utbot.common.AbstractSettings
5-
import org.utbot.common.PropertiesSettingsContainer
6-
import kotlin.reflect.KProperty
7-
86
private val logger = KotlinLogging.logger {}
97

108
/**
@@ -266,7 +264,17 @@ object UtSettings : AbstractSettings(
266264
)
267265

268266
/**
269-
* Determines whether should errors from a child process and idea engine process be written to a log file or suppressed.
267+
* Log level for engine process, which started in idea on generate tests action.
268+
*/
269+
var engineProcessLogLevel by getEnumProperty(LogLevel.Info)
270+
271+
/**
272+
* Log level for concrete executor process.
273+
*/
274+
var childProcessLogLevel by getEnumProperty(LogLevel.Info)
275+
276+
/**
277+
* Determines whether should errors from a child process be written to a log file or suppressed.
270278
* Note: being enabled, this option can highly increase disk usage when using ContestEstimator.
271279
*
272280
* False by default (for saving disk space).
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package org.utbot.framework.process
2+
3+
import org.utbot.framework.plugin.services.JdkInfoService
4+
5+
object OpenModulesContainer {
6+
private val modulesContainer: List<String>
7+
val javaVersionSpecificArguments: List<String>
8+
get() = modulesContainer
9+
.takeIf { JdkInfoService.provide().version > 8 }
10+
?: emptyList()
11+
12+
init {
13+
modulesContainer = buildList {
14+
openPackage("java.base", "jdk.internal.misc")
15+
openPackage("java.base", "java.lang")
16+
openPackage("java.base", "java.lang.reflect")
17+
openPackage("java.base", "sun.security.provider")
18+
add("--illegal-access=warn")
19+
}
20+
}
21+
22+
private fun MutableList<String>.openPackage(module: String, pakage: String) {
23+
add("--add-opens")
24+
add("$module/$pakage=ALL-UNNAMED")
25+
}
26+
}

utbot-instrumentation/src/main/kotlin/org/utbot/instrumentation/process/ChildProcess.kt

+14-2
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,20 @@ internal object HandlerClassesLoader : URLClassLoader(emptyArray()) {
5353
* Command-line option to disable the sandbox
5454
*/
5555
const val DISABLE_SANDBOX_OPTION = "--disable-sandbox"
56-
private val defaultLogLevel = LogLevel.Info
56+
const val ENABLE_LOGS_OPTION = "--enable-logs"
5757
private val logger = getLogger("ChildProcess")
5858
private val messageFromMainTimeout: Duration = 120.seconds
5959

60+
fun logLevelArgument(level: LogLevel): String {
61+
return "$ENABLE_LOGS_OPTION=$level"
62+
}
63+
64+
private fun findLogLevel(args: Array<String>): LogLevel {
65+
val logArgument = args.find{ it.contains(ENABLE_LOGS_OPTION) } ?: return LogLevel.Fatal
66+
67+
return enumValueOf(logArgument.split("=").last())
68+
}
69+
6070
/**
6171
* It should be compiled into separate jar file (child_process.jar) and be run with an agent (agent.jar) option.
6272
*/
@@ -76,7 +86,9 @@ fun main(args: Array<String>) = runBlocking {
7686
}
7787
}
7888

79-
Logger.set(Lifetime.Eternal, UtRdConsoleLoggerFactory(defaultLogLevel, System.err))
89+
val logLevel: LogLevel = findLogLevel(args)
90+
Logger.set(Lifetime.Eternal, UtRdConsoleLoggerFactory(logLevel, System.err))
91+
8092
val port = findRdPort(args)
8193

8294
try {

utbot-instrumentation/src/main/kotlin/org/utbot/instrumentation/process/ChildProcessRunner.kt

+12-14
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import org.utbot.common.utBotTempDirectory
77
import org.utbot.framework.plugin.services.JdkInfoService
88
import org.utbot.framework.UtSettings
99
import org.utbot.framework.plugin.services.WorkingDirService
10+
import org.utbot.framework.process.OpenModulesContainer
1011
import org.utbot.instrumentation.Settings
1112
import org.utbot.instrumentation.agent.DynamicClassTransformer
1213
import org.utbot.rd.rdPortArgument
@@ -19,26 +20,20 @@ class ChildProcessRunner {
1920
private val id = Random.nextLong()
2021
private var processSeqN = 0
2122
private val cmds: List<String> by lazy {
22-
val debugCmd =
23-
listOfNotNull(DEBUG_RUN_CMD.takeIf { Settings.runChildProcessWithDebug} )
24-
25-
val javaVersionSpecificArguments =
26-
listOf("--add-opens", "java.base/jdk.internal.misc=ALL-UNNAMED", "--illegal-access=warn")
27-
.takeIf { JdkInfoService.provide().version > 8 }
28-
?: emptyList()
29-
23+
val debugCmd = listOfNotNull(DEBUG_RUN_CMD.takeIf { Settings.runChildProcessWithDebug })
24+
val javaVersionSpecificArguments = OpenModulesContainer.javaVersionSpecificArguments
3025
val pathToJava = JdkInfoService.provide().path
3126

32-
listOf(pathToJava.resolve("bin${File.separatorChar}java").toString()) +
27+
listOf(pathToJava.resolve("bin${File.separatorChar}${osSpecificJavaExecutable()}").toString()) +
3328
debugCmd +
3429
javaVersionSpecificArguments +
3530
listOf("-javaagent:$jarFile", "-ea", "-jar", "$jarFile")
3631
}
3732

3833
var errorLogFile: File = NULL_FILE
3934

40-
fun start(port: Int): Process {
41-
val portArgument = rdPortArgument(port)
35+
fun start(rdPort: Int): Process {
36+
val portArgument = rdPortArgument(rdPort)
4237

4338
logger.debug { "Starting child process: ${cmds.joinToString(" ")} $portArgument" }
4439
processSeqN++
@@ -54,6 +49,9 @@ class ChildProcessRunner {
5449
if (!UtSettings.useSandbox) {
5550
add(DISABLE_SANDBOX_OPTION)
5651
}
52+
if (UtSettings.logConcreteExecutionErrors) {
53+
add(logLevelArgument(UtSettings.childProcessLogLevel))
54+
}
5755
add(portArgument)
5856
}
5957

@@ -62,10 +60,10 @@ class ChildProcessRunner {
6260
.directory(directory)
6361

6462
return processBuilder.start().also {
65-
logger.debug { "Process started with PID=${it.getPid}" }
63+
logger.info { "Process started with PID=${it.getPid}" }
6664

6765
if (UtSettings.logConcreteExecutionErrors) {
68-
logger.debug { "Child process error log: ${errorLogFile.absolutePath}" }
66+
logger.info { "Child process error log: ${errorLogFile.absolutePath}" }
6967
}
7068
}
7169
}
@@ -75,7 +73,7 @@ class ChildProcessRunner {
7573
private const val ERRORS_FILE_PREFIX = "utbot-childprocess-errors"
7674
private const val INSTRUMENTATION_LIB = "lib"
7775

78-
private const val DEBUG_RUN_CMD = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,quiet=y,address=5005"
76+
private const val DEBUG_RUN_CMD = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,quiet=y,address=5006"
7977

8078
private val UT_BOT_TEMP_DIR: File = File(utBotTempDirectory.toFile(), ERRORS_FILE_PREFIX)
8179

utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/CodeGenerationController.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ import org.utbot.framework.plugin.api.CodegenLanguage
5454
import org.utbot.intellij.plugin.models.GenerateTestsModel
5555
import org.utbot.intellij.plugin.models.packageName
5656
import org.utbot.intellij.plugin.process.EngineProcess
57-
import org.utbot.intellij.plugin.process.RdGTestenerationResult
57+
import org.utbot.intellij.plugin.process.RdTestGenerationResult
5858
import org.utbot.intellij.plugin.sarif.SarifReportIdea
5959
import org.utbot.intellij.plugin.sarif.SourceFindingStrategyIdea
6060
import org.utbot.intellij.plugin.ui.*
@@ -83,7 +83,7 @@ object CodeGenerationController {
8383

8484
fun generateTests(
8585
model: GenerateTestsModel,
86-
classesWithTests: Map<PsiClass, RdGTestenerationResult>,
86+
classesWithTests: Map<PsiClass, RdTestGenerationResult>,
8787
psi2KClass: Map<PsiClass, ClassId>,
8888
proc: EngineProcess
8989
) {

utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/UtTestsDialogProcessor.kt

+3-8
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import org.utbot.intellij.plugin.generator.CodeGenerationController.generateTest
3636
import org.utbot.intellij.plugin.models.GenerateTestsModel
3737
import org.utbot.intellij.plugin.models.packageName
3838
import org.utbot.intellij.plugin.process.EngineProcess
39-
import org.utbot.intellij.plugin.process.RdGTestenerationResult
39+
import org.utbot.intellij.plugin.process.RdTestGenerationResult
4040
import org.utbot.intellij.plugin.settings.Settings
4141
import org.utbot.intellij.plugin.ui.GenerateTestsDialogWindow
4242
import org.utbot.intellij.plugin.ui.utils.isBuildWithGradle
@@ -46,7 +46,6 @@ import org.utbot.intellij.plugin.ui.utils.testModules
4646
import org.utbot.intellij.plugin.util.*
4747
import org.utbot.rd.terminateOnException
4848
import java.io.File
49-
import java.net.URLClassLoader
5049
import java.nio.file.Path
5150
import java.nio.file.Paths
5251
import java.util.concurrent.TimeUnit
@@ -136,12 +135,12 @@ object UtTestsDialogProcessor {
136135

137136
val (buildDirs, classpath, classpathList, pluginJarsPath) = buildPaths
138137

139-
val testSetsByClass = mutableMapOf<PsiClass, RdGTestenerationResult>()
138+
val testSetsByClass = mutableMapOf<PsiClass, RdTestGenerationResult>()
140139
val psi2KClass = mutableMapOf<PsiClass, ClassId>()
141140
var processedClasses = 0
142141
val totalClasses = model.srcClasses.size
143142

144-
val proc = EngineProcess(lifetime)
143+
val proc = EngineProcess(lifetime, project)
145144

146145
proc.setupUtContext(buildDirs + classpathList)
147146
proc.createTestGenerator(
@@ -283,10 +282,6 @@ object UtTestsDialogProcessor {
283282
appendLine("Alternatively, you could try to increase current timeout $timeout sec for generating tests in generation dialog.")
284283
}
285284

286-
287-
private fun urlClassLoader(classpath: List<String>) =
288-
URLClassLoader(classpath.map { File(it).toURI().toURL() }.toTypedArray())
289-
290285
private fun findSrcModule(srcClasses: Set<PsiClass>): Module {
291286
val srcModules = srcClasses.mapNotNull { it.module }.distinct()
292287
return when (srcModules.size) {

0 commit comments

Comments
 (0)