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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,17 @@ class SimpleTestClassModel(

/**
* Extended [SimpleTestClassModel] for Spring analysis reasons
*
* @param injectingMocksClass a class to inject other mocks into
* @param mockedClasses variables of test class to represent mocked instances
*/
class SpringTestClassModel(
classUnderTest: ClassId,
methodTestSets: List<CgMethodTestSet>,
nestedClasses: List<SimpleTestClassModel>,
val thisInstanceModels: TypedModelWrappers = mapOf(),
val thisInstanceDependentMocks: TypedModelWrappers = mapOf(),
val springSpecificInformation: SpringSpecificInformation,
): TestClassModel(classUnderTest, methodTestSets, nestedClasses)


class SpringSpecificInformation(
val thisInstanceModels: TypedModelWrappers = mapOf(),
val thisInstanceDependentMocks: TypedModelWrappers = mapOf(),
val applicationContextModels: TypedModelWrappers = mapOf(),
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.utbot.framework.codegen.domain.models.builders
import org.utbot.framework.codegen.domain.UtModelWrapper
import org.utbot.framework.codegen.domain.context.CgContext
import org.utbot.framework.codegen.domain.models.CgMethodTestSet
import org.utbot.framework.codegen.domain.models.SpringSpecificInformation
import org.utbot.framework.codegen.domain.models.SpringTestClassModel
import org.utbot.framework.plugin.api.ClassId
import org.utbot.framework.plugin.api.UtArrayModel
Expand All @@ -11,7 +12,6 @@ import org.utbot.framework.plugin.api.UtClassRefModel
import org.utbot.framework.plugin.api.UtCompositeModel
import org.utbot.framework.plugin.api.UtDirectSetFieldModel
import org.utbot.framework.plugin.api.UtEnumConstantModel
import org.utbot.framework.plugin.api.UtExecutableCallModel
import org.utbot.framework.plugin.api.UtLambdaModel
import org.utbot.framework.plugin.api.UtModel
import org.utbot.framework.plugin.api.UtNullModel
Expand All @@ -27,20 +27,20 @@ class SpringTestClassModelBuilder(val context: CgContext): TestClassModelBuilder

override fun createTestClassModel(classUnderTest: ClassId, testSets: List<CgMethodTestSet>): SpringTestClassModel {
val baseModel = SimpleTestClassModelBuilder(context).createTestClassModel(classUnderTest, testSets)
val (thisInstanceModels, dependentMockModels) = collectThisInstanceAndDependentModels(testSets)
val springSpecificInformation = collectSpecificModelsForClassVariables(testSets)

return SpringTestClassModel(
classUnderTest = baseModel.classUnderTest,
methodTestSets = baseModel.methodTestSets,
nestedClasses = baseModel.nestedClasses,
thisInstanceModels = thisInstanceModels,
thisInstanceDependentMocks = dependentMockModels
springSpecificInformation = springSpecificInformation
)
}

private fun collectThisInstanceAndDependentModels(testSets: List<CgMethodTestSet>): Pair<TypedModelWrappers, TypedModelWrappers> {
private fun collectSpecificModelsForClassVariables(testSets: List<CgMethodTestSet>): SpringSpecificInformation {
val thisInstanceModels = mutableSetOf<UtModelWrapper>()
val thisInstancesDependentModels = mutableSetOf<UtModelWrapper>()
val stateBeforeDependentModels = mutableSetOf<UtModelWrapper>()

with(context) {
for ((testSetIndex, testSet) in testSets.withIndex()) {
Expand All @@ -51,8 +51,13 @@ class SpringTestClassModelBuilder(val context: CgContext): TestClassModelBuilder
.filterNotNull()
.forEach { model ->
thisInstanceModels += model.wrap()
thisInstancesDependentModels += collectByThisInstanceModel(model)
thisInstancesDependentModels += collectByModel(model)

}

(execution.stateBefore.parameters + execution.stateBefore.thisInstance)
.filterNotNull()
.forEach { model -> stateBeforeDependentModels += collectByModel(model) }
}
}
}
Expand All @@ -65,10 +70,18 @@ class SpringTestClassModelBuilder(val context: CgContext): TestClassModelBuilder
cgModel.model.isMockModel() && cgModel !in thisInstanceModels
}

return thisInstanceModels.groupByClassId() to dependentMockModels.groupByClassId()
val applicationContextModels = stateBeforeDependentModels
.filter { it.model is UtSpringContextModel }
.toSet()

return SpringSpecificInformation(
thisInstanceModels.groupByClassId(),
dependentMockModels.groupByClassId(),
applicationContextModels.groupByClassId(),
)
}

private fun collectByThisInstanceModel(model: UtModel): Set<UtModelWrapper> {
private fun collectByModel(model: UtModel): Set<UtModelWrapper> {
val dependentModels = mutableSetOf<UtModelWrapper>()
collectRecursively(model, dependentModels)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,17 +85,9 @@ abstract class CgAbstractSpringTestClassConstructor(context: CgContext):
abstract fun constructAdditionalMethods(): CgMethodsCluster

protected fun constructFieldsWithAnnotation(
annotationClassId: ClassId,
groupedModelsByClassId: TypedModelWrappers,
annotationClassId: ClassId
): List<CgFieldDeclaration> {
require(
annotationClassId == injectMocksClassId ||
annotationClassId == mockClassId ||
annotationClassId == autowiredClassId
) {
error("Unexpected annotation classId -- $annotationClassId")
}

val annotation = statementConstructor.annotation(annotationClassId)

val constructedDeclarations = mutableListOf<CgFieldDeclaration>()
Expand All @@ -111,10 +103,8 @@ abstract class CgAbstractSpringTestClassConstructor(context: CgContext):
valueByUtModelWrapper[key] = createdVariable
}

when (annotationClassId) {
injectMocksClassId -> variableConstructor.injectedMocksModelsVariables += listOfUtModels
mockClassId -> variableConstructor.mockedModelsVariables += listOfUtModels
}
variableConstructor.annotatedModelVariables
.getOrPut(annotationClassId) { mutableSetOf() } += listOfUtModels
}

return constructedDeclarations
Expand All @@ -130,12 +120,8 @@ abstract class CgAbstractSpringTestClassConstructor(context: CgContext):
* related side effects and just creating a variable definition,
* but it will take very long time to do it now.
*/
protected fun clearUnwantedVariableModels() {
val whiteListOfModels =
listOf(
variableConstructor.mockedModelsVariables,
variableConstructor.injectedMocksModelsVariables
).flatten()
private fun clearUnwantedVariableModels() {
val whiteListOfModels = variableConstructor.annotatedModelVariables.values.flatten()

valueByUtModelWrapper
.filter { it.key !in whiteListOfModels }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import org.utbot.framework.codegen.domain.models.SpringTestClassModel
class CgSpringIntegrationTestClassConstructor(context: CgContext) : CgAbstractSpringTestClassConstructor(context) {

override fun constructClassFields(testClassModel: SpringTestClassModel): List<CgFieldDeclaration> {
return constructFieldsWithAnnotation(testClassModel.thisInstanceModels, autowiredClassId)
val applicationContextModels = testClassModel.springSpecificInformation.applicationContextModels
return constructFieldsWithAnnotation(autowiredClassId, applicationContextModels)
}

override fun constructAdditionalMethods() = CgMethodsCluster(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ class CgSpringUnitTestClassConstructor(context: CgContext) : CgAbstractSpringTes

override fun constructClassFields(testClassModel: SpringTestClassModel): List<CgFieldDeclaration> {
val fields = mutableListOf<CgFieldDeclaration>()
val thisInstances = testClassModel.springSpecificInformation.thisInstanceModels
val mocks = testClassModel.springSpecificInformation.thisInstanceDependentMocks

if (testClassModel.thisInstanceDependentMocks.isNotEmpty()) {
val mockedFields = constructFieldsWithAnnotation(testClassModel.thisInstanceDependentMocks, mockClassId)
val injectingMocksFields = constructFieldsWithAnnotation(testClassModel.thisInstanceModels, injectMocksClassId)
if (mocks.isNotEmpty()) {
val mockedFields = constructFieldsWithAnnotation(mockClassId, mocks)
val injectingMocksFields = constructFieldsWithAnnotation(injectMocksClassId, thisInstances)

fields += injectingMocksFields
fields += mockedFields
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
package org.utbot.framework.codegen.tree

import org.utbot.framework.codegen.domain.UtModelWrapper
import org.utbot.framework.codegen.domain.builtin.autowiredClassId
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.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

class CgSpringVariableConstructor(context: CgContext) : CgVariableConstructor(context) {
val injectedMocksModelsVariables: MutableSet<UtModelWrapper> = mutableSetOf()
val mockedModelsVariables: MutableSet<UtModelWrapper> = mutableSetOf()
val annotatedModelVariables: MutableMap<ClassId, MutableSet<UtModelWrapper>> = mutableMapOf()

override fun getOrCreateVariable(model: UtModel, name: String?): CgValue {
if (model is UtSpringContextModel) {
// TODO also, properly render corresponding @Autowired field(s), and make sure name isn't taken
return CgVariable(model.modelName, model.classId)
}

val alreadyCreatedInjectMocks = findCgValueByModel(model, injectedMocksModelsVariables)
val alreadyCreatedInjectMocks = findCgValueByModel(model, annotatedModelVariables[injectMocksClassId])
if (alreadyCreatedInjectMocks != null) {
val fields: Collection<UtModel> = when (model) {
is UtCompositeModel -> model.fields.values
Expand All @@ -33,7 +31,7 @@ class CgSpringVariableConstructor(context: CgContext) : CgVariableConstructor(co
return alreadyCreatedInjectMocks
}

val alreadyCreatedMock = findCgValueByModel(model, mockedModelsVariables)
val alreadyCreatedMock = findCgValueByModel(model, annotatedModelVariables[mockClassId])
if (alreadyCreatedMock != null) {
if (model.isMockModel()) {
mockFrameworkManager.createMockForVariable(
Expand All @@ -45,11 +43,26 @@ class CgSpringVariableConstructor(context: CgContext) : CgVariableConstructor(co
return alreadyCreatedMock
}

return super.getOrCreateVariable(model, name)
val alreadyCreatedAutowired = findCgValueByModel(model, annotatedModelVariables[autowiredClassId])
if (alreadyCreatedAutowired != null) {
return alreadyCreatedAutowired
}

return when (model) {
is UtSpringContextModel -> constructSpringContext(model, name)
else -> super.getOrCreateVariable(model, name)
}
}

private fun constructSpringContext(model: UtSpringContextModel, baseName: String?): CgValue {
val obj = newVar(model.classId, baseName) { utilsClassId[createInstance](model.classId.name) }

valueByUtModelWrapper[model.wrap()] = obj
return obj
}

private fun findCgValueByModel(model: UtModel, setOfModels: Set<UtModelWrapper>): CgValue? {
val key = setOfModels.find { it == model.wrap() }
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 @@ -52,6 +52,7 @@ import org.utbot.framework.plugin.api.UtModel
import org.utbot.framework.plugin.api.UtNullModel
import org.utbot.framework.plugin.api.UtPrimitiveModel
import org.utbot.framework.plugin.api.UtReferenceModel
import org.utbot.framework.plugin.api.UtSpringContextModel
import org.utbot.framework.plugin.api.UtStatementCallModel
import org.utbot.framework.plugin.api.UtVoidModel
import org.utbot.framework.plugin.api.util.classClassId
Expand Down