Skip to content

Commit

Permalink
CgSpringVariableConstructor refactoring #2326 (#2416)
Browse files Browse the repository at this point in the history
---------

Co-authored-by: Egor Kulikov <[email protected]>
  • Loading branch information
tepa46 and EgorkaKulikov authored Jul 17, 2023
1 parent b051634 commit f44dd6f
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ abstract class CgAbstractSpringTestClassConstructor(context: CgContext):
valueByUtModelWrapper[key] = createdVariable
}

variableConstructor.annotatedModelVariables
variableConstructor.annotatedModelGroups
.getOrPut(annotationClassId) { mutableSetOf() } += listOfUtModels
}

Expand All @@ -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 }
Expand Down
Original file line number Diff line number Diff line change
@@ -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<ClassId, Set<UtModelWrapper>>,
): 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<UtModelWrapper>?): CgValue? {
val key = setOfModels?.find { it == model.wrap() } ?: return null
return valueByUtModelWrapper[key]
}
}
Original file line number Diff line number Diff line change
@@ -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<ClassId, MutableSet<UtModelWrapper>> = mutableMapOf()
val annotatedModelGroups: MutableMap<ClassId, MutableSet<UtModelWrapper>> = 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()
Expand All @@ -80,9 +35,4 @@ class CgSpringVariableConstructor(context: CgContext) : CgVariableConstructor(co
valueByUtModelWrapper[UtSpringContextModel.wrap()] = it
}
}

private fun findCgValueByModel(model: UtModel, setOfModels: Set<UtModelWrapper>?): CgValue? {
val key = setOfModels?.find { it == model.wrap() } ?: return null
return valueByUtModelWrapper[key]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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 -> {
Expand Down

0 comments on commit f44dd6f

Please sign in to comment.