Skip to content

Commit b587f6c

Browse files
Enlarge model returned from utbot-spring-analyzer (#2200)
1 parent 0cceaa4 commit b587f6c

File tree

16 files changed

+479
-72
lines changed

16 files changed

+479
-72
lines changed

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

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ import org.utbot.framework.plugin.api.TypeReplacementMode.*
6262
import org.utbot.framework.plugin.api.util.allDeclaredFieldIds
6363
import org.utbot.framework.plugin.api.util.fieldId
6464
import org.utbot.framework.plugin.api.util.isSubtypeOf
65-
import org.utbot.framework.plugin.api.util.objectClassId
6665
import org.utbot.framework.plugin.api.util.utContext
6766
import org.utbot.framework.process.OpenModulesContainer
6867
import soot.SootField
@@ -1258,13 +1257,13 @@ open class ApplicationContext(
12581257
* Data we get from Spring application context
12591258
* to manage engine and code generator behaviour.
12601259
*
1261-
* @param beanQualifiedNames describes fqn of types from bean definitions
1260+
* @param beanDefinitions describes bean definitions (bean name, type, some optional additional data)
12621261
* @param shouldUseImplementors describes it we want to replace interfaces with injected types or not
12631262
*/
12641263
class SpringApplicationContext(
12651264
mockInstalled: Boolean,
12661265
staticsMockingIsConfigured: Boolean,
1267-
private val beanQualifiedNames: List<String> = emptyList(),
1266+
private val beanDefinitions: List<BeanDefinitionData> = emptyList(),
12681267
private val shouldUseImplementors: Boolean,
12691268
): ApplicationContext(mockInstalled, staticsMockingIsConfigured) {
12701269

@@ -1278,7 +1277,8 @@ class SpringApplicationContext(
12781277
private val springInjectedClasses: Set<ClassId>
12791278
get() {
12801279
if (!areInjectedClassesInitialized) {
1281-
for (beanFqn in beanQualifiedNames) {
1280+
// TODO: use more info from SpringBeanDefinitionData than beanTypeFqn offers here
1281+
for (beanFqn in beanDefinitions.map { it.beanTypeFqn }) {
12821282
try {
12831283
val beanClass = utContext.classLoader.loadClass(beanFqn)
12841284
if (!beanClass.isAbstract && !beanClass.isInterface &&
@@ -1341,6 +1341,29 @@ class SpringApplicationContext(
13411341
): Boolean = field.fieldId in classUnderTest.allDeclaredFieldIds && field.declaringClass.id !in springInjectedClasses
13421342
}
13431343

1344+
/**
1345+
* Describes information about beans obtained from Spring analysis process.
1346+
*
1347+
* Contains the name of the bean, its type (class or interface) and optional additional data.
1348+
*/
1349+
data class BeanDefinitionData(
1350+
val beanName: String,
1351+
val beanTypeFqn: String,
1352+
val additionalData: BeanAdditionalData?,
1353+
)
1354+
1355+
/**
1356+
* Describes some additional information about beans obtained from Spring analysis process.
1357+
*
1358+
* Sometimes the actual type of the bean can not be obtained from bean definition.
1359+
* Then we try to recover it by method and class defining bean (e.g. using Psi elements).
1360+
*/
1361+
data class BeanAdditionalData(
1362+
val factoryMethodName: String,
1363+
val configClassFqn: String,
1364+
)
1365+
1366+
13441367
val RefType.isAbstractType
13451368
get() = this.sootClass.isAbstract || this.sootClass.isInterface
13461369

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

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import org.utbot.framework.plugin.api.util.jClass
2424
import org.utbot.framework.plugin.api.util.method
2525
import org.utbot.framework.plugin.services.JdkInfo
2626
import org.utbot.framework.process.generated.*
27+
import org.utbot.framework.process.generated.BeanAdditionalData
28+
import org.utbot.framework.process.generated.BeanDefinitionData
2729
import org.utbot.instrumentation.instrumentation.instrumenter.Instrumenter
2830
import org.utbot.instrumentation.util.KryoHelper
2931
import org.utbot.rd.IdleWatchdog
@@ -72,21 +74,27 @@ private fun EngineProcessModel.setup(kryoHelper: KryoHelper, watchdog: IdleWatch
7274
File(it).toURI().toURL()
7375
}.toTypedArray())))
7476
}
75-
watchdog.measureTimeForActiveCall(getSpringBeanQualifiedNames, "Getting Spring bean definitions") { params ->
77+
watchdog.measureTimeForActiveCall(getSpringBeanDefinitions, "Getting Spring bean definitions") { params ->
7678
try {
7779
val springAnalyzerProcess = SpringAnalyzerProcess.createBlocking(params.classpath.toList())
78-
val beans = springAnalyzerProcess.terminateOnException { _ ->
79-
springAnalyzerProcess.getBeanQualifiedNames(
80+
val result = springAnalyzerProcess.terminateOnException { _ ->
81+
springAnalyzerProcess.getBeanDefinitions(
8082
params.config,
8183
params.fileStorage,
8284
params.profileExpression,
83-
).toTypedArray()
85+
)
8486
}
8587
springAnalyzerProcess.terminate()
86-
beans
88+
val beanDefinitions = result.beanDefinitions
89+
.map { data ->
90+
val additionalData = data.additionalData?.let { BeanAdditionalData(it.factoryMethodName, it.configClassFqn) }
91+
BeanDefinitionData(data.beanName, data.beanTypeFqn, additionalData)
92+
}
93+
.toTypedArray()
94+
SpringAnalyzerResult(beanDefinitions)
8795
} catch (e: Exception) {
88-
logger.error(e) { "Spring Analyzer crushed, resorting to using empty bean list" }
89-
emptyArray()
96+
logger.error(e) { "Spring Analyzer crashed, resorting to using empty bean list" }
97+
SpringAnalyzerResult(emptyArray())
9098
}
9199
}
92100
watchdog.measureTimeForActiveCall(createTestGenerator, "Creating Test Generator") { params ->

0 commit comments

Comments
 (0)