Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ import org.utbot.framework.plugin.api.TypeReplacementMode.*
import org.utbot.framework.plugin.api.util.allDeclaredFieldIds
import org.utbot.framework.plugin.api.util.fieldId
import org.utbot.framework.plugin.api.util.isSubtypeOf
import org.utbot.framework.plugin.api.util.objectClassId
import org.utbot.framework.plugin.api.util.utContext
import org.utbot.framework.process.OpenModulesContainer
import soot.SootField
Expand Down Expand Up @@ -1258,13 +1257,13 @@ open class ApplicationContext(
* Data we get from Spring application context
* to manage engine and code generator behaviour.
*
* @param beanQualifiedNames describes fqn of types from bean definitions
* @param beanDefinitions describes bean definitions (bean name, type, some optional additional data)
* @param shouldUseImplementors describes it we want to replace interfaces with injected types or not
*/
class SpringApplicationContext(
mockInstalled: Boolean,
staticsMockingIsConfigured: Boolean,
private val beanQualifiedNames: List<String> = emptyList(),
private val beanDefinitions: List<BeanDefinitionData> = emptyList(),
private val shouldUseImplementors: Boolean,
): ApplicationContext(mockInstalled, staticsMockingIsConfigured) {

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

/**
* Describes information about beans obtained from Spring analysis process.
*
* Contains the name of the bean, its type (class or interface) and optional additional data.
*/
data class BeanDefinitionData(
val beanName: String,
val beanTypeFqn: String,
val additionalData: BeanAdditionalData?,
)

/**
* Describes some additional information about beans obtained from Spring analysis process.
*
* Sometimes the actual type of the bean can not be obtained from bean definition.
* Then we try to recover it by method and class defining bean (e.g. using Psi elements).
*/
data class BeanAdditionalData(
val factoryMethodName: String,
val configClassFqn: String,
)


val RefType.isAbstractType
get() = this.sootClass.isAbstract || this.sootClass.isInterface

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import org.utbot.framework.plugin.api.util.jClass
import org.utbot.framework.plugin.api.util.method
import org.utbot.framework.plugin.services.JdkInfo
import org.utbot.framework.process.generated.*
import org.utbot.framework.process.generated.BeanAdditionalData
import org.utbot.framework.process.generated.BeanDefinitionData
import org.utbot.instrumentation.instrumentation.instrumenter.Instrumenter
import org.utbot.instrumentation.util.KryoHelper
import org.utbot.rd.IdleWatchdog
Expand Down Expand Up @@ -72,21 +74,27 @@ private fun EngineProcessModel.setup(kryoHelper: KryoHelper, watchdog: IdleWatch
File(it).toURI().toURL()
}.toTypedArray())))
}
watchdog.measureTimeForActiveCall(getSpringBeanQualifiedNames, "Getting Spring bean definitions") { params ->
watchdog.measureTimeForActiveCall(getSpringBeanDefinitions, "Getting Spring bean definitions") { params ->
try {
val springAnalyzerProcess = SpringAnalyzerProcess.createBlocking(params.classpath.toList())
val beans = springAnalyzerProcess.terminateOnException { _ ->
springAnalyzerProcess.getBeanQualifiedNames(
val result = springAnalyzerProcess.terminateOnException { _ ->
springAnalyzerProcess.getBeanDefinitions(
params.config,
params.fileStorage,
params.profileExpression,
).toTypedArray()
)
}
springAnalyzerProcess.terminate()
beans
val beanDefinitions = result.beanDefinitions
.map { data ->
val additionalData = data.additionalData?.let { BeanAdditionalData(it.factoryMethodName, it.configClassFqn) }
BeanDefinitionData(data.beanName, data.beanTypeFqn, additionalData)
}
.toTypedArray()
SpringAnalyzerResult(beanDefinitions)
} catch (e: Exception) {
logger.error(e) { "Spring Analyzer crushed, resorting to using empty bean list" }
emptyArray()
logger.error(e) { "Spring Analyzer crashed, resorting to using empty bean list" }
SpringAnalyzerResult(emptyArray())
}
}
watchdog.measureTimeForActiveCall(createTestGenerator, "Creating Test Generator") { params ->
Expand Down
Loading