diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgAbstractSpringTestClassConstructor.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgAbstractSpringTestClassConstructor.kt index 337454db66..105b00105b 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgAbstractSpringTestClassConstructor.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgAbstractSpringTestClassConstructor.kt @@ -114,7 +114,7 @@ abstract class CgAbstractSpringTestClassConstructor(context: CgContext): valueByUtModelWrapper[key] = createdVariable } - variableConstructor.annotatedModelVariables + variableConstructor.annotatedModelGroups .getOrPut(annotationClassId) { mutableSetOf() } += listOfUtModels } @@ -133,7 +133,7 @@ abstract class CgAbstractSpringTestClassConstructor(context: CgContext): */ private fun clearUnwantedVariableModels() { val trustedListOfModels = - variableConstructor.annotatedModelVariables.values.flatten() + listOf(UtSpringContextModel.wrap()) + variableConstructor.annotatedModelGroups.values.flatten() + listOf(UtSpringContextModel.wrap()) valueByUtModelWrapper .filterNot { it.key in trustedListOfModels } diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgClassFieldManager.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgClassFieldManager.kt new file mode 100644 index 0000000000..6d61d7e337 --- /dev/null +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgClassFieldManager.kt @@ -0,0 +1,119 @@ +package org.utbot.framework.codegen.tree + +import org.utbot.framework.codegen.domain.UtModelWrapper +import org.utbot.framework.codegen.domain.builtin.injectMocksClassId +import org.utbot.framework.codegen.domain.builtin.mockClassId +import org.utbot.framework.codegen.domain.context.CgContext +import org.utbot.framework.codegen.domain.context.CgContextOwner +import org.utbot.framework.codegen.domain.models.CgValue +import org.utbot.framework.codegen.domain.models.CgVariable +import org.utbot.framework.plugin.api.ClassId +import org.utbot.framework.plugin.api.UtAssembleModel +import org.utbot.framework.plugin.api.UtCompositeModel +import org.utbot.framework.plugin.api.UtModel +import org.utbot.framework.plugin.api.isMockModel +import org.utbot.framework.plugin.api.util.SpringModelUtils.autowiredClassId +import org.utbot.framework.plugin.api.util.SpringModelUtils.isAutowiredFromContext + +sealed interface CgClassFieldManager : CgContextOwner { + + val annotationType: ClassId + + fun constructVariableForField(model: UtModel, modelVariable: CgValue): CgValue +} + +abstract class CgClassFieldManagerImpl(context: CgContext) : + CgClassFieldManager, + CgContextOwner by context { + + val variableConstructor: CgSpringVariableConstructor by lazy { + CgComponents.getVariableConstructorBy(context) as CgSpringVariableConstructor + } +} + +class CgInjectingMocksFieldsManager(val context: CgContext) : CgClassFieldManagerImpl(context) { + + override val annotationType = injectMocksClassId + + override fun constructVariableForField(model: UtModel, modelVariable: CgValue): CgValue { + val modelFields = when (model) { + is UtCompositeModel -> model.fields + is UtAssembleModel -> model.origin?.fields + else -> null + } + + modelFields?.forEach { (fieldId, fieldModel) -> + //creating variables for modelVariable fields + val variableForField = variableConstructor.getOrCreateVariable(fieldModel) + + // If field model is a mock, it is set in the connected with instance under test automatically via @InjectMocks; + // Otherwise we need to set this field manually. + if (!fieldModel.isMockModel()) { + variableConstructor.setFieldValue(modelVariable, fieldId, variableForField) + } + } + + return modelVariable + } + +} + +class CgMockedFieldsManager(context: CgContext) : CgClassFieldManagerImpl(context) { + + override val annotationType = mockClassId + + override fun constructVariableForField(model: UtModel, modelVariable: CgValue): CgValue { + if (model.isMockModel()) { + variableConstructor.mockFrameworkManager.createMockForVariable( + model as UtCompositeModel, + modelVariable as CgVariable, + ) + } + return modelVariable + } + +} + +class CgAutowiredFieldsManager(context: CgContext) : CgClassFieldManagerImpl(context) { + + override val annotationType = autowiredClassId + + override fun constructVariableForField(model: UtModel, modelVariable: CgValue): CgValue { + return when { + model.isAutowiredFromContext() -> { + variableConstructor.constructAssembleForVariable(model as UtAssembleModel) + } + + else -> error("Trying to autowire model $model but it is not appropriate") + } + } +} + +class ClassFieldManagerFacade(context: CgContext) : CgContextOwner by context { + + private val injectingMocksFieldsManager = CgInjectingMocksFieldsManager(context) + private val mockedFieldsManager = CgMockedFieldsManager(context) + private val autowiredFieldsManager = CgAutowiredFieldsManager(context) + + fun constructVariableForField( + model: UtModel, + annotatedModelGroups: Map>, + ): CgValue? { + val annotationManagers = listOf(injectingMocksFieldsManager, mockedFieldsManager, autowiredFieldsManager) + + annotationManagers.forEach { manager -> + val alreadyCreatedVariable = findCgValueByModel(model, annotatedModelGroups[manager.annotationType]) + + if (alreadyCreatedVariable != null) { + return manager.constructVariableForField(model, alreadyCreatedVariable) + } + } + + return null + } + + private fun findCgValueByModel(model: UtModel, setOfModels: Set?): CgValue? { + val key = setOfModels?.find { it == model.wrap() } ?: return null + return valueByUtModelWrapper[key] + } +} \ No newline at end of file diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringVariableConstructor.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringVariableConstructor.kt index 32f82dc246..b86e6cb418 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringVariableConstructor.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgSpringVariableConstructor.kt @@ -1,68 +1,23 @@ package org.utbot.framework.codegen.tree import org.utbot.framework.codegen.domain.UtModelWrapper -import org.utbot.framework.codegen.domain.builtin.injectMocksClassId -import org.utbot.framework.codegen.domain.builtin.mockClassId import org.utbot.framework.codegen.domain.context.CgContext import org.utbot.framework.codegen.domain.models.CgLiteral import org.utbot.framework.codegen.domain.models.CgValue -import org.utbot.framework.codegen.domain.models.CgVariable import org.utbot.framework.plugin.api.ClassId -import org.utbot.framework.plugin.api.UtAssembleModel -import org.utbot.framework.plugin.api.UtCompositeModel import org.utbot.framework.plugin.api.UtModel import org.utbot.framework.plugin.api.UtSpringContextModel -import org.utbot.framework.plugin.api.isMockModel -import org.utbot.framework.plugin.api.util.SpringModelUtils.autowiredClassId -import org.utbot.framework.plugin.api.util.SpringModelUtils.isAutowiredFromContext import org.utbot.framework.plugin.api.util.stringClassId class CgSpringVariableConstructor(context: CgContext) : CgVariableConstructor(context) { - val annotatedModelVariables: MutableMap> = mutableMapOf() + val annotatedModelGroups: MutableMap> = mutableMapOf() - override fun getOrCreateVariable(model: UtModel, name: String?): CgValue { - val alreadyCreatedInjectMocks = findCgValueByModel(model, annotatedModelVariables[injectMocksClassId]) - if (alreadyCreatedInjectMocks != null) { - val modelFields = when (model) { - is UtCompositeModel -> model.fields - is UtAssembleModel -> model.origin?.fields - else -> null - } - - modelFields?.forEach{ (fieldId, fieldModel) -> - val variableForField = getOrCreateVariable(fieldModel) - - // If field model is a mock, it is set in the connected with instance under test automatically via @InjectMocks; - // Otherwise we need to set this field manually. - if(!fieldModel.isMockModel()) { - setFieldValue(alreadyCreatedInjectMocks, fieldId, variableForField) - } - } - - return alreadyCreatedInjectMocks - } - - val alreadyCreatedMock = findCgValueByModel(model, annotatedModelVariables[mockClassId]) - if (alreadyCreatedMock != null) { - if (model.isMockModel()) { - mockFrameworkManager.createMockForVariable( - model as UtCompositeModel, - alreadyCreatedMock as CgVariable, - ) - } + private val classFieldManager = ClassFieldManagerFacade(context) - return alreadyCreatedMock - } + override fun getOrCreateVariable(model: UtModel, name: String?): CgValue { + val variable = classFieldManager.constructVariableForField(model, annotatedModelGroups) - val alreadyCreatedAutowired = findCgValueByModel(model, annotatedModelVariables[autowiredClassId]) - if (alreadyCreatedAutowired != null) { - return when { - model.isAutowiredFromContext() -> { - super.constructAssembleForVariable(model as UtAssembleModel) - } - else -> error("Trying to autowire model $model but it is not appropriate") - } - } + variable?.let { return it } return when (model) { is UtSpringContextModel -> createApplicationContextVariable() @@ -80,9 +35,4 @@ class CgSpringVariableConstructor(context: CgContext) : CgVariableConstructor(co valueByUtModelWrapper[UtSpringContextModel.wrap()] = it } } - - private fun findCgValueByModel(model: UtModel, setOfModels: Set?): CgValue? { - val key = setOfModels?.find { it == model.wrap() } ?: return null - return valueByUtModelWrapper[key] - } } \ No newline at end of file diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgVariableConstructor.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgVariableConstructor.kt index 3b4ee48122..39374fb616 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgVariableConstructor.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgVariableConstructor.kt @@ -64,7 +64,7 @@ open class CgVariableConstructor(val context: CgContext) : CgStatementConstructor by getStatementConstructorBy(context) { private val nameGenerator = getNameGeneratorBy(context) - protected val mockFrameworkManager = getMockFrameworkManagerBy(context) + val mockFrameworkManager = getMockFrameworkManagerBy(context) /** * Take already created CgValue or construct either a new [CgVariable] or new [CgLiteral] for the given model. @@ -176,7 +176,7 @@ open class CgVariableConstructor(val context: CgContext) : return obj } - protected fun setFieldValue(obj: CgValue, fieldId: FieldId, variableForField: CgValue){ + fun setFieldValue(obj: CgValue, fieldId: FieldId, variableForField: CgValue){ val field = fieldId.jField val fieldFromVariableSpecifiedType = obj.type.findFieldByIdOrNull(fieldId) @@ -219,7 +219,7 @@ open class CgVariableConstructor(val context: CgContext) : .also { valueByUtModelWrapper[model.wrap()] = it } } - protected fun constructAssembleForVariable(model: UtAssembleModel): CgValue { + fun constructAssembleForVariable(model: UtAssembleModel): CgValue { for (statementModel in model.modificationsChain) { when (statementModel) { is UtDirectSetFieldModel -> {