Skip to content

Commit

Permalink
Refactor RD processes
Browse files Browse the repository at this point in the history
  • Loading branch information
IlyaMuravjov committed Apr 3, 2023
1 parent a884f5c commit 8ffdeb4
Show file tree
Hide file tree
Showing 12 changed files with 58 additions and 117 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,17 @@ package org.utbot.framework.process

import org.utbot.common.osSpecificJavaExecutable
import org.utbot.framework.plugin.services.JdkInfoService
import org.utbot.rd.rdPortArgument
import java.io.File
import java.nio.file.Path
import kotlin.io.path.pathString

private val javaExecutablePathString: Path
get() = JdkInfoService.jdkInfoProvider.info.path.resolve("bin${File.separatorChar}${osSpecificJavaExecutable()}")

// TODO use it in EngineProcess and InstrumentedProcess
fun withCommonProcessCommandLineArgs(
processSpecificArgs: List<String>,
fun obtainCommonProcessCommandLineArgs(
debugPort: Int,
runWithDebug: Boolean,
suspendExecutionInDebugMode: Boolean,
rdPort: Int
): List<String> = buildList {
val suspendValue = if (suspendExecutionInDebugMode) "y" else "n"
val debugArgument = "-agentlib:jdwp=transport=dt_socket,server=n,suspend=${suspendValue},quiet=y,address=$debugPort"
Expand All @@ -28,6 +24,4 @@ fun withCommonProcessCommandLineArgs(
addAll(javaVersionSpecificArgs)
}
debugArgument?.let { add(it) }
addAll(processSpecificArgs)
add(rdPortArgument(rdPort))
}
12 changes: 12 additions & 0 deletions utbot-framework/build.gradle
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
configurations {
fetchSpringAnalyzerJar
}

dependencies {

api project(':utbot-fuzzers')
Expand Down Expand Up @@ -36,4 +40,12 @@ dependencies {

implementation group: 'com.github.UnitTestBot.ksmt', name: 'ksmt-core', version: ksmtVersion
implementation group: 'com.github.UnitTestBot.ksmt', name: 'ksmt-z3', version: ksmtVersion

fetchSpringAnalyzerJar project(path: ':utbot-spring-analyzer', configuration: 'springAnalyzerJar')
}

processResources {
from(configurations.fetchSpringAnalyzerJar) {
into "lib"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package org.utbot.framework.codegen.domain
import org.utbot.framework.DEFAULT_EXECUTION_TIMEOUT_IN_INSTRUMENTED_PROCESS_MS
import org.utbot.framework.codegen.domain.builtin.mockitoClassId
import org.utbot.framework.codegen.domain.builtin.ongoingStubbingClassId
import org.utbot.framework.codegen.domain.context.CgContext
import org.utbot.framework.codegen.domain.models.CgClassId
import org.utbot.framework.codegen.tree.argumentsClassId
import org.utbot.framework.plugin.api.BuiltinClassId
Expand Down Expand Up @@ -751,7 +750,7 @@ sealed class TypeReplacementApproach {
*
* Currently used in Spring applications only.
*/
class ReplaceIfPossible(val configFqn: String) : TypeReplacementApproach()
class ReplaceIfPossible(val config: String) : TypeReplacementApproach()
}

abstract class DependencyInjectionFramework(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import org.utbot.rd.generated.synchronizationModel
import org.utbot.rd.loggers.UtRdKLogger
import org.utbot.rd.loggers.setupRdLogger
import org.utbot.rd.onSchedulerBlocking
import org.utbot.rd.rdPortArgument
import org.utbot.rd.startBlocking
import org.utbot.rd.startUtProcessWithRdServer
import org.utbot.rd.terminateOnException
Expand All @@ -35,7 +36,7 @@ class SpringAnalyzerProcess private constructor(
) : ProcessWithRdServer by rdProcess {

companion object {
private fun obtainProcessSpecificCommandLineArgs(): List<String> {
private fun obtainProcessSpecificCommandLineArgs(port: Int): List<String> {
val jarFile =
Files.createDirectories(utBotTempDirectory.toFile().resolve("spring-analyzer").toPath())
.toFile().resolve(SPRING_ANALYZER_JAR_FILENAME)
Expand All @@ -46,21 +47,20 @@ class SpringAnalyzerProcess private constructor(
return listOf(
"-Dorg.apache.commons.logging.LogFactory=org.utbot.rd.loggers.RDApacheCommonsLogFactory",
"-jar",
jarFile.path
jarFile.path,
rdPortArgument(port)
)
}

fun createBlocking() = runBlocking { SpringAnalyzerProcess() }

suspend operator fun invoke(): SpringAnalyzerProcess = LifetimeDefinition().terminateOnException { lifetime ->
val rdProcess = startUtProcessWithRdServer(lifetime) { port ->
val cmd = withCommonProcessCommandLineArgs(
obtainProcessSpecificCommandLineArgs(),
val cmd = obtainCommonProcessCommandLineArgs(
debugPort = UtSettings.springAnalyzerProcessDebugPort,
runWithDebug = UtSettings.runSpringAnalyzerProcessWithDebug,
suspendExecutionInDebugMode = UtSettings.suspendSpringAnalyzerProcessExecutionInDebugMode,
rdPort = port
)
) + obtainProcessSpecificCommandLineArgs(port)
val process = ProcessBuilder(cmd)
.directory(Files.createTempDirectory(utBotTempDirectory, "spring-analyzer").toFile())
.start()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@ import org.utbot.rd.generated.settingsModel
import org.utbot.rd.generated.synchronizationModel
import org.utbot.rd.loggers.UtRdRemoteLoggerFactory
import java.io.File
import java.io.IOException
import java.io.OutputStream
import java.io.PrintStream
import java.net.URLClassLoader
import java.security.AllPermission
import kotlin.time.Duration
Expand Down Expand Up @@ -62,23 +59,6 @@ const val DISABLE_SANDBOX_OPTION = "--disable-sandbox"
private val logger = getLogger<InstrumentedProcessMain>()
private val messageFromMainTimeout: Duration = 120.seconds

private fun closeStandardStreams() {
// we should change out/err streams as not to spend time on user output
// and also because rd default logging system writes some initial values to stdout, polluting it as well
val tmpStream = PrintStream(object : OutputStream() {
override fun write(b: Int) {}
})
val prevOut = System.out
val prevError = System.err
System.setOut(tmpStream)
System.setErr(tmpStream)
// stdin/stderr should be closed as not to leave hanging descriptors
// and we cannot log any exceptions here as rd remote logging is still not configured
// so we pass any exceptions
silent { prevOut.close() }
silent { prevError.close() }
}

interface DummyForMockitoWarmup {
fun method1()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ import mu.KotlinLogging
import org.utbot.common.*
import org.utbot.common.scanForResourcesContaining
import org.utbot.common.utBotTempDirectory
import org.utbot.framework.plugin.services.JdkInfoService
import org.utbot.framework.UtSettings
import org.utbot.framework.plugin.services.WorkingDirService
import org.utbot.framework.process.OpenModulesContainer
import org.utbot.framework.process.obtainCommonProcessCommandLineArgs
import org.utbot.instrumentation.agent.DynamicClassTransformer
import org.utbot.rd.rdPortArgument
import java.io.File
Expand All @@ -16,14 +15,11 @@ private val logger = KotlinLogging.logger {}

class InstrumentedProcessRunner {
private val cmds: List<String> by lazy {
val debugCmd = listOfNotNull(DEBUG_RUN_CMD.takeIf { UtSettings.runInstrumentedProcessWithDebug })
val javaVersionSpecificArguments = OpenModulesContainer.javaVersionSpecificArguments
val pathToJava = JdkInfoService.provide().path

listOf(pathToJava.resolve("bin${File.separatorChar}${osSpecificJavaExecutable()}").toString()) +
debugCmd +
javaVersionSpecificArguments +
listOf("-javaagent:$jarFile", "-ea", "-jar", "$jarFile")
obtainCommonProcessCommandLineArgs(
debugPort = UtSettings.instrumentedProcessDebugPort,
runWithDebug = UtSettings.runInstrumentedProcessWithDebug,
suspendExecutionInDebugMode = UtSettings.suspendInstrumentedProcessExecutionInDebugMode
) + listOf("-javaagent:$jarFile", "-ea", "-jar", "$jarFile")
}

fun start(rdPort: Int): Process {
Expand Down Expand Up @@ -53,13 +49,9 @@ class InstrumentedProcessRunner {
}

companion object {
private fun suspendValue(): String = if (UtSettings.suspendInstrumentedProcessExecutionInDebugMode) "y" else "n"

private const val UTBOT_INSTRUMENTATION = "utbot-instrumentation"
private const val INSTRUMENTATION_LIB = "lib"

private val DEBUG_RUN_CMD = "-agentlib:jdwp=transport=dt_socket,server=n,suspend=${suspendValue()},quiet=y,address=${UtSettings.instrumentedProcessDebugPort}"

private val NULL_FILE_PATH: String = if (System.getProperty("os.name").startsWith("Windows")) {
"NUL"
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import org.utbot.rd.generated.loggerModel
import org.utbot.rd.generated.synchronizationModel
import org.utbot.rd.loggers.UtRdKLogger
import org.utbot.rd.loggers.UtRdRemoteLogger
import org.utbot.rd.loggers.setupRdLogger
import org.utbot.rd.onSchedulerBlocking
import org.utbot.rd.startUtProcessWithRdServer
import org.utbot.rd.terminateOnException
Expand Down Expand Up @@ -63,21 +64,7 @@ class InstrumentedProcess private constructor(
logger.trace("rd process started")

val proc = InstrumentedProcess(classLoader, rdProcess)

// currently we do not specify log level for different categories in instrumented process
// though it is possible with some additional map on categories -> consider performance
proc.loggerModel.getCategoryMinimalLogLevel.set { _ ->
// this logLevel is obtained from KotlinLogger
rdLogger.logLevel.ordinal
}

proc.loggerModel.log.advise(proc.lifetime) {
val logLevel = UtRdRemoteLogger.logLevelValues[it.logLevelOrdinal]
// assume throwable already in message
rdLogger.log(logLevel, it.message, null)
}

rdProcess.protocol.synchronizationModel.initRemoteLogging.fire(Unit)
setupRdLogger(rdProcess, proc.loggerModel, rdLogger)

proc.lifetime.onTermination {
logger.trace { "process is terminating" }
Expand Down
13 changes: 0 additions & 13 deletions utbot-intellij/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,6 @@ repositories {
maven("https://packages.jetbrains.team/maven/p/ij/intellij-dependencies")
}

val fetchSpringAnalyzerJar: Configuration by configurations.creating {
isCanBeResolved = true
isCanBeConsumed = false
}

dependencies {
implementation(group ="com.jetbrains.rd", name = "rd-framework", version = rdVersion)
implementation(group ="com.jetbrains.rd", name = "rd-core", version = rdVersion)
Expand Down Expand Up @@ -173,8 +168,6 @@ dependencies {

implementation(project(":utbot-android-studio"))

fetchSpringAnalyzerJar(project(":utbot-spring-analyzer", "springAnalyzerJar"))

testImplementation("com.intellij.remoterobot:remote-robot:$remoteRobotVersion")
testImplementation("com.intellij.remoterobot:remote-fixtures:$remoteRobotVersion")

Expand All @@ -191,9 +184,3 @@ dependencies {
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:$junit5Version")
testRuntimeOnly("org.junit.vintage:junit-vintage-engine:$junit5Version")
}

tasks.processResources {
from(fetchSpringAnalyzerJar) {
into("lib")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ import org.utbot.framework.plugin.api.util.LockFile
import org.utbot.framework.plugin.api.util.withStaticsSubstitutionRequired
import org.utbot.framework.plugin.services.JdkInfoService
import org.utbot.framework.plugin.services.WorkingDirService
import org.utbot.framework.process.generated.GetSpringBeanQualifiedNamesParams
import org.utbot.intellij.plugin.generator.CodeGenerationController.generateTests
import org.utbot.intellij.plugin.models.GenerateTestsModel
import org.utbot.intellij.plugin.models.packageName
Expand Down Expand Up @@ -162,7 +161,7 @@ object UtTestsDialogProcessor {
val springConfigClass = when (val approach = model.typeReplacementApproach) {
TypeReplacementApproach.DoNotReplace -> null
is TypeReplacementApproach.ReplaceIfPossible ->
approach.configFqn.takeUnless { it.endsWith(".xml") }?.let {
approach.config.takeUnless { it.endsWith(".xml") }?.let {
JavaPsiFacade.getInstance(project).findClass(it, GlobalSearchScope.projectScope(project)) ?:
error("Can't find configuration class $it")
}
Expand Down Expand Up @@ -223,11 +222,10 @@ object UtTestsDialogProcessor {
if (!model.useSpringAnalyzer) emptyList()
else when (val approach = model.typeReplacementApproach) {
TypeReplacementApproach.DoNotReplace -> emptyList()
is TypeReplacementApproach.ReplaceIfPossible -> process.getSpringBeanQualifiedNames(
GetSpringBeanQualifiedNamesParams(
(buildDirs + classpathList).toTypedArray(),
approach.configFqn
)
is TypeReplacementApproach.ReplaceIfPossible ->
process.getSpringBeanQualifiedNames(
buildDirs + classpathList,
approach.config
).also { logger.info { "Detected Spring Beans: $it" } }
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,10 @@ import org.utbot.framework.codegen.domain.*
import org.utbot.framework.codegen.tree.ututils.UtilClassKind
import org.utbot.framework.plugin.api.*
import org.utbot.framework.plugin.services.JdkInfo
import org.utbot.framework.plugin.services.JdkInfoService
import org.utbot.framework.plugin.services.WorkingDirService
import org.utbot.framework.process.OpenModulesContainer
import org.utbot.framework.process.generated.*
import org.utbot.framework.process.generated.MethodDescription
import org.utbot.framework.process.obtainCommonProcessCommandLineArgs
import org.utbot.framework.util.Conflict
import org.utbot.framework.util.ConflictTriggers
import org.utbot.instrumentation.util.KryoHelper
Expand Down Expand Up @@ -94,15 +93,6 @@ class EngineProcess private constructor(val project: Project, private val classN

private val log4j2ConfigSwitch = "-Dlog4j2.configurationFile=${log4j2ConfigFile.canonicalPath}"

private fun suspendValue(): String = if (UtSettings.suspendEngineProcessExecutionInDebugMode) "y" else "n"

private val debugArgument: String?
get() = "-agentlib:jdwp=transport=dt_socket,server=n,suspend=${suspendValue()},quiet=y,address=${UtSettings.engineProcessDebugPort}"
.takeIf { UtSettings.runEngineProcessWithDebug }

private val javaExecutablePathString: Path
get() = JdkInfoService.jdkInfoProvider.info.path.resolve("bin${File.separatorChar}${osSpecificJavaExecutable()}")

private val pluginClasspath: String
get() = (this.javaClass.classLoader as PluginClassLoader).classPath.baseUrls.joinToString(
separator = File.pathSeparator,
Expand All @@ -112,27 +102,25 @@ class EngineProcess private constructor(val project: Project, private val classN

private const val startFileName = "org.utbot.framework.process.EngineProcessMainKt"

private fun obtainEngineProcessCommandLine(port: Int) = buildList {
add(javaExecutablePathString.pathString)
add("-ea")
val javaVersionSpecificArgs = OpenModulesContainer.javaVersionSpecificArguments
if (javaVersionSpecificArgs.isNotEmpty()) {
addAll(javaVersionSpecificArgs)
}
debugArgument?.let { add(it) }
add(log4j2ConfigSwitch)
add("-cp")
add(pluginClasspath)
add(startFileName)
add(rdPortArgument(port))
}
private fun obtainProcessSpecificCommandLineArgs(port: Int) = listOf(
"-ea",
log4j2ConfigSwitch,
"-cp",
pluginClasspath,
startFileName,
rdPortArgument(port)
)

fun createBlocking(project: Project, classNameToPath: Map<String, String?>): EngineProcess = runBlocking { EngineProcess(project, classNameToPath) }

suspend operator fun invoke(project: Project, classNameToPath: Map<String, String?>): EngineProcess =
LifetimeDefinition().terminateOnException { lifetime ->
val rdProcess = startUtProcessWithRdServer(lifetime) { port ->
val cmd = obtainEngineProcessCommandLine(port)
val cmd = obtainCommonProcessCommandLineArgs(
debugPort = UtSettings.engineProcessDebugPort,
runWithDebug = UtSettings.runEngineProcessWithDebug,
suspendExecutionInDebugMode = UtSettings.suspendEngineProcessExecutionInDebugMode,
) + obtainProcessSpecificCommandLineArgs(port)
val directory = WorkingDirService.provide().toFile()
val builder = ProcessBuilder(cmd).directory(directory)
val process = builder.start()
Expand Down Expand Up @@ -167,9 +155,11 @@ class EngineProcess private constructor(val project: Project, private val classN
engineModel.setupUtContext.startBlocking(SetupContextParams(classpathForUrlsClassloader))
}

fun getSpringBeanQualifiedNames(params: GetSpringBeanQualifiedNamesParams): List<String> {
fun getSpringBeanQualifiedNames(classpathList: List<String>, config: String): List<String> {
assertReadAccessNotAllowed()
return engineModel.getSpringBeanQualifiedNames.startBlocking(params).toList()
return engineModel.getSpringBeanQualifiedNames.startBlocking(
GetSpringBeanQualifiedNamesParams(classpathList.toTypedArray(), config)
).toList()
}

private fun computeSourceFileByClass(params: ComputeSourceFileByClassArguments): String =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ fun overrideDefaultRdLoggerFactoryWithKLogger(logger: KLogger) {
}
}

// TODO use in instrumented process
fun setupRdLogger(rdProcess: ProcessWithRdServer, loggerModel: LoggerModel, rdLogger: UtRdKLogger) {
// currently we do not specify log level for different categories
// though it is possible with some additional map on categories -> consider performance
Expand Down
Loading

0 comments on commit 8ffdeb4

Please sign in to comment.