Skip to content

Commit 9e2eaae

Browse files
authored
Introduce inter-process communication between utbot and utbot-spring-analyzer #2038 #2039 (#2085)
1 parent 67bd15d commit 9e2eaae

File tree

43 files changed

+1044
-343
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1044
-343
lines changed

.run/Debug All.run.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<toRun name="Run IDEA" type="GradleRunConfiguration" />
44
<toRun name="Listen for Engine Process" type="Remote" />
55
<toRun name="Listen for Instrumented Process" type="Remote" />
6+
<toRun name="Listen for Spring Analyzer Process" type="Remote" />
67
<method v="2" />
78
</configuration>
89
</component>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<component name="ProjectRunConfigurationManager">
2+
<configuration default="false" name="Debug Spring Analyzer Process" type="CompoundRunConfigurationType">
3+
<toRun name="Run IDEA" type="GradleRunConfiguration" />
4+
<toRun name="Listen for Spring Analyzer Process" type="Remote" />
5+
<method v="2" />
6+
</configuration>
7+
</component>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<component name="ProjectRunConfigurationManager">
2+
<configuration default="false" name="Listen for Spring Analyzer Process" type="Remote" folderName="Utility Configurations">
3+
<option name="USE_SOCKET_TRANSPORT" value="true" />
4+
<option name="SERVER_MODE" value="true" />
5+
<option name="SHMEM_ADDRESS" />
6+
<option name="HOST" value="localhost" />
7+
<option name="PORT" value="5007" />
8+
<option name="AUTO_RESTART" value="true" />
9+
<RunnerSettings RunnerId="Debug">
10+
<option name="DEBUG_PORT" value="5007" />
11+
<option name="LOCAL" value="false" />
12+
</RunnerSettings>
13+
<method v="2" />
14+
</configuration>
15+
</component>

build.gradle.kts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,6 @@ plugins {
1919
`maven-publish`
2020
}
2121

22-
configure<JavaPluginExtension> {
23-
sourceCompatibility = VERSION_11
24-
targetCompatibility = VERSION_17
25-
}
26-
2722
allprojects {
2823

2924
apply {

gradle.properties

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ pytorchNativeVersion=1.9.1
7777
shadowJarVersion=7.1.2
7878
openblasVersion=0.3.10-1.5.4
7979
arpackNgVersion=3.7.0-1.5.4
80+
commonsLoggingVersion=1.2
81+
commonsIOVersion=2.11.0
82+
springBootVersion=2.7.8
8083

8184
# configuration for build server
8285
#

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

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ object UtSettings : AbstractSettings(logger, defaultKeyForSettingsPath, defaultS
283283
var runEngineProcessWithDebug by getBooleanProperty(false)
284284

285285
/**
286-
* The engine process JDWP agent's port of the instrumented process.
286+
* The engine process JDWP agent's port of the engine process.
287287
* A debugger attaches to the port in order to debug the process.
288288
*/
289289
var engineProcessDebugPort by getIntProperty(5005)
@@ -296,6 +296,29 @@ object UtSettings : AbstractSettings(logger, defaultKeyForSettingsPath, defaultS
296296

297297
// endregion
298298

299+
// region spring analyzer process debug
300+
/**
301+
* The property is useful only for the IntelliJ IDEs.
302+
* If the property is set in true the spring analyzer process opens a debug port.
303+
* @see runInstrumentedProcessWithDebug
304+
* @see org.utbot.framework.process.SpringAnalyzerProcess
305+
*/
306+
var runSpringAnalyzerProcessWithDebug by getBooleanProperty(false)
307+
308+
/**
309+
* The spring analyzer process JDWP agent's port.
310+
* A debugger attaches to the port in order to debug the process.
311+
*/
312+
var springAnalyzerProcessDebugPort by getIntProperty(5007)
313+
314+
/**
315+
* Value of the suspend mode for the JDWP agent of the spring analyzer process.
316+
* If the value is true, the spring analyzer process will suspend until a debugger attaches to it.
317+
*/
318+
var suspendSpringAnalyzerProcessExecutionInDebugMode by getBooleanProperty(true)
319+
320+
// endregion
321+
299322
// region instrumented process debug
300323
/**
301324
* The instrumented process JDWP agent's port of the instrumented process.
@@ -312,15 +335,16 @@ object UtSettings : AbstractSettings(logger, defaultKeyForSettingsPath, defaultS
312335
/**
313336
* If true, runs the instrumented process with the ability to attach a debugger.
314337
*
315-
* To debug the instrumented process, set the breakpoint in the instrumentedProcessRunner.start() line
338+
* To debug the instrumented process, set the breakpoint in the
339+
* [org.utbot.instrumentation.rd.InstrumentedProcess.Companion.invoke]
316340
* and in the instrumented process's main function and run the main process.
317341
* Then run the remote JVM debug configuration in IDEA.
318342
* If you see the message in console about successful connection, then
319343
* the debugger is attached successfully.
320344
* Now you can put the breakpoints in the instrumented process and debug
321345
* both processes simultaneously.
322346
*
323-
* @see [org.utbot.instrumentation.process.InstrumentedProcessRunner.cmds]
347+
* @see [org.utbot.instrumentation.rd.InstrumentedProcess.Companion.invoke]
324348
*/
325349
var runInstrumentedProcessWithDebug by getBooleanProperty(false)
326350
// endregion

utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/services/JdkInfoService.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ data class JdkInfo(
1111
/**
1212
* Singleton to enable abstract access to path to JDK.
1313
14-
* Used in [org.utbot.instrumentation.process.InstrumentedProcessRunner].
14+
* Used in [org.utbot.framework.process.AbstractRDProcessCompanion].
1515
* The purpose is to use the same JDK in [org.utbot.instrumentation.ConcreteExecutor] and in the test runs.
1616
* This is necessary because the engine can be run from the various starting points, like IDEA plugin, CLI, etc.
1717
*/

utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/services/WorkingDirService.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import java.nio.file.Paths
66
/**
77
* Singleton to enable abstract access to the working directory.
88
*
9-
* Used in [org.utbot.instrumentation.process.InstrumentedProcessRunner].
9+
* Used in [org.utbot.instrumentation.rd.InstrumentedProcess].
1010
* The purpose is to use the same working directory in [org.utbot.instrumentation.ConcreteExecutor]
1111
* and in the test runs.
1212
*/
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package org.utbot.framework.process
2+
3+
import org.utbot.common.osSpecificJavaExecutable
4+
import org.utbot.framework.plugin.services.JdkInfoService
5+
import org.utbot.rd.rdPortArgument
6+
import java.io.File
7+
import kotlin.io.path.pathString
8+
9+
abstract class AbstractRDProcessCompanion(
10+
private val debugPort: Int,
11+
private val runWithDebug: Boolean,
12+
private val suspendExecutionInDebugMode: Boolean
13+
) {
14+
private val javaExecutablePathString get() =
15+
JdkInfoService.provide().path.resolve("bin${File.separatorChar}${osSpecificJavaExecutable()}")
16+
17+
protected abstract fun obtainProcessSpecificCommandLineArgs(): List<String>
18+
19+
protected fun obtainProcessCommandLine(port: Int): List<String> = buildList {
20+
addAll(obtainCommonProcessCommandLineArgs())
21+
addAll(obtainProcessSpecificCommandLineArgs())
22+
add(rdPortArgument(port))
23+
}
24+
25+
private fun obtainCommonProcessCommandLineArgs(): List<String> = buildList {
26+
val suspendValue = if (suspendExecutionInDebugMode) "y" else "n"
27+
val debugArgument =
28+
"-agentlib:jdwp=transport=dt_socket,server=n,suspend=${suspendValue},quiet=y,address=$debugPort"
29+
.takeIf { runWithDebug }
30+
31+
add(javaExecutablePathString.pathString)
32+
val javaVersionSpecificArgs = OpenModulesContainer.javaVersionSpecificArguments
33+
if (javaVersionSpecificArgs.isNotEmpty()) {
34+
addAll(javaVersionSpecificArgs)
35+
}
36+
debugArgument?.let { add(it) }
37+
}
38+
}

utbot-framework-api/src/main/kotlin/org/utbot/framework/process/OpenModulesContainer.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ object OpenModulesContainer {
1111
init {
1212
modulesContainer = buildList {
1313
openPackage("java.base", "sun.security.util")
14+
openPackage("java.base", "sun.reflect.annotation")
1415
openPackage("java.base", "java.text")
1516
openPackage("java.base", "java.lang.invoke")
1617
openPackage("java.base", "jdk.internal.misc")

utbot-framework/build.gradle

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
configurations {
2+
fetchSpringAnalyzerJar
3+
}
4+
15
dependencies {
26

37
api project(':utbot-fuzzers')
@@ -34,4 +38,13 @@ dependencies {
3438

3539
implementation group: 'com.github.UnitTestBot.ksmt', name: 'ksmt-core', version: ksmtVersion
3640
implementation group: 'com.github.UnitTestBot.ksmt', name: 'ksmt-z3', version: ksmtVersion
41+
implementation project(':utbot-spring-analyzer')
42+
43+
fetchSpringAnalyzerJar project(path: ':utbot-spring-analyzer', configuration: 'springAnalyzerJar')
44+
}
45+
46+
processResources {
47+
from(configurations.fetchSpringAnalyzerJar) {
48+
into "lib"
49+
}
3750
}

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/Domain.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package org.utbot.framework.codegen.domain
33
import org.utbot.framework.DEFAULT_EXECUTION_TIMEOUT_IN_INSTRUMENTED_PROCESS_MS
44
import org.utbot.framework.codegen.domain.builtin.mockitoClassId
55
import org.utbot.framework.codegen.domain.builtin.ongoingStubbingClassId
6-
import org.utbot.framework.codegen.domain.context.CgContext
76
import org.utbot.framework.codegen.domain.models.CgClassId
87
import org.utbot.framework.codegen.tree.argumentsClassId
98
import org.utbot.framework.plugin.api.BuiltinClassId
@@ -751,7 +750,7 @@ sealed class TypeReplacementApproach {
751750
*
752751
* Currently used in Spring applications only.
753752
*/
754-
class ReplaceIfPossible(val configFqn: String) : TypeReplacementApproach()
753+
class ReplaceIfPossible(val config: String) : TypeReplacementApproach()
755754
}
756755

757756
abstract class DependencyInjectionFramework(

utbot-framework/src/main/kotlin/org/utbot/framework/process/EngineProcessMain.kt

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,10 @@ import org.utbot.rd.RdSettingsContainerFactory
3434
import org.utbot.rd.findRdPort
3535
import org.utbot.rd.generated.settingsModel
3636
import org.utbot.rd.loggers.UtRdKLoggerFactory
37+
import org.utbot.rd.terminateOnException
3738
import org.utbot.sarif.RdSourceFindingStrategyFacade
3839
import org.utbot.sarif.SarifReport
40+
import org.utbot.spring.process.SpringAnalyzerProcess
3941
import org.utbot.summary.summarizeAll
4042
import java.io.File
4143
import java.net.URLClassLoader
@@ -51,16 +53,11 @@ object EngineProcessMain
5153

5254
// use log4j2.configurationFile property to set log4j configuration
5355
suspend fun main(args: Array<String>) = runBlocking {
54-
Logger.set(Lifetime.Eternal, UtRdKLoggerFactory(logger))
55-
5656
logger.info("-----------------------------------------------------------------------")
5757
logger.info("-------------------NEW ENGINE PROCESS STARTED--------------------------")
5858
logger.info("-----------------------------------------------------------------------")
59-
// 0 - auto port for server, should not be used here
60-
val port = findRdPort(args)
61-
6259

63-
ClientProtocolBuilder().withProtocolTimeout(messageFromMainTimeoutMillis).start(port) {
60+
ClientProtocolBuilder().withProtocolTimeout(messageFromMainTimeoutMillis).start(args) {
6461
AbstractSettings.setupFactory(RdSettingsContainerFactory(protocol.settingsModel))
6562
val kryoHelper = KryoHelper(lifetime)
6663
engineProcessModel.setup(kryoHelper, it, protocol)
@@ -79,6 +76,21 @@ private fun EngineProcessModel.setup(kryoHelper: KryoHelper, watchdog: IdleWatch
7976
File(it).toURI().toURL()
8077
}.toTypedArray())))
8178
}
79+
watchdog.measureTimeForActiveCall(getSpringBeanQualifiedNames, "Getting Spring bean definitions") { params ->
80+
val springAnalyzerProcess = SpringAnalyzerProcess.createBlocking()
81+
val beans = springAnalyzerProcess.terminateOnException { _ ->
82+
springAnalyzerProcess.getBeanQualifiedNames(
83+
params.classpath.toList(),
84+
params.config,
85+
// TODO remove once spring-analyzer learns to find resources on its own, temporarily leaving it here for testing with hardcoded absolute paths
86+
propertyFilesPaths = emptyList(),
87+
xmlConfigurationPaths = emptyList(),
88+
params.useSpringAnalyzer
89+
).toTypedArray()
90+
}
91+
springAnalyzerProcess.terminate()
92+
beans
93+
}
8294
watchdog.measureTimeForActiveCall(createTestGenerator, "Creating Test Generator") { params ->
8395
AnalyticsConfigureUtil.configureML()
8496
Instrumenter.adapter = RdInstrumenter(realProtocol.rdInstrumenterAdapter)

0 commit comments

Comments
 (0)