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 @@ -757,9 +757,12 @@ object SpringBoot : DependencyInjectionFramework(
*
* Used as a key in [valueByUtModelWrapper].
* Was introduced primarily for shared among all test methods global variables.
*
* `modelTagName` is used to distinguish between variables with annotation @Mock that have the same model
*/
data class UtModelWrapper(
val testSetId: Int,
val executionId: Int,
val model: UtModel
val model: UtModel,
val modelTagName: String?
)
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ interface CgContextOwner {
val getLambdaMethod: MethodId
get() = utilMethodProvider.getLambdaMethodMethodId

fun UtModel.wrap(): UtModelWrapper
fun UtModel.wrap(modelTagName: String? = null): UtModelWrapper
}

/**
Expand Down Expand Up @@ -580,11 +580,12 @@ class CgContext(
}
}

override fun UtModel.wrap(): UtModelWrapper =
override fun UtModel.wrap(modelTagName: String?): UtModelWrapper =
UtModelWrapper(
testSetId = currentTestSetId,
executionId = currentExecutionId,
model = this
model = this,
modelTagName = modelTagName
)

private fun createClassIdForNestedClass(testClassModel: SimpleTestClassModel): ClassId {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,10 @@ class SpringTestClassModelBuilder(val context: CgContext): TestClassModelBuilder

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

with(context){
collectRecursively(model.wrap(), dependentModels)
}

return dependentModels
}
Expand All @@ -98,49 +101,54 @@ class SpringTestClassModelBuilder(val context: CgContext): TestClassModelBuilder
return classModels
}

private fun collectRecursively(currentModel: UtModel, allModels: MutableSet<UtModelWrapper>) {
val cgModel = with(context) { currentModel.wrap() }
if (!allModels.add(cgModel)) {
private fun collectRecursively(currentModelWrapper: UtModelWrapper, allModels: MutableSet<UtModelWrapper>) {
if (!allModels.add(currentModelWrapper)) {
return
}

when (currentModel) {
is UtNullModel,
is UtPrimitiveModel,
is UtClassRefModel,
is UtVoidModel,
is UtEnumConstantModel,
is UtSpringContextModel -> {}
is UtLambdaModel -> {
currentModel.capturedValues.forEach { collectRecursively(it, allModels) }
}
is UtArrayModel -> {
currentModel.stores.values.forEach { collectRecursively(it, allModels) }
if (currentModel.stores.count() < currentModel.length) {
collectRecursively(currentModel.constModel, allModels)
with(context) {
when (val currentModel = currentModelWrapper.model) {
is UtNullModel,
is UtPrimitiveModel,
is UtClassRefModel,
is UtVoidModel,
is UtEnumConstantModel,
is UtSpringContextModel -> {}
is UtLambdaModel -> {
currentModel.capturedValues.forEach { collectRecursively(it.wrap(), allModels) }
}
}
is UtCompositeModel -> {
// Here we traverse fields only.
// Traversing mocks as well will result in wrong models playing
// a role of class fields with @Mock annotation.
currentModel.fields.values.forEach { collectRecursively(it, allModels) }
}
is UtAssembleModel -> {
currentModel.origin?.let { collectRecursively(it, allModels) }
is UtArrayModel -> {
currentModel.stores.values.forEach { collectRecursively(it.wrap(), allModels) }
if (currentModel.stores.count() < currentModel.length) {
collectRecursively(currentModel.constModel.wrap(), allModels)
}
}
is UtCompositeModel -> {
// Here we traverse fields only.
// Traversing mocks as well will result in wrong models playing
// a role of class fields with @Mock annotation.
currentModel.fields.forEach { (fieldId, model) ->
// We use `modelTagName` in order to distinguish mock models
val modeTagName = if(model.isMockModel()) fieldId.name else null
collectRecursively(model.wrap(modeTagName), allModels)
}
}
is UtAssembleModel -> {
currentModel.origin?.let { collectRecursively(it.wrap(), allModels) }

currentModel.instantiationCall.instance?.let { collectRecursively(it, allModels) }
currentModel.instantiationCall.params.forEach { collectRecursively(it, allModels) }
currentModel.instantiationCall.instance?.let { collectRecursively(it.wrap(), allModels) }
currentModel.instantiationCall.params.forEach { collectRecursively(it.wrap(), allModels) }

currentModel.modificationsChain.forEach { stmt ->
stmt.instance?.let { collectRecursively(it, allModels) }
when (stmt) {
is UtStatementCallModel -> stmt.params.forEach { collectRecursively(it, allModels) }
is UtDirectSetFieldModel -> collectRecursively(stmt.fieldModel, allModels)
currentModel.modificationsChain.forEach { stmt ->
stmt.instance?.let { collectRecursively(it.wrap(), allModels) }
when (stmt) {
is UtStatementCallModel -> stmt.params.forEach { collectRecursively(it.wrap(), allModels) }
is UtDirectSetFieldModel -> collectRecursively(stmt.fieldModel.wrap(), allModels)
}
}
}
//Python, JavaScript, Go models are not required in Spring
}
//Python, JavaScript, Go models are not required in Spring
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.utbot.framework.codegen.tree

import org.utbot.framework.codegen.domain.UtModelWrapper
import org.utbot.framework.codegen.domain.builtin.TestClassUtilMethodProvider
import org.utbot.framework.codegen.domain.context.CgContext
import org.utbot.framework.codegen.domain.models.AnnotationTarget.*
Expand All @@ -21,7 +22,6 @@ import org.utbot.framework.plugin.api.UtSpringContextModel
import org.utbot.framework.plugin.api.util.SpringModelUtils.getBeanNameOrNull
import org.utbot.framework.plugin.api.util.id
import java.lang.Exception
import java.util.Collections.max

abstract class CgAbstractSpringTestClassConstructor(context: CgContext) :
CgAbstractTestClassConstructor<SpringTestClassModel>(context) {
Expand Down Expand Up @@ -125,10 +125,18 @@ abstract class CgAbstractSpringTestClassConstructor(context: CgContext) :

modelWrappers
.forEach { modelWrapper ->
modelWrapper.let {
valueByUtModelWrapper[modelWrapper] = createdVariable
variableConstructor.annotatedModelGroups.getOrPut(annotationClassId) { mutableSetOf() } += modelWrapper
}

val modelWrapperWithNullTagName = UtModelWrapper(
testSetId = modelWrapper.testSetId,
executionId = modelWrapper.executionId,
model = modelWrapper.model,
modelTagName = null,
)

valueByUtModelWrapper[modelWrapperWithNullTagName] = createdVariable

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ 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
import java.util.*
import java.util.Collections.max
import kotlin.collections.HashMap

sealed interface CgClassFieldManager : CgContextOwner {
Expand Down Expand Up @@ -88,15 +88,16 @@ class CgMockedFieldsManager(context: CgContext) : CgClassFieldManagerImpl(contex
override fun fieldWithAnnotationIsRequired(modelWrappers: Set<UtModelWrapper>): Boolean {
// group [listOfUtModels] by `testSetId` and `executionId`
// to check how many instances of one type are used in each execution
val modelsByExecutions = modelWrappers
val modelWrappersByExecutions = modelWrappers
.groupByTo(HashMap()) { Pair(it.testSetId, it.executionId) }

// maximal instances of one type amount in one execution
val instanceMaxCount = Collections.max(modelsByExecutions.map { (_, modelsList) -> modelsList.size })
// maximal count of instances of the same type amount in one execution
// we use `modelTagName` in order to distinguish mock models by their name
val maxCountOfInstancesOfTheSameTypeByExecution = max(modelWrappersByExecutions.map { (_, modelsList) -> modelsList.size })

// if [instanceCount] is 1, then we mock variable by @Mock annotation
// if [maxCountOfInstancesOfTheSameTypeByExecution] is 1, then we mock variable by @Mock annotation
// Otherwise we will mock variable by simple mock later
return instanceMaxCount == 1
return maxCountOfInstancesOfTheSameTypeByExecution == 1
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ public Person(String firstName, String secondName, Integer age) {
this.age = age;
}

public Integer getAge(){
return age;
public String getName() {
return firstName + " " + lastName;
}

public String name() {
return firstName + " " + lastName;
public Integer getAge(){
return age;
}
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.utbot.examples.spring.autowiring.twoAndMoreBeansForOneType;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class ServiceOfBeansWithSameType {
@Autowired
private Person personOne;

@Autowired
private Person personTwo;

public final List<String> baseOrders = new ArrayList<>();

// a method for testing the case when the Engine produces one model on @Autowired variables of the same type
public Integer ageSum(){
return personOne.getAge() + personTwo.getAge();
}

// a method for testing the case when the Engine produces two models on @Autowired variables of the same type
public Boolean checker() {
return personOne.getName().equals("k") && personTwo.getName().length() > 5 && baseOrders.isEmpty();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.utbot.examples.spring.autowiring.oneBeanForOneType
package org.utbot.examples.spring.autowiring

import org.utbot.examples.spring.utils.standardSpringTestingConfigurations
import org.utbot.testing.UtValueTestCaseChecker
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.utbot.examples.spring.autowiring.oneBeanForOneType

import org.junit.jupiter.api.Test
import org.utbot.examples.spring.autowiring.SpringNoConfigUtValueTestCaseChecker
import org.utbot.examples.spring.utils.findAllRepositoryCall
import org.utbot.examples.spring.utils.springAdditionalDependencies
import org.utbot.examples.spring.utils.springMockStrategy
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.utbot.examples.spring.autowiring.oneBeanForOneType

import org.junit.jupiter.api.Test
import org.utbot.examples.spring.autowiring.SpringNoConfigUtValueTestCaseChecker
import org.utbot.examples.spring.utils.findAllRepositoryCall
import org.utbot.examples.spring.utils.saveRepositoryCall
import org.utbot.examples.spring.utils.springAdditionalDependencies
Expand Down
Loading