diff --git a/settings.gradle.kts b/settings.gradle.kts index 78ff02e22e..3a54a76c59 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -56,6 +56,7 @@ if (includeRiderInBuild.toBoolean()) { include("utbot-ui-commons") +include("utbot-spring-framework") include("utbot-spring-commons-api") include("utbot-spring-commons") include("utbot-spring-analyzer") diff --git a/utbot-core/src/main/kotlin/org/utbot/common/DynamicProperties.kt b/utbot-core/src/main/kotlin/org/utbot/common/DynamicProperties.kt index be6fe3f6a9..666929bbbb 100644 --- a/utbot-core/src/main/kotlin/org/utbot/common/DynamicProperties.kt +++ b/utbot-core/src/main/kotlin/org/utbot/common/DynamicProperties.kt @@ -36,6 +36,11 @@ interface MutableDynamicProperties : DynamicProperties { operator fun set(property: DynamicProperty, value: T) } +fun MutableDynamicProperties.getOrPut(property: DynamicProperty, default: () -> T): T { + if (property !in this) set(property, default()) + return getValue(property) +} + fun Iterable>.toMutableDynamicProperties(): MutableDynamicProperties = DynamicPropertiesImpl().also { properties -> forEach { properties.add(it) } diff --git a/utbot-framework/build.gradle b/utbot-framework/build.gradle index 3b4e7b3a9e..b56b4bfb88 100644 --- a/utbot-framework/build.gradle +++ b/utbot-framework/build.gradle @@ -3,8 +3,6 @@ plugins { } configurations { - fetchSpringAnalyzerJar - fetchSpringCommonsJar fetchInstrumentationJar } @@ -48,23 +46,10 @@ dependencies { implementation group: 'com.github.UnitTestBot.ksmt', name: 'ksmt-z3', version: ksmtVersion fetchInstrumentationJar project(path: ':utbot-instrumentation', configuration: 'instrumentationArchive') - - implementation project(':utbot-spring-commons-api') - implementation project(':utbot-spring-analyzer') - fetchSpringAnalyzerJar project(path: ':utbot-spring-analyzer', configuration: 'springAnalyzerJar') - fetchSpringCommonsJar project(path: ':utbot-spring-commons', configuration: 'springCommonsJar') } processResources { from(configurations.fetchInstrumentationJar) { into "lib" } - - from(configurations.fetchSpringAnalyzerJar) { - into "lib" - } - - from(configurations.fetchSpringCommonsJar) { - into "lib" - } } diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/assemble/AssembleModelGenerator.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/assemble/AssembleModelGenerator.kt index bdb4fc6868..3ba048cffc 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/assemble/AssembleModelGenerator.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/assemble/AssembleModelGenerator.kt @@ -205,12 +205,12 @@ class AssembleModelGenerator(private val basePackageName: String) { is UtClassRefModel, is UtVoidModel, is UtEnumConstantModel, - is UtCustomModel -> utModel + is UtCustomModel -> utModel // for example, UtSpringContextModel is UtLambdaModel -> assembleLambdaModel(utModel) is UtArrayModel -> assembleArrayModel(utModel) is UtCompositeModel -> assembleCompositeModel(utModel) is UtAssembleModel -> assembleAssembleModel(utModel) - // Python, JavaScript, UtSpringContextModel are supposed to be here as well + // Python, JavaScript are supposed to be here as well else -> utModel } } catch (e: AssembleException) { diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/Domain.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/Domain.kt index 0def0daa04..d64f54c186 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/Domain.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/Domain.kt @@ -711,47 +711,6 @@ enum class ProjectType { JavaScript, } -abstract class DependencyInjectionFramework( - override val id: String, - override val displayName: String, - override val description: String = "Use $displayName as dependency injection framework", - val testFrameworkDisplayName: String, - /** - * Generation Spring specific tests requires special spring test framework being installed, - * so we can use `TestContextManager` from `spring-test` to configure test context in - * spring-analyzer and to run integration tests. - */ - var testFrameworkInstalled: Boolean = false -) : CodeGenerationSettingItem { - var isInstalled = false - - companion object : CodeGenerationSettingBox { - override val defaultItem: DependencyInjectionFramework get() = SpringBoot - override val allItems: List get() = listOf(SpringBoot, SpringBeans) - - val installedItems get() = allItems.filter { it.isInstalled } - - /** - * Generation Spring specific tests requires special spring test framework being installed, - * so we can use `TestContextManager` from `spring-test` to configure test context in - * spring-analyzer and to run integration tests. - */ - var testFrameworkInstalled: Boolean = false - } -} - -object SpringBeans : DependencyInjectionFramework( - id = "spring-beans", - displayName = "Spring Beans", - testFrameworkDisplayName = "spring-test", -) - -object SpringBoot : DependencyInjectionFramework( - id = "spring-boot", - displayName = "Spring Boot", - testFrameworkDisplayName = "spring-boot-test", -) - /** * Extended [UtModel] model with testSet id and execution id. * diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/builtin/MockitoBuiltins.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/builtin/MockitoBuiltins.kt index 4ac8a665e9..d78bd10b3d 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/builtin/MockitoBuiltins.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/builtin/MockitoBuiltins.kt @@ -20,21 +20,6 @@ internal val mockitoClassId = BuiltinClassId( simpleName = "Mockito", ) -internal val mockClassId = BuiltinClassId( - canonicalName = "org.mockito.Mock", - simpleName = "Mock", -) - -internal val spyClassId = BuiltinClassId( - canonicalName = "org.mockito.Spy", - simpleName = "Spy" -) - -internal val injectMocksClassId = BuiltinClassId( - canonicalName = "org.mockito.InjectMocks", - simpleName = "InjectMocks", -) - internal val ongoingStubbingClassId = BuiltinClassId( canonicalName = "org.mockito.stubbing.OngoingStubbing", simpleName = "OngoingStubbing", diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/builtin/UtilMethodBuiltins.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/builtin/UtilMethodBuiltins.kt index 6cda7456cd..f438f12cd6 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/builtin/UtilMethodBuiltins.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/builtin/UtilMethodBuiltins.kt @@ -278,7 +278,7 @@ internal class UtilClassFileMethodProvider(language: CodegenLanguage) val UTIL_CLASS_VERSION = "2.1" } -internal class TestClassUtilMethodProvider(testClassId: ClassId) : UtilMethodProvider(testClassId) +class TestClassUtilMethodProvider(testClassId: ClassId) : UtilMethodProvider(testClassId) internal fun selectUtilClassId(codegenLanguage: CodegenLanguage): ClassId = when (codegenLanguage) { diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/context/CgContext.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/context/CgContext.kt index ad92f3078d..219f846907 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/context/CgContext.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/context/CgContext.kt @@ -13,6 +13,9 @@ import kotlinx.collections.immutable.PersistentSet import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentMapOf import kotlinx.collections.immutable.persistentSetOf +import org.utbot.common.DynamicProperty +import org.utbot.common.MutableDynamicProperties +import org.utbot.common.mutableDynamicPropertiesOf import org.utbot.framework.codegen.domain.UtModelWrapper import org.utbot.framework.codegen.domain.ProjectType import org.utbot.framework.codegen.domain.builtin.TestClassUtilMethodProvider @@ -25,7 +28,6 @@ import org.utbot.framework.codegen.tree.importIfNeeded import org.utbot.framework.plugin.api.BuiltinClassId import org.utbot.framework.plugin.api.ClassId import org.utbot.framework.codegen.services.language.CgLanguageAssistant -import org.utbot.framework.codegen.tree.fieldmanager.CgAbstractClassFieldManager import org.utbot.framework.plugin.api.CodegenLanguage import org.utbot.framework.plugin.api.ExecutableId import org.utbot.framework.plugin.api.FieldId @@ -38,6 +40,9 @@ import org.utbot.framework.plugin.api.util.isCheckedException import org.utbot.framework.plugin.api.util.isSubtypeOf import org.utbot.framework.plugin.api.util.jClass +typealias CgContextProperties = MutableDynamicProperties +typealias CgContextProperty = DynamicProperty + /** * Interface for all code generation context aware entities * @@ -243,10 +248,16 @@ interface CgContextOwner { var successfulExecutionsModels: List /** - * Managers to process annotated fields of the class under test - * relevant for the current generation type. + * Many of [CgContext] properties are only needed in some specific scenarios + * (e.g. Spring-related properties and parametrized test specific properties). + * + * To avoid overly inflating [CgContext] interface such properties should + * be added as dynamic properties. + * + * @see DynamicProperty */ - val relevantFieldManagers: MutableList + // TODO make parameterized test specific properties dynamic + val properties: CgContextProperties fun block(init: () -> Unit): Block { val prevBlock = currentBlock @@ -509,8 +520,8 @@ class CgContext( RuntimeExceptionTestsBehaviour.defaultItem, override val hangingTestsTimeout: HangingTestsTimeout = HangingTestsTimeout(), override val enableTestsTimeout: Boolean = true, - override val relevantFieldManagers: MutableList = mutableListOf(), override var containsReflectiveCall: Boolean = false, + override val properties: CgContextProperties = mutableDynamicPropertiesOf(), ) : CgContextOwner { override lateinit var statesCache: EnvironmentFieldStateCache override lateinit var actual: CgVariable @@ -667,5 +678,6 @@ class CgContext( hangingTestsTimeout = this.hangingTestsTimeout, enableTestsTimeout = this.enableTestsTimeout, containsReflectiveCall = this.containsReflectiveCall, + properties = this.properties, ) } \ No newline at end of file diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/services/access/CgCallableAccessManager.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/services/access/CgCallableAccessManager.kt index cb29b17f6f..1c2b015c06 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/services/access/CgCallableAccessManager.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/services/access/CgCallableAccessManager.kt @@ -87,7 +87,7 @@ interface CgCallableAccessManager { operator fun ClassId.get(fieldId: FieldId): CgStaticFieldAccess } -internal class CgCallableAccessManagerImpl(val context: CgContext) : CgCallableAccessManager, +class CgCallableAccessManagerImpl(val context: CgContext) : CgCallableAccessManager, CgContextOwner by context { private val statementConstructor by lazy { getStatementConstructorBy(context) } diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/services/framework/TestFrameworkManager.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/services/framework/TestFrameworkManager.kt index 7cc8ab4015..871518e71e 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/services/framework/TestFrameworkManager.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/services/framework/TestFrameworkManager.kt @@ -25,9 +25,6 @@ import org.utbot.framework.plugin.api.BuiltinMethodId import org.utbot.framework.plugin.api.ClassId import org.utbot.framework.plugin.api.CodegenLanguage import org.utbot.framework.plugin.api.ConstructorId -import org.utbot.framework.plugin.api.util.SpringModelUtils.extendWithClassId -import org.utbot.framework.plugin.api.util.SpringModelUtils.runWithClassId -import org.utbot.framework.plugin.api.util.SpringModelUtils.springExtensionClassId import org.utbot.framework.plugin.api.util.booleanArrayClassId import org.utbot.framework.plugin.api.util.byteArrayClassId import org.utbot.framework.plugin.api.util.charArrayClassId diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/ConstructorUtils.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/ConstructorUtils.kt index cf56a49cf3..f4e8cf6d7e 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/ConstructorUtils.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/ConstructorUtils.kt @@ -255,7 +255,7 @@ fun CgContextOwner.importIfNeeded(type: ClassId) { } } -internal fun CgContextOwner.importIfNeeded(method: MethodId) { +fun CgContextOwner.importIfNeeded(method: MethodId) { val name = method.name val packageName = method.classId.packageName method.takeIf { it.isStatic && packageName != testClassPackageName && packageName != "java.lang" } diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/ututils/UtilClassKind.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/ututils/UtilClassKind.kt index 6df90f7192..7b318f9678 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/ututils/UtilClassKind.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/ututils/UtilClassKind.kt @@ -120,7 +120,7 @@ sealed class UtilClassKind( * @return `null` if [CgContext.utilMethodProvider] is not [UtilClassFileMethodProvider], * because it means that util methods will be taken from some other provider (e.g. [TestClassUtilMethodProvider]). */ - internal fun fromCgContextOrNull(context: CgContext): UtilClassKind? { + fun fromCgContextOrNull(context: CgContext): UtilClassKind? { if (context.requiredUtilMethods.isEmpty()) return null if (!context.mockFrameworkUsed) { return RegularUtUtils(context.codegenLanguage) diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/plugin/api/TestCaseGenerator.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/plugin/api/TestCaseGenerator.kt index 7980c7e3be..a04cad2149 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/plugin/api/TestCaseGenerator.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/plugin/api/TestCaseGenerator.kt @@ -38,8 +38,6 @@ import org.utbot.framework.util.ConflictTriggers import org.utbot.framework.util.SootUtils import org.utbot.framework.util.jimpleBody import org.utbot.framework.util.toModel -import org.utbot.framework.plugin.api.SpringSettings.* -import org.utbot.framework.plugin.api.SpringTestType.* import org.utbot.instrumentation.ConcreteExecutor import org.utbot.instrumentation.warmup import org.utbot.taint.TaintConfigurationProvider diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/plugin/api/utils/DependencyPatterns.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/plugin/api/utils/DependencyPatterns.kt index 9effee7219..57397e0d4c 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/plugin/api/utils/DependencyPatterns.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/plugin/api/utils/DependencyPatterns.kt @@ -1,10 +1,7 @@ package org.utbot.framework.plugin.api.utils -import org.utbot.framework.codegen.domain.DependencyInjectionFramework import org.utbot.framework.codegen.domain.Junit4 import org.utbot.framework.codegen.domain.Junit5 -import org.utbot.framework.codegen.domain.SpringBeans -import org.utbot.framework.codegen.domain.SpringBoot import org.utbot.framework.codegen.domain.TestFramework import org.utbot.framework.codegen.domain.TestNg import org.utbot.framework.plugin.api.MockFramework @@ -61,36 +58,6 @@ fun MockFramework.patterns(): Patterns { return Patterns(moduleLibraryPatterns, libraryPatterns) } -fun DependencyInjectionFramework.patterns(): Patterns { - val moduleLibraryPatterns = when (this) { - SpringBoot -> springBootModulePatterns - SpringBeans -> springBeansModulePatterns - else -> throw UnsupportedOperationException("Unknown dependency injection framework $this") - } - val libraryPatterns = when (this) { - SpringBoot -> springBootPatterns - SpringBeans -> springBeansPatterns - else -> throw UnsupportedOperationException("Unknown dependency injection framework $this") - } - - return Patterns(moduleLibraryPatterns, libraryPatterns) -} - -fun DependencyInjectionFramework.testPatterns(): Patterns { - val moduleLibraryPatterns = when (this) { - SpringBoot -> springBootTestModulePatterns - SpringBeans -> springBeansTestModulePatterns - else -> throw UnsupportedOperationException("Unknown dependency injection framework $this") - } - val libraryPatterns = when (this) { - SpringBoot -> springBootTestPatterns - SpringBeans -> springBeansTestPatterns - else -> throw UnsupportedOperationException("Unknown dependency injection framework $this") - } - - return Patterns(moduleLibraryPatterns, libraryPatterns) -} - val JUNIT_4_JAR_PATTERN = Regex("junit-4(\\.1[2-9])(\\.[0-9]+)?") val JUNIT_4_MVN_PATTERN = Regex("junit:junit:4(\\.1[2-9])(\\.[0-9]+)?") val junit4Patterns = listOf(JUNIT_4_JAR_PATTERN, JUNIT_4_MVN_PATTERN) @@ -127,32 +94,3 @@ val mockitoModulePatterns = listOf(MOCKITO_BASIC_MODULE_PATTERN) const val MOCKITO_EXTENSIONS_FOLDER = "mockito-extensions" const val MOCKITO_MOCKMAKER_FILE_NAME = "org.mockito.plugins.MockMaker" val MOCKITO_EXTENSIONS_FILE_CONTENT = "mock-maker-inline" - -val SPRING_BEANS_JAR_PATTERN = Regex("spring-beans-([0-9]+)(\\.[0-9]+){1,2}") -val SPRING_BEANS_MVN_PATTERN = Regex("org\\.springframework:spring-beans:([0-9]+)(\\.[0-9]+){1,2}") -val springBeansPatterns = listOf(SPRING_BEANS_JAR_PATTERN, SPRING_BEANS_MVN_PATTERN) - -val SPRING_BEANS_BASIC_MODULE_PATTERN = Regex("spring-beans") -val springBeansModulePatterns = listOf(SPRING_BEANS_BASIC_MODULE_PATTERN) - -val SPRING_BEANS_TEST_JAR_PATTERN = Regex("spring-test-([0-9]+)(\\.[0-9]+){1,2}") -val SPRING_BEANS_TEST_MVN_PATTERN = Regex("org\\.springframework:spring-test:([0-9]+)(\\.[0-9]+){1,2}") -val springBeansTestPatterns = listOf(SPRING_BEANS_TEST_JAR_PATTERN, SPRING_BEANS_TEST_MVN_PATTERN) - -val SPRING_BEANS_TEST_BASIC_MODULE_PATTERN = Regex("spring-test") -val springBeansTestModulePatterns = listOf(SPRING_BEANS_TEST_BASIC_MODULE_PATTERN) - -val SPRING_BOOT_JAR_PATTERN = Regex("spring-boot-([0-9]+)(\\.[0-9]+){1,2}") -val SPRING_BOOT_MVN_PATTERN = Regex("org\\.springframework\\.boot:spring-boot:([0-9]+)(\\.[0-9]+){1,2}") -val springBootPatterns = listOf(SPRING_BOOT_JAR_PATTERN, SPRING_BOOT_MVN_PATTERN) - -val SPRING_BOOT_BASIC_MODULE_PATTERN = Regex("spring-boot") -val springBootModulePatterns = listOf(SPRING_BOOT_BASIC_MODULE_PATTERN) - -val SPRING_BOOT_TEST_JAR_PATTERN = Regex("spring-boot-test-([0-9]+)(\\.[0-9]+){1,2}") -val SPRING_BOOT_TEST_MVN_PATTERN = Regex("org\\.springframework\\.boot:spring-boot-test:([0-9]+)(\\.[0-9]+){1,2}") - -val springBootTestPatterns = listOf(SPRING_BOOT_TEST_JAR_PATTERN, SPRING_BOOT_TEST_MVN_PATTERN) - -val SPRING_BOOT_TEST_BASIC_MODULE_PATTERN = Regex("spring-boot-test") -val springBootTestModulePatterns = listOf(SPRING_BOOT_TEST_BASIC_MODULE_PATTERN) diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/process/EngineProcessMain.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/process/EngineProcessMain.kt index 6cde1f9cb8..3b2f98e51c 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/process/EngineProcessMain.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/process/EngineProcessMain.kt @@ -28,18 +28,14 @@ import org.utbot.framework.plugin.api.util.method import org.utbot.framework.plugin.api.utils.ClassNameUtils 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.framework.process.kryo.KryoHelper import org.utbot.instrumentation.instrumentation.instrumenter.Instrumenter import org.utbot.rd.IdleWatchdog import org.utbot.rd.ClientProtocolBuilder import org.utbot.rd.RdSettingsContainerFactory import org.utbot.rd.generated.settingsModel -import org.utbot.rd.terminateOnException import org.utbot.sarif.RdSourceFindingStrategyFacade import org.utbot.sarif.SarifReport -import org.utbot.spring.process.SpringAnalyzerProcess import org.utbot.summary.summarizeAll import org.utbot.taint.TaintConfigurationProviderUserRules import java.io.File @@ -90,27 +86,6 @@ private fun EngineProcessModel.setup(kryoHelper: KryoHelper, watchdog: IdleWatch ) UtContext.setUtContext(UtContext(classLoader)) } - watchdog.measureTimeForActiveCall(getSpringBeanDefinitions, "Getting Spring bean definitions") { params -> - try { - val springAnalyzerProcess = SpringAnalyzerProcess.createBlocking(params.classpath.toList()) - val result = springAnalyzerProcess.terminateOnException { _ -> - springAnalyzerProcess.getBeanDefinitions( - kryoHelper.readObject(params.springSettings) - ) - } - springAnalyzerProcess.terminate() - val beanDefinitions = result.beanDefinitions - .map { data -> - val additionalData = data.additionalData?.let { BeanAdditionalData(it.factoryMethodName, it.parameterTypes, it.configClassFqn) } - BeanDefinitionData(data.beanName, data.beanTypeFqn, additionalData) - } - .toTypedArray() - SpringAnalyzerResult(beanDefinitions) - } catch (e: Exception) { - logger.error(e) { "Spring Analyzer crashed, resorting to using empty bean list" } - SpringAnalyzerResult(emptyArray()) - } - } watchdog.measureTimeForActiveCall(createTestGenerator, "Creating Test Generator") { params -> AnalyticsConfigureUtil.configureML() Instrumenter.adapter = RdInstrumenter(realProtocol.rdInstrumenterAdapter) @@ -273,6 +248,11 @@ private fun EngineProcessModel.setup(kryoHelper: KryoHelper, watchdog: IdleWatch } GenerateTestReportResult(notifyMessage, statistics, hasWarnings) } + watchdog.measureTimeForActiveCall(perform, "Performing dynamic task") { params -> + val task = kryoHelper.readObject>(params.engineProcessTask) + val result = task.perform(kryoHelper) + kryoHelper.writeObject(result) + } } private fun processInitialWarnings(report: TestsGenerationReport, params: GenerateTestReportArgs) { diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/process/EngineProcessTask.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/process/EngineProcessTask.kt new file mode 100644 index 0000000000..7a2b0d6618 --- /dev/null +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/process/EngineProcessTask.kt @@ -0,0 +1,16 @@ +package org.utbot.framework.process + +import org.utbot.framework.process.kryo.KryoHelper + +/** + * Implementations of this interface can be passed to engine process for execution and should + * be used for adding feature-specific (e.g. Spring-specific) tasks without inflating core UtBot codebase. + * + * Such tasks are serialised with kryo when passed between processes, meaning that for successful execution same + * implementation of [EngineProcessTask] should be present on the classpath of both parent process and engine process. + * + * @param R result type of the task (should be present on the classpath of both processes). + */ +interface EngineProcessTask { + fun perform(kryoHelper: KryoHelper): R +} \ No newline at end of file diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/process/generated/EngineProcessModel.Generated.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/process/generated/EngineProcessModel.Generated.kt index fda6c3852e..c399ead4df 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/process/generated/EngineProcessModel.Generated.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/process/generated/EngineProcessModel.Generated.kt @@ -20,7 +20,6 @@ import kotlin.jvm.JvmStatic */ class EngineProcessModel private constructor( private val _setupUtContext: RdCall, - private val _getSpringBeanDefinitions: RdCall, private val _createTestGenerator: RdCall, private val _isCancelled: RdCall, private val _findTestClassName: RdCall, @@ -30,7 +29,8 @@ class EngineProcessModel private constructor( private val _findMethodsInClassMatchingSelected: RdCall, private val _findMethodParamNames: RdCall, private val _writeSarifReport: RdCall, - private val _generateTestReport: RdCall + private val _generateTestReport: RdCall, + private val _perform: RdCall ) : RdExtBase() { //companion @@ -46,7 +46,6 @@ class EngineProcessModel private constructor( serializers.register(RenderParams) serializers.register(RenderResult) serializers.register(SetupContextParams) - serializers.register(GetSpringBeanDefinitions) serializers.register(MethodDescription) serializers.register(FindMethodsInClassMatchingSelectedArguments) serializers.register(FindMethodsInClassMatchingSelectedResult) @@ -55,9 +54,7 @@ class EngineProcessModel private constructor( serializers.register(WriteSarifReportArguments) serializers.register(GenerateTestReportArgs) serializers.register(GenerateTestReportResult) - serializers.register(BeanAdditionalData) - serializers.register(BeanDefinitionData) - serializers.register(SpringAnalyzerResult) + serializers.register(PerformParams) } @@ -78,7 +75,7 @@ class EngineProcessModel private constructor( } - const val serializationHash = -271702162812013897L + const val serializationHash = 7072495177628793247L } override val serializersOwner: ISerializersOwner get() = EngineProcessModel @@ -86,7 +83,6 @@ class EngineProcessModel private constructor( //fields val setupUtContext: RdCall get() = _setupUtContext - val getSpringBeanDefinitions: RdCall get() = _getSpringBeanDefinitions val createTestGenerator: RdCall get() = _createTestGenerator val isCancelled: RdCall get() = _isCancelled val findTestClassName: RdCall get() = _findTestClassName @@ -97,11 +93,11 @@ class EngineProcessModel private constructor( val findMethodParamNames: RdCall get() = _findMethodParamNames val writeSarifReport: RdCall get() = _writeSarifReport val generateTestReport: RdCall get() = _generateTestReport + val perform: RdCall get() = _perform //methods //initializer init { _setupUtContext.async = true - _getSpringBeanDefinitions.async = true _createTestGenerator.async = true _isCancelled.async = true _findTestClassName.async = true @@ -112,11 +108,11 @@ class EngineProcessModel private constructor( _findMethodParamNames.async = true _writeSarifReport.async = true _generateTestReport.async = true + _perform.async = true } init { bindableChildren.add("setupUtContext" to _setupUtContext) - bindableChildren.add("getSpringBeanDefinitions" to _getSpringBeanDefinitions) bindableChildren.add("createTestGenerator" to _createTestGenerator) bindableChildren.add("isCancelled" to _isCancelled) bindableChildren.add("findTestClassName" to _findTestClassName) @@ -127,13 +123,13 @@ class EngineProcessModel private constructor( bindableChildren.add("findMethodParamNames" to _findMethodParamNames) bindableChildren.add("writeSarifReport" to _writeSarifReport) bindableChildren.add("generateTestReport" to _generateTestReport) + bindableChildren.add("perform" to _perform) } //secondary constructor private constructor( ) : this( RdCall(SetupContextParams, FrameworkMarshallers.Void), - RdCall(GetSpringBeanDefinitions, SpringAnalyzerResult), RdCall(TestGeneratorParams, FrameworkMarshallers.Void), RdCall(FrameworkMarshallers.Void, FrameworkMarshallers.Bool), RdCall(TestClassNameParams, TestClassNameResult), @@ -143,7 +139,8 @@ class EngineProcessModel private constructor( RdCall(FindMethodsInClassMatchingSelectedArguments, FindMethodsInClassMatchingSelectedResult), RdCall(FindMethodParamNamesArguments, FindMethodParamNamesResult), RdCall(WriteSarifReportArguments, FrameworkMarshallers.String), - RdCall(GenerateTestReportArgs, GenerateTestReportResult) + RdCall(GenerateTestReportArgs, GenerateTestReportResult), + RdCall(PerformParams, FrameworkMarshallers.ByteArray) ) //equals trait @@ -153,7 +150,6 @@ class EngineProcessModel private constructor( printer.println("EngineProcessModel (") printer.indent { print("setupUtContext = "); _setupUtContext.print(printer); println() - print("getSpringBeanDefinitions = "); _getSpringBeanDefinitions.print(printer); println() print("createTestGenerator = "); _createTestGenerator.print(printer); println() print("isCancelled = "); _isCancelled.print(printer); println() print("findTestClassName = "); _findTestClassName.print(printer); println() @@ -164,6 +160,7 @@ class EngineProcessModel private constructor( print("findMethodParamNames = "); _findMethodParamNames.print(printer); println() print("writeSarifReport = "); _writeSarifReport.print(printer); println() print("generateTestReport = "); _generateTestReport.print(printer); println() + print("perform = "); _perform.print(printer); println() } printer.print(")") } @@ -171,7 +168,6 @@ class EngineProcessModel private constructor( override fun deepClone(): EngineProcessModel { return EngineProcessModel( _setupUtContext.deepClonePolymorphic(), - _getSpringBeanDefinitions.deepClonePolymorphic(), _createTestGenerator.deepClonePolymorphic(), _isCancelled.deepClonePolymorphic(), _findTestClassName.deepClonePolymorphic(), @@ -181,7 +177,8 @@ class EngineProcessModel private constructor( _findMethodsInClassMatchingSelected.deepClonePolymorphic(), _findMethodParamNames.deepClonePolymorphic(), _writeSarifReport.deepClonePolymorphic(), - _generateTestReport.deepClonePolymorphic() + _generateTestReport.deepClonePolymorphic(), + _perform.deepClonePolymorphic() ) } //contexts @@ -191,145 +188,7 @@ val IProtocol.engineProcessModel get() = getOrCreateExtension(EngineProcessModel /** - * #### Generated from [EngineProcessModel.kt:136] - */ -data class BeanAdditionalData ( - val factoryMethodName: String, - val parameterTypes: List, - val configClassName: String -) : IPrintable { - //companion - - companion object : IMarshaller { - override val _type: KClass = BeanAdditionalData::class - - @Suppress("UNCHECKED_CAST") - override fun read(ctx: SerializationCtx, buffer: AbstractBuffer): BeanAdditionalData { - val factoryMethodName = buffer.readString() - val parameterTypes = buffer.readList { buffer.readString() } - val configClassName = buffer.readString() - return BeanAdditionalData(factoryMethodName, parameterTypes, configClassName) - } - - override fun write(ctx: SerializationCtx, buffer: AbstractBuffer, value: BeanAdditionalData) { - buffer.writeString(value.factoryMethodName) - buffer.writeList(value.parameterTypes) { v -> buffer.writeString(v) } - buffer.writeString(value.configClassName) - } - - - } - //fields - //methods - //initializer - //secondary constructor - //equals trait - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other == null || other::class != this::class) return false - - other as BeanAdditionalData - - if (factoryMethodName != other.factoryMethodName) return false - if (parameterTypes != other.parameterTypes) return false - if (configClassName != other.configClassName) return false - - return true - } - //hash code trait - override fun hashCode(): Int { - var __r = 0 - __r = __r*31 + factoryMethodName.hashCode() - __r = __r*31 + parameterTypes.hashCode() - __r = __r*31 + configClassName.hashCode() - return __r - } - //pretty print - override fun print(printer: PrettyPrinter) { - printer.println("BeanAdditionalData (") - printer.indent { - print("factoryMethodName = "); factoryMethodName.print(printer); println() - print("parameterTypes = "); parameterTypes.print(printer); println() - print("configClassName = "); configClassName.print(printer); println() - } - printer.print(")") - } - //deepClone - //contexts -} - - -/** - * #### Generated from [EngineProcessModel.kt:141] - */ -data class BeanDefinitionData ( - val beanName: String, - val beanTypeFqn: String, - val additionalData: BeanAdditionalData? -) : IPrintable { - //companion - - companion object : IMarshaller { - override val _type: KClass = BeanDefinitionData::class - - @Suppress("UNCHECKED_CAST") - override fun read(ctx: SerializationCtx, buffer: AbstractBuffer): BeanDefinitionData { - val beanName = buffer.readString() - val beanTypeFqn = buffer.readString() - val additionalData = buffer.readNullable { BeanAdditionalData.read(ctx, buffer) } - return BeanDefinitionData(beanName, beanTypeFqn, additionalData) - } - - override fun write(ctx: SerializationCtx, buffer: AbstractBuffer, value: BeanDefinitionData) { - buffer.writeString(value.beanName) - buffer.writeString(value.beanTypeFqn) - buffer.writeNullable(value.additionalData) { BeanAdditionalData.write(ctx, buffer, it) } - } - - - } - //fields - //methods - //initializer - //secondary constructor - //equals trait - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other == null || other::class != this::class) return false - - other as BeanDefinitionData - - if (beanName != other.beanName) return false - if (beanTypeFqn != other.beanTypeFqn) return false - if (additionalData != other.additionalData) return false - - return true - } - //hash code trait - override fun hashCode(): Int { - var __r = 0 - __r = __r*31 + beanName.hashCode() - __r = __r*31 + beanTypeFqn.hashCode() - __r = __r*31 + if (additionalData != null) additionalData.hashCode() else 0 - return __r - } - //pretty print - override fun print(printer: PrettyPrinter) { - printer.println("BeanDefinitionData (") - printer.indent { - print("beanName = "); beanName.print(printer); println() - print("beanTypeFqn = "); beanTypeFqn.print(printer); println() - print("additionalData = "); additionalData.print(printer); println() - } - printer.print(")") - } - //deepClone - //contexts -} - - -/** - * #### Generated from [EngineProcessModel.kt:110] + * #### Generated from [EngineProcessModel.kt:106] */ data class FindMethodParamNamesArguments ( val classId: ByteArray, @@ -392,7 +251,7 @@ data class FindMethodParamNamesArguments ( /** - * #### Generated from [EngineProcessModel.kt:114] + * #### Generated from [EngineProcessModel.kt:110] */ data class FindMethodParamNamesResult ( val paramNames: ByteArray @@ -449,7 +308,7 @@ data class FindMethodParamNamesResult ( /** - * #### Generated from [EngineProcessModel.kt:103] + * #### Generated from [EngineProcessModel.kt:99] */ data class FindMethodsInClassMatchingSelectedArguments ( val classId: ByteArray, @@ -512,7 +371,7 @@ data class FindMethodsInClassMatchingSelectedArguments ( /** - * #### Generated from [EngineProcessModel.kt:107] + * #### Generated from [EngineProcessModel.kt:103] */ data class FindMethodsInClassMatchingSelectedResult ( val executableIds: ByteArray @@ -743,7 +602,7 @@ data class GenerateResult ( /** - * #### Generated from [EngineProcessModel.kt:122] + * #### Generated from [EngineProcessModel.kt:118] */ data class GenerateTestReportArgs ( val eventLogMessage: String?, @@ -836,7 +695,7 @@ data class GenerateTestReportArgs ( /** - * #### Generated from [EngineProcessModel.kt:131] + * #### Generated from [EngineProcessModel.kt:127] */ data class GenerateTestReportResult ( val notifyMessage: String, @@ -904,69 +763,6 @@ data class GenerateTestReportResult ( } -/** - * #### Generated from [EngineProcessModel.kt:94] - */ -data class GetSpringBeanDefinitions ( - val classpath: Array, - val springSettings: ByteArray -) : IPrintable { - //companion - - companion object : IMarshaller { - override val _type: KClass = GetSpringBeanDefinitions::class - - @Suppress("UNCHECKED_CAST") - override fun read(ctx: SerializationCtx, buffer: AbstractBuffer): GetSpringBeanDefinitions { - val classpath = buffer.readArray {buffer.readString()} - val springSettings = buffer.readByteArray() - return GetSpringBeanDefinitions(classpath, springSettings) - } - - override fun write(ctx: SerializationCtx, buffer: AbstractBuffer, value: GetSpringBeanDefinitions) { - buffer.writeArray(value.classpath) { buffer.writeString(it) } - buffer.writeByteArray(value.springSettings) - } - - - } - //fields - //methods - //initializer - //secondary constructor - //equals trait - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other == null || other::class != this::class) return false - - other as GetSpringBeanDefinitions - - if (!(classpath contentDeepEquals other.classpath)) return false - if (!(springSettings contentEquals other.springSettings)) return false - - return true - } - //hash code trait - override fun hashCode(): Int { - var __r = 0 - __r = __r*31 + classpath.contentDeepHashCode() - __r = __r*31 + springSettings.contentHashCode() - return __r - } - //pretty print - override fun print(printer: PrettyPrinter) { - printer.println("GetSpringBeanDefinitions (") - printer.indent { - print("classpath = "); classpath.print(printer); println() - print("springSettings = "); springSettings.print(printer); println() - } - printer.print(")") - } - //deepClone - //contexts -} - - /** * #### Generated from [EngineProcessModel.kt:32] */ @@ -1031,7 +827,7 @@ data class JdkInfo ( /** - * #### Generated from [EngineProcessModel.kt:98] + * #### Generated from [EngineProcessModel.kt:94] */ data class MethodDescription ( val name: String, @@ -1099,6 +895,63 @@ data class MethodDescription ( } +/** + * #### Generated from [EngineProcessModel.kt:132] + */ +data class PerformParams ( + val engineProcessTask: ByteArray +) : IPrintable { + //companion + + companion object : IMarshaller { + override val _type: KClass = PerformParams::class + + @Suppress("UNCHECKED_CAST") + override fun read(ctx: SerializationCtx, buffer: AbstractBuffer): PerformParams { + val engineProcessTask = buffer.readByteArray() + return PerformParams(engineProcessTask) + } + + override fun write(ctx: SerializationCtx, buffer: AbstractBuffer, value: PerformParams) { + buffer.writeByteArray(value.engineProcessTask) + } + + + } + //fields + //methods + //initializer + //secondary constructor + //equals trait + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other == null || other::class != this::class) return false + + other as PerformParams + + if (!(engineProcessTask contentEquals other.engineProcessTask)) return false + + return true + } + //hash code trait + override fun hashCode(): Int { + var __r = 0 + __r = __r*31 + engineProcessTask.contentHashCode() + return __r + } + //pretty print + override fun print(printer: PrettyPrinter) { + printer.println("PerformParams (") + printer.indent { + print("engineProcessTask = "); engineProcessTask.print(printer); println() + } + printer.print(")") + } + //deepClone + //contexts +} + + /** * #### Generated from [EngineProcessModel.kt:69] */ @@ -1366,63 +1219,6 @@ data class SetupContextParams ( } -/** - * #### Generated from [EngineProcessModel.kt:146] - */ -data class SpringAnalyzerResult ( - val beanDefinitions: Array -) : IPrintable { - //companion - - companion object : IMarshaller { - override val _type: KClass = SpringAnalyzerResult::class - - @Suppress("UNCHECKED_CAST") - override fun read(ctx: SerializationCtx, buffer: AbstractBuffer): SpringAnalyzerResult { - val beanDefinitions = buffer.readArray {BeanDefinitionData.read(ctx, buffer)} - return SpringAnalyzerResult(beanDefinitions) - } - - override fun write(ctx: SerializationCtx, buffer: AbstractBuffer, value: SpringAnalyzerResult) { - buffer.writeArray(value.beanDefinitions) { BeanDefinitionData.write(ctx, buffer, it) } - } - - - } - //fields - //methods - //initializer - //secondary constructor - //equals trait - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other == null || other::class != this::class) return false - - other as SpringAnalyzerResult - - if (!(beanDefinitions contentDeepEquals other.beanDefinitions)) return false - - return true - } - //hash code trait - override fun hashCode(): Int { - var __r = 0 - __r = __r*31 + beanDefinitions.contentDeepHashCode() - return __r - } - //pretty print - override fun print(printer: PrettyPrinter) { - printer.println("SpringAnalyzerResult (") - printer.indent { - print("beanDefinitions = "); beanDefinitions.print(printer); println() - } - printer.print(")") - } - //deepClone - //contexts -} - - /** * #### Generated from [EngineProcessModel.kt:43] */ @@ -1619,7 +1415,7 @@ data class TestGeneratorParams ( /** - * #### Generated from [EngineProcessModel.kt:117] + * #### Generated from [EngineProcessModel.kt:113] */ data class WriteSarifReportArguments ( val testSetsId: Long, diff --git a/utbot-intellij/build.gradle.kts b/utbot-intellij/build.gradle.kts index bd0a5f8f9b..afd5662b64 100644 --- a/utbot-intellij/build.gradle.kts +++ b/utbot-intellij/build.gradle.kts @@ -157,6 +157,7 @@ dependencies { implementation(group = "com.fasterxml.jackson.module", name = "jackson-module-kotlin", version = jacksonVersion) implementation(project(":utbot-framework")) { exclude(group = "org.slf4j", module = "slf4j-api") } + implementation(project(":utbot-spring-framework")) { exclude(group = "org.slf4j", module = "slf4j-api") } implementation(project(":utbot-java-fuzzing")) //api(project(":utbot-analytics")) testImplementation("org.mock-server:mockserver-netty:5.4.1") diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/UtTestsDialogProcessor.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/UtTestsDialogProcessor.kt index 2a0a208cb4..4b8ff4c0e8 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/UtTestsDialogProcessor.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/generator/UtTestsDialogProcessor.kt @@ -59,6 +59,7 @@ 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.SpringAnalyzerTask import org.utbot.instrumentation.instrumentation.spring.SpringUtExecutionInstrumentation import org.utbot.intellij.plugin.generator.CodeGenerationController.generateTests import org.utbot.intellij.plugin.models.GenerateTestsModel @@ -279,9 +280,11 @@ object UtTestsDialogProcessor { when (val settings = model.springSettings) { is AbsentSpringSettings -> emptyList() is PresentSpringSettings -> { - process.getSpringBeanDefinitions( - classpathForClassLoader, - settings + process.perform( + SpringAnalyzerTask( + classpath = classpathForClassLoader, + settings = settings + ) ) } } diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/process/EngineProcess.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/process/EngineProcess.kt index 3a49cf4a71..7d180f6363 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/process/EngineProcess.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/process/EngineProcess.kt @@ -13,17 +13,15 @@ import com.jetbrains.rd.util.ConcurrentHashMap import com.jetbrains.rd.util.lifetime.LifetimeDefinition import kotlinx.coroutines.runBlocking import mu.KotlinLogging -import org.utbot.framework.plugin.api.SpringSettings.* import org.utbot.common.* import org.utbot.framework.UtSettings import org.utbot.framework.codegen.tree.ututils.UtilClassKind import org.utbot.framework.context.ApplicationContext import org.utbot.framework.plugin.api.* -import org.utbot.framework.plugin.api.BeanAdditionalData -import org.utbot.framework.plugin.api.BeanDefinitionData import org.utbot.framework.plugin.services.JdkInfo import org.utbot.framework.plugin.services.WorkingDirService import org.utbot.framework.process.AbstractRDProcessCompanion +import org.utbot.framework.process.EngineProcessTask import org.utbot.framework.process.generated.* import org.utbot.framework.process.generated.MethodDescription import org.utbot.framework.process.kryo.KryoHelper @@ -144,34 +142,6 @@ class EngineProcess private constructor(val project: Project, private val classN engineModel.setupUtContext.startBlocking(SetupContextParams(classpathForUrlsClassloader)) } - fun getSpringBeanDefinitions( - classpathList: List, - springSettings: PresentSpringSettings - ): List { - assertReadAccessNotAllowed() - val result = engineModel.getSpringBeanDefinitions.startBlocking( - GetSpringBeanDefinitions( - classpathList.toTypedArray(), - kryoHelper.writeObject(springSettings) - ) - ) - return result.beanDefinitions - .map { data -> - BeanDefinitionData( - beanName = data.beanName, - beanTypeName = data.beanTypeFqn, - additionalData = data.additionalData - ?.let { - BeanAdditionalData( - it.factoryMethodName, - it.parameterTypes, - it.configClassName - ) - } - ) - } - } - private fun computeSourceFileByClass(params: ComputeSourceFileByClassArguments): String? = DumbService.getInstance(project).runReadActionInSmartMode { val scope = GlobalSearchScope.allScope(project) @@ -416,6 +386,13 @@ class EngineProcess private constructor(val project: Project, private val classN return Triple(result.notifyMessage, result.statistics, result.hasWarnings) } + fun perform(engineProcessTask: EngineProcessTask): R { + assertReadAccessNotAllowed() + return kryoHelper.readObject( + engineModel.perform.startBlocking(PerformParams(kryoHelper.writeObject(engineProcessTask))) + ) + } + init { lifetime.onTermination { protocol.synchronizationModel.stopProcess.fire(Unit) diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/GenerateTestsDialogWindow.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/GenerateTestsDialogWindow.kt index 0af1bc1217..80c87ebe55 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/GenerateTestsDialogWindow.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/GenerateTestsDialogWindow.kt @@ -78,7 +78,7 @@ import org.jetbrains.concurrency.Promise import org.jetbrains.concurrency.thenRun import org.utbot.common.PathUtil.toPath import org.utbot.framework.UtSettings -import org.utbot.framework.codegen.domain.DependencyInjectionFramework +import org.utbot.framework.codegen.domain.SpringModule import org.utbot.framework.codegen.domain.ForceStaticMocking import org.utbot.framework.codegen.domain.Junit4 import org.utbot.framework.codegen.domain.Junit5 @@ -86,8 +86,8 @@ import org.utbot.framework.codegen.domain.MockitoStaticMocking import org.utbot.framework.codegen.domain.NoStaticMocking import org.utbot.framework.codegen.domain.ParametrizedTestSource import org.utbot.framework.codegen.domain.ProjectType -import org.utbot.framework.codegen.domain.SpringBeans -import org.utbot.framework.codegen.domain.SpringBoot +import org.utbot.framework.codegen.domain.SpringModule.SPRING_BEANS +import org.utbot.framework.codegen.domain.SpringModule.SPRING_BOOT import org.utbot.framework.codegen.domain.StaticsMocking import org.utbot.framework.codegen.domain.TestFramework import org.utbot.framework.codegen.domain.TestNg @@ -361,10 +361,10 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m } - DependencyInjectionFramework.allItems.forEach { + SpringModule.values().forEach { it.isInstalled = findDependencyInjectionLibrary(model.srcModule, it) != null } - DependencyInjectionFramework.installedItems.forEach { + SpringModule.installedItems.forEach { it.testFrameworkInstalled = findDependencyInjectionTestLibrary(model.testModule, it) != null } @@ -372,7 +372,7 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m model.projectType = // TODO show some warning, when we see Spring project, but don't have `utBotSpringRuntime` - if (isUtBotSpringRuntimePresent && DependencyInjectionFramework.installedItems.isNotEmpty()) ProjectType.Spring + if (isUtBotSpringRuntimePresent && SpringModule.installedItems.isNotEmpty()) ProjectType.Spring else ProjectType.PureJvm // Configure notification urls callbacks @@ -963,8 +963,7 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m private fun configureSpringTestFrameworkIfRequired() { if (springConfig.item != NO_SPRING_CONFIGURATION_OPTION) { - DependencyInjectionFramework.installedItems - .filter { it.isInstalled } + SpringModule.installedItems .forEach { configureSpringTestDependency(it) } } } @@ -992,11 +991,11 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m .onError { selectedTestFramework.isInstalled = false } } - private fun configureSpringTestDependency(framework: DependencyInjectionFramework) { + private fun configureSpringTestDependency(springModule: SpringModule) { val frameworkLibrary = - findDependencyInjectionLibrary(model.srcModule, framework, LibrarySearchScope.Project) + findDependencyInjectionLibrary(model.srcModule, springModule, LibrarySearchScope.Project) val frameworkTestLibrary = - findDependencyInjectionTestLibrary(model.testModule, framework, LibrarySearchScope.Project) + findDependencyInjectionTestLibrary(model.testModule, springModule, LibrarySearchScope.Project) val frameworkVersionInProject = frameworkLibrary?.libraryName?.parseVersion() ?: error("Trying to install Spring test framework, but Spring framework is not found in module ${model.srcModule.name}") @@ -1005,16 +1004,15 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m if (frameworkTestVersionInProject == null || !frameworkTestVersionInProject.isCompatibleWith(frameworkVersionInProject) ) { - val libraryDescriptor = when (framework) { - SpringBoot -> springBootTestLibraryDescriptor(frameworkVersionInProject) - SpringBeans -> springTestLibraryDescriptor(frameworkVersionInProject) - else -> error("Unsupported DI framework type $framework") + val libraryDescriptor = when (springModule) { + SPRING_BOOT -> springBootTestLibraryDescriptor(frameworkVersionInProject) + SPRING_BEANS -> springTestLibraryDescriptor(frameworkVersionInProject) } model.preClasspathCollectionPromises += addDependency(model.testModule, libraryDescriptor) } - framework.testFrameworkInstalled = true + springModule.testFrameworkInstalled = true } private fun configureMockFramework() { @@ -1308,7 +1306,7 @@ class GenerateTestsDialogWindow(val model: GenerateTestsModel) : DialogWrapper(m ) { this.append(value.displayName, SimpleTextAttributes.REGULAR_ATTRIBUTES) if (springConfig.item != NO_SPRING_CONFIGURATION_OPTION) { - DependencyInjectionFramework.installedItems + SpringModule.installedItems // only first missing test framework is shown to avoid overflowing ComboBox .firstOrNull { !it.testFrameworkInstalled } ?.let { diFramework -> diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/utils/LibraryMatcher.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/utils/LibraryMatcher.kt index 542cb30dd4..8666a3c4d8 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/utils/LibraryMatcher.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/ui/utils/LibraryMatcher.kt @@ -4,7 +4,7 @@ import org.utbot.framework.codegen.domain.TestFramework import org.utbot.framework.plugin.api.MockFramework import com.intellij.openapi.module.Module import com.intellij.openapi.roots.LibraryOrderEntry -import org.utbot.framework.codegen.domain.DependencyInjectionFramework +import org.utbot.framework.codegen.domain.SpringModule import org.utbot.framework.plugin.api.utils.Patterns import org.utbot.framework.plugin.api.utils.parametrizedTestsPatterns import org.utbot.framework.plugin.api.utils.patterns @@ -30,15 +30,15 @@ fun findParametrizedTestsLibrary( fun findDependencyInjectionLibrary( module: Module, - springFrameworkType: DependencyInjectionFramework, + springModule: SpringModule, scope: LibrarySearchScope = LibrarySearchScope.Module -): LibraryOrderEntry? = findMatchingLibraryOrNull(module, springFrameworkType.patterns(), scope) +): LibraryOrderEntry? = findMatchingLibraryOrNull(module, springModule.patterns(), scope) fun findDependencyInjectionTestLibrary( module: Module, - springFrameworkType: DependencyInjectionFramework, + springModule: SpringModule, scope: LibrarySearchScope = LibrarySearchScope.Module -): LibraryOrderEntry? = findMatchingLibraryOrNull(module, springFrameworkType.testPatterns(), scope) +): LibraryOrderEntry? = findMatchingLibraryOrNull(module, springModule.testPatterns(), scope) private fun findMatchingLibraryOrNull( module: Module, diff --git a/utbot-rd/src/main/rdgen/org/utbot/rd/models/EngineProcessModel.kt b/utbot-rd/src/main/rdgen/org/utbot/rd/models/EngineProcessModel.kt index 62894729a7..bc8ffcabfb 100644 --- a/utbot-rd/src/main/rdgen/org/utbot/rd/models/EngineProcessModel.kt +++ b/utbot-rd/src/main/rdgen/org/utbot/rd/models/EngineProcessModel.kt @@ -91,10 +91,6 @@ object EngineProcessModel : Ext(EngineProcessRoot) { val setupContextParams = structdef { field("classpathForUrlsClassloader", immutableList(PredefinedType.string)) } - val getSpringBeanDefinitions = structdef { - field("classpath", array(PredefinedType.string)) - field("springSettings", array(PredefinedType.byte)) - } val methodDescription = structdef { field("name", PredefinedType.string) field("containingClass", PredefinedType.string.nullable) @@ -133,23 +129,12 @@ object EngineProcessModel : Ext(EngineProcessRoot) { field("statistics", PredefinedType.string.nullable) field("hasWarnings", PredefinedType.bool) } - val beanAdditionalData = structdef { - field("factoryMethodName", PredefinedType.string) - field("parameterTypes", immutableList(PredefinedType.string)) - field("configClassName", PredefinedType.string) - } - val beanDefinitionData = structdef { - field("beanName", PredefinedType.string) - field("beanTypeFqn", PredefinedType.string) - field("additionalData", beanAdditionalData.nullable) - } - val springAnalyzerResult = structdef { - field("beanDefinitions", array(beanDefinitionData)) + val performParams = structdef { + field("engineProcessTask", array(PredefinedType.byte)) } init { call("setupUtContext", setupContextParams, PredefinedType.void).async - call("getSpringBeanDefinitions", getSpringBeanDefinitions, springAnalyzerResult).async call("createTestGenerator", testGeneratorParams, PredefinedType.void).async call("isCancelled", PredefinedType.void, PredefinedType.bool).async call("findTestClassName", testClassNameParams, testClassNameResult).async @@ -160,5 +145,6 @@ object EngineProcessModel : Ext(EngineProcessRoot) { call("findMethodParamNames", findMethodParamNamesArguments, findMethodParamNamesResult).async call("writeSarifReport", writeSarifReportArguments, PredefinedType.string).async call("generateTestReport", generateTestReportArgs, generateTestReportResult).async + call("perform", performParams, array(PredefinedType.byte)).async } } \ No newline at end of file diff --git a/utbot-spring-framework/build.gradle.kts b/utbot-spring-framework/build.gradle.kts new file mode 100644 index 0000000000..0852abd8aa --- /dev/null +++ b/utbot-spring-framework/build.gradle.kts @@ -0,0 +1,39 @@ +val kotlinLoggingVersion: String by rootProject +val rdVersion: String by rootProject +val sootVersion: String by rootProject + +val fetchSpringCommonsJar: Configuration by configurations.creating { + isCanBeResolved = true + isCanBeConsumed = false +} + +val fetchSpringAnalyzerJar: Configuration by configurations.creating { + isCanBeResolved = true + isCanBeConsumed = false +} + +dependencies { + implementation(project(":utbot-framework")) + implementation(project(":utbot-spring-commons-api")) + implementation(project(":utbot-spring-analyzer")) + + implementation(group = "io.github.microutils", name = "kotlin-logging", version = kotlinLoggingVersion) + implementation(group = "com.jetbrains.rd", name = "rd-core", version = rdVersion) + + implementation("org.unittestbot.soot:soot-utbot-fork:${sootVersion}") { + exclude(group = "com.google.guava", module = "guava") + } + + fetchSpringCommonsJar(project(":utbot-spring-commons", configuration = "springCommonsJar")) + fetchSpringAnalyzerJar(project(":utbot-spring-analyzer", configuration = "springAnalyzerJar")) +} + +tasks.processResources { + from(fetchSpringCommonsJar) { + into("lib") + } + + from(fetchSpringAnalyzerJar) { + into("lib") + } +} \ No newline at end of file diff --git a/utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/domain/SpringModule.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/domain/SpringModule.kt new file mode 100644 index 0000000000..aedace2ef1 --- /dev/null +++ b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/domain/SpringModule.kt @@ -0,0 +1,24 @@ +package org.utbot.framework.codegen.domain + +enum class SpringModule( + val testFrameworkDisplayName: String, +) { + SPRING_BEANS( + testFrameworkDisplayName = "spring-test", + ), + SPRING_BOOT( + testFrameworkDisplayName = "spring-boot-test", + ); + + var isInstalled = false + /** + * Generation Spring specific tests requires special spring test framework being installed, + * so we can use `TestContextManager` from `spring-test` to configure test context in + * spring-analyzer and to run integration tests. + */ + var testFrameworkInstalled: Boolean = false + + companion object { + val installedItems get() = values().filter { it.isInstalled } + } +} diff --git a/utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/domain/builtin/MockitoAnnotationBuiltins.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/domain/builtin/MockitoAnnotationBuiltins.kt new file mode 100644 index 0000000000..0f6bac180e --- /dev/null +++ b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/domain/builtin/MockitoAnnotationBuiltins.kt @@ -0,0 +1,18 @@ +package org.utbot.framework.codegen.domain.builtin + +import org.utbot.framework.plugin.api.BuiltinClassId + +internal val mockClassId = BuiltinClassId( + canonicalName = "org.mockito.Mock", + simpleName = "Mock", +) + +internal val spyClassId = BuiltinClassId( + canonicalName = "org.mockito.Spy", + simpleName = "Spy" +) + +internal val injectMocksClassId = BuiltinClassId( + canonicalName = "org.mockito.InjectMocks", + simpleName = "InjectMocks", +) \ No newline at end of file diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/generator/SpringCodeGenerator.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/generator/SpringCodeGenerator.kt similarity index 100% rename from utbot-framework/src/main/kotlin/org/utbot/framework/codegen/generator/SpringCodeGenerator.kt rename to utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/generator/SpringCodeGenerator.kt diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/services/framework/SpyFrameworkManager.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/services/framework/SpyFrameworkManager.kt similarity index 100% rename from utbot-framework/src/main/kotlin/org/utbot/framework/codegen/services/framework/SpyFrameworkManager.kt rename to utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/services/framework/SpyFrameworkManager.kt diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgAbstractSpringTestClassConstructor.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgAbstractSpringTestClassConstructor.kt similarity index 100% rename from utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgAbstractSpringTestClassConstructor.kt rename to utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgAbstractSpringTestClassConstructor.kt diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgMockMvcResultActionsAssertConstructor.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgMockMvcResultActionsAssertConstructor.kt similarity index 100% rename from utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgMockMvcResultActionsAssertConstructor.kt rename to utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgMockMvcResultActionsAssertConstructor.kt diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringIntegrationTestClassConstructor.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringIntegrationTestClassConstructor.kt similarity index 100% rename from utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringIntegrationTestClassConstructor.kt rename to utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringIntegrationTestClassConstructor.kt diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringUnitTestClassConstructor.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringUnitTestClassConstructor.kt similarity index 100% rename from utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringUnitTestClassConstructor.kt rename to utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringUnitTestClassConstructor.kt diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringVariableConstructor.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringVariableConstructor.kt similarity index 100% rename from utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringVariableConstructor.kt rename to utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringVariableConstructor.kt diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgAbstractClassFieldManager.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgAbstractClassFieldManager.kt similarity index 100% rename from utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgAbstractClassFieldManager.kt rename to utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgAbstractClassFieldManager.kt diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgAutowiredFieldsManager.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgAutowiredFieldsManager.kt similarity index 100% rename from utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgAutowiredFieldsManager.kt rename to utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgAutowiredFieldsManager.kt diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgClassFieldManager.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgClassFieldManager.kt similarity index 100% rename from utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgClassFieldManager.kt rename to utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgClassFieldManager.kt diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgInjectingMocksFieldsManager.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgInjectingMocksFieldsManager.kt similarity index 95% rename from utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgInjectingMocksFieldsManager.kt rename to utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgInjectingMocksFieldsManager.kt index dc3cdf0159..2e8a14740d 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgInjectingMocksFieldsManager.kt +++ b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgInjectingMocksFieldsManager.kt @@ -1,8 +1,6 @@ package org.utbot.framework.codegen.tree.fieldmanager import org.utbot.framework.codegen.domain.builtin.injectMocksClassId -import org.utbot.framework.codegen.domain.builtin.mockClassId -import org.utbot.framework.codegen.domain.builtin.spyClassId import org.utbot.framework.codegen.domain.context.CgContext import org.utbot.framework.codegen.domain.models.CgFieldDeclaration import org.utbot.framework.codegen.domain.models.CgValue diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgMockedFieldsManager.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgMockedFieldsManager.kt similarity index 100% rename from utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgMockedFieldsManager.kt rename to utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgMockedFieldsManager.kt diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgPersistenceContextFieldsManager.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgPersistenceContextFieldsManager.kt similarity index 100% rename from utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgPersistenceContextFieldsManager.kt rename to utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgPersistenceContextFieldsManager.kt diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgSpiedFieldsManager.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgSpiedFieldsManager.kt similarity index 100% rename from utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgSpiedFieldsManager.kt rename to utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/CgSpiedFieldsManager.kt diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/ClassFieldManagerFacade.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/ClassFieldManagerFacade.kt similarity index 74% rename from utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/ClassFieldManagerFacade.kt rename to utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/ClassFieldManagerFacade.kt index 791bcba608..3b61b4a403 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/ClassFieldManagerFacade.kt +++ b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/ClassFieldManagerFacade.kt @@ -1,12 +1,23 @@ package org.utbot.framework.codegen.tree.fieldmanager +import org.utbot.common.getOrPut import org.utbot.framework.codegen.domain.UtModelWrapper import org.utbot.framework.codegen.domain.context.CgContext import org.utbot.framework.codegen.domain.context.CgContextOwner +import org.utbot.framework.codegen.domain.context.CgContextProperty import org.utbot.framework.codegen.domain.models.CgValue import org.utbot.framework.plugin.api.UtModel import org.utbot.framework.plugin.api.UtSpringContextModel +object RelevantFieldManagersProperty : CgContextProperty> + +/** + * Managers to process annotated fields of the class under test + * relevant for the current generation type. + */ +val CgContextOwner.relevantFieldManagers: MutableList + get() = properties.getOrPut(RelevantFieldManagersProperty) { mutableListOf() } + class ClassFieldManagerFacade(context: CgContext) : CgContextOwner by context { private val alreadyInitializedModels = mutableSetOf() diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/MockitoInjectionUtils.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/MockitoInjectionUtils.kt similarity index 100% rename from utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/MockitoInjectionUtils.kt rename to utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/MockitoInjectionUtils.kt diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/ModelGroupsProvider.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/ModelGroupsProvider.kt similarity index 100% rename from utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/ModelGroupsProvider.kt rename to utbot-spring-framework/src/main/kotlin/org/utbot/framework/codegen/tree/fieldmanager/ModelGroupsProvider.kt diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/context/spring/SpringApplicationContext.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/context/spring/SpringApplicationContext.kt similarity index 100% rename from utbot-framework/src/main/kotlin/org/utbot/framework/context/spring/SpringApplicationContext.kt rename to utbot-spring-framework/src/main/kotlin/org/utbot/framework/context/spring/SpringApplicationContext.kt diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/context/spring/SpringApplicationContextImpl.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/context/spring/SpringApplicationContextImpl.kt similarity index 100% rename from utbot-framework/src/main/kotlin/org/utbot/framework/context/spring/SpringApplicationContextImpl.kt rename to utbot-spring-framework/src/main/kotlin/org/utbot/framework/context/spring/SpringApplicationContextImpl.kt diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/context/spring/SpringIntegrationTestConcreteExecutionContext.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/context/spring/SpringIntegrationTestConcreteExecutionContext.kt similarity index 100% rename from utbot-framework/src/main/kotlin/org/utbot/framework/context/spring/SpringIntegrationTestConcreteExecutionContext.kt rename to utbot-spring-framework/src/main/kotlin/org/utbot/framework/context/spring/SpringIntegrationTestConcreteExecutionContext.kt diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/context/spring/SpringIntegrationTestJavaFuzzingContext.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/context/spring/SpringIntegrationTestJavaFuzzingContext.kt similarity index 100% rename from utbot-framework/src/main/kotlin/org/utbot/framework/context/spring/SpringIntegrationTestJavaFuzzingContext.kt rename to utbot-spring-framework/src/main/kotlin/org/utbot/framework/context/spring/SpringIntegrationTestJavaFuzzingContext.kt diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/context/spring/SpringNonNullSpeculator.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/context/spring/SpringNonNullSpeculator.kt similarity index 100% rename from utbot-framework/src/main/kotlin/org/utbot/framework/context/spring/SpringNonNullSpeculator.kt rename to utbot-spring-framework/src/main/kotlin/org/utbot/framework/context/spring/SpringNonNullSpeculator.kt diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/context/spring/SpringTypeReplacer.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/context/spring/SpringTypeReplacer.kt similarity index 100% rename from utbot-framework/src/main/kotlin/org/utbot/framework/context/spring/SpringTypeReplacer.kt rename to utbot-spring-framework/src/main/kotlin/org/utbot/framework/context/spring/SpringTypeReplacer.kt diff --git a/utbot-spring-framework/src/main/kotlin/org/utbot/framework/plugin/api/utils/SpringDependencyPatterns.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/plugin/api/utils/SpringDependencyPatterns.kt new file mode 100644 index 0000000000..8b83c23c1b --- /dev/null +++ b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/plugin/api/utils/SpringDependencyPatterns.kt @@ -0,0 +1,60 @@ +package org.utbot.framework.plugin.api.utils + +import org.utbot.framework.codegen.domain.SpringModule.SPRING_BEANS +import org.utbot.framework.codegen.domain.SpringModule.SPRING_BOOT +import org.utbot.framework.codegen.domain.SpringModule + +fun SpringModule.patterns(): Patterns { + val moduleLibraryPatterns = when (this) { + SPRING_BOOT -> springBootModulePatterns + SPRING_BEANS -> springBeansModulePatterns + } + val libraryPatterns = when (this) { + SPRING_BOOT -> springBootPatterns + SPRING_BEANS -> springBeansPatterns + } + + return Patterns(moduleLibraryPatterns, libraryPatterns) +} + +fun SpringModule.testPatterns(): Patterns { + val moduleLibraryPatterns = when (this) { + SPRING_BOOT -> springBootTestModulePatterns + SPRING_BEANS -> springBeansTestModulePatterns + } + val libraryPatterns = when (this) { + SPRING_BOOT -> springBootTestPatterns + SPRING_BEANS -> springBeansTestPatterns + } + + return Patterns(moduleLibraryPatterns, libraryPatterns) +} + +val SPRING_BEANS_JAR_PATTERN = Regex("spring-beans-([0-9]+)(\\.[0-9]+){1,2}") +val SPRING_BEANS_MVN_PATTERN = Regex("org\\.springframework:spring-beans:([0-9]+)(\\.[0-9]+){1,2}") +val springBeansPatterns = listOf(SPRING_BEANS_JAR_PATTERN, SPRING_BEANS_MVN_PATTERN) + +val SPRING_BEANS_BASIC_MODULE_PATTERN = Regex("spring-beans") +val springBeansModulePatterns = listOf(SPRING_BEANS_BASIC_MODULE_PATTERN) + +val SPRING_BEANS_TEST_JAR_PATTERN = Regex("spring-test-([0-9]+)(\\.[0-9]+){1,2}") +val SPRING_BEANS_TEST_MVN_PATTERN = Regex("org\\.springframework:spring-test:([0-9]+)(\\.[0-9]+){1,2}") +val springBeansTestPatterns = listOf(SPRING_BEANS_TEST_JAR_PATTERN, SPRING_BEANS_TEST_MVN_PATTERN) + +val SPRING_BEANS_TEST_BASIC_MODULE_PATTERN = Regex("spring-test") +val springBeansTestModulePatterns = listOf(SPRING_BEANS_TEST_BASIC_MODULE_PATTERN) + +val SPRING_BOOT_JAR_PATTERN = Regex("spring-boot-([0-9]+)(\\.[0-9]+){1,2}") +val SPRING_BOOT_MVN_PATTERN = Regex("org\\.springframework\\.boot:spring-boot:([0-9]+)(\\.[0-9]+){1,2}") +val springBootPatterns = listOf(SPRING_BOOT_JAR_PATTERN, SPRING_BOOT_MVN_PATTERN) + +val SPRING_BOOT_BASIC_MODULE_PATTERN = Regex("spring-boot") +val springBootModulePatterns = listOf(SPRING_BOOT_BASIC_MODULE_PATTERN) + +val SPRING_BOOT_TEST_JAR_PATTERN = Regex("spring-boot-test-([0-9]+)(\\.[0-9]+){1,2}") +val SPRING_BOOT_TEST_MVN_PATTERN = Regex("org\\.springframework\\.boot:spring-boot-test:([0-9]+)(\\.[0-9]+){1,2}") + +val springBootTestPatterns = listOf(SPRING_BOOT_TEST_JAR_PATTERN, SPRING_BOOT_TEST_MVN_PATTERN) + +val SPRING_BOOT_TEST_BASIC_MODULE_PATTERN = Regex("spring-boot-test") +val springBootTestModulePatterns = listOf(SPRING_BOOT_TEST_BASIC_MODULE_PATTERN) \ No newline at end of file diff --git a/utbot-spring-framework/src/main/kotlin/org/utbot/framework/process/SpringAnalyzerTask.kt b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/process/SpringAnalyzerTask.kt new file mode 100644 index 0000000000..ab07f85d8f --- /dev/null +++ b/utbot-spring-framework/src/main/kotlin/org/utbot/framework/process/SpringAnalyzerTask.kt @@ -0,0 +1,42 @@ +package org.utbot.framework.process + +import mu.KotlinLogging +import org.utbot.framework.plugin.api.BeanAdditionalData +import org.utbot.framework.plugin.api.BeanDefinitionData +import org.utbot.framework.plugin.api.SpringSettings.PresentSpringSettings +import org.utbot.framework.process.kryo.KryoHelper +import org.utbot.rd.use +import org.utbot.spring.process.SpringAnalyzerProcess + +class SpringAnalyzerTask( + private val classpath: List, + private val settings: PresentSpringSettings, +) : EngineProcessTask> { + companion object { + private val logger = KotlinLogging.logger {} + } + + override fun perform(kryoHelper: KryoHelper): List = try { + SpringAnalyzerProcess.createBlocking(classpath).use { + it.getBeanDefinitions(settings) + }.beanDefinitions + .map { data -> + // mapping RD models to API models + val additionalData = data.additionalData?.let { + BeanAdditionalData( + it.factoryMethodName, + it.parameterTypes, + it.configClassFqn + ) + } + BeanDefinitionData( + data.beanName, + data.beanTypeFqn, + additionalData + ) + } + } catch (e: Exception) { + logger.error(e) { "Spring Analyzer crashed, resorting to using empty bean list" } + emptyList() + } +} \ No newline at end of file diff --git a/utbot-spring-test/build.gradle b/utbot-spring-test/build.gradle index c186b9c6e8..f9941479cf 100644 --- a/utbot-spring-test/build.gradle +++ b/utbot-spring-test/build.gradle @@ -1,5 +1,6 @@ dependencies { testImplementation(project(":utbot-framework")) + testImplementation(project(":utbot-spring-framework")) testImplementation project(':utbot-testing') testImplementation project(':utbot-spring-sample') diff --git a/utbot-spring-test/src/test/kotlin/org/utbot/examples/spring/autowiring/SpringNoConfigUtValueTestCaseChecker.kt b/utbot-spring-test/src/test/kotlin/org/utbot/examples/spring/autowiring/SpringNoConfigUtValueTestCaseChecker.kt index ed54103277..5a713137c5 100644 --- a/utbot-spring-test/src/test/kotlin/org/utbot/examples/spring/autowiring/SpringNoConfigUtValueTestCaseChecker.kt +++ b/utbot-spring-test/src/test/kotlin/org/utbot/examples/spring/autowiring/SpringNoConfigUtValueTestCaseChecker.kt @@ -1,10 +1,20 @@ package org.utbot.examples.spring.autowiring import org.utbot.examples.spring.utils.standardSpringTestingConfigurations +import org.utbot.framework.context.spring.SpringApplicationContextImpl +import org.utbot.framework.plugin.api.SpringSettings +import org.utbot.framework.plugin.api.SpringTestType import org.utbot.testing.UtValueTestCaseChecker -import org.utbot.testing.springNoConfigApplicationContext +import org.utbot.testing.defaultApplicationContext import kotlin.reflect.KClass +val springNoConfigApplicationContext = SpringApplicationContextImpl( + delegateContext = defaultApplicationContext, + springTestType = SpringTestType.UNIT_TEST, + springSettings = SpringSettings.AbsentSpringSettings, + beanDefinitions = emptyList() +) + abstract class SpringNoConfigUtValueTestCaseChecker( testClass: KClass<*> ) : UtValueTestCaseChecker( diff --git a/utbot-testing/src/main/kotlin/org/utbot/testing/Configurations.kt b/utbot-testing/src/main/kotlin/org/utbot/testing/Configurations.kt index d468673abd..e45de519d9 100644 --- a/utbot-testing/src/main/kotlin/org/utbot/testing/Configurations.kt +++ b/utbot-testing/src/main/kotlin/org/utbot/testing/Configurations.kt @@ -4,11 +4,8 @@ import org.utbot.framework.codegen.domain.ParametrizedTestSource import org.utbot.framework.codegen.domain.ProjectType import org.utbot.framework.context.simple.SimpleApplicationContext import org.utbot.framework.context.simple.SimpleMockerContext -import org.utbot.framework.context.spring.SpringApplicationContextImpl import org.utbot.framework.plugin.api.CodegenLanguage import org.utbot.framework.plugin.api.MockStrategyApi -import org.utbot.framework.plugin.api.SpringSettings -import org.utbot.framework.plugin.api.SpringTestType interface AbstractConfiguration { val projectType: ProjectType @@ -48,10 +45,3 @@ val defaultApplicationContext = SimpleApplicationContext( staticsMockingIsConfigured = true, ) ) - -val springNoConfigApplicationContext = SpringApplicationContextImpl( - delegateContext = defaultApplicationContext, - springTestType = SpringTestType.UNIT_TEST, - springSettings = SpringSettings.AbsentSpringSettings, - beanDefinitions = emptyList() -)