Skip to content

Commit a505cae

Browse files
authored
Improve the readability of integration test generated for Spring controller (#2564)
* Make `CgVariableConstructor` generate more base names * Pass array as varargs param to set `queryParams` * Replace `declareOrGet` with `getOrCreateVariable`
1 parent 9f849b3 commit a505cae

File tree

2 files changed

+25
-46
lines changed

2 files changed

+25
-46
lines changed

utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/util/SpringModelUtils.kt

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -739,34 +739,17 @@ object SpringModelUtils {
739739
methodId: MethodId,
740740
arguments: List<UtModel>,
741741
idGenerator: () -> Int
742-
): List< Pair<UtPrimitiveModel, UtAssembleModel> > {
742+
): List<Pair<UtPrimitiveModel, UtArrayModel>> {
743743
val requestParams = collectArgumentsWithAnnotationModels(methodId, requestParamClassId, arguments)
744744

745745
return requestParams.map { (name, value) ->
746746
Pair(UtPrimitiveModel(name),
747-
UtAssembleModel(
747+
UtArrayModel(
748748
id = idGenerator(),
749-
classId = listClassId,
750-
modelName = "queryParams",
751-
instantiationCall = UtExecutableCallModel(
752-
instance = null,
753-
executable = constructorId(java.util.ArrayList::class.id),
754-
params = emptyList()
755-
),
756-
modificationsChainProvider = {
757-
listOf(
758-
UtExecutableCallModel(
759-
instance = this,
760-
executable = methodId(
761-
classId = listClassId,
762-
name = "add",
763-
returnType = booleanClassId,
764-
arguments = arrayOf(Object::class.id),
765-
),
766-
params = listOf(value)
767-
)
768-
)
769-
}
749+
classId = getArrayClassIdByElementClassId(objectClassId),
750+
length = 1,
751+
constModel = UtNullModel(objectClassId),
752+
stores = mutableMapOf(0 to value),
770753
)
771754
)
772755
}
@@ -820,7 +803,7 @@ object SpringModelUtils {
820803
private fun createUrlTemplateModel(
821804
requestPath: String,
822805
pathVariablesModel: UtAssembleModel,
823-
requestParamModel: List<Pair<UtPrimitiveModel, UtAssembleModel>>,
806+
requestParamModel: List<Pair<UtPrimitiveModel, UtArrayModel>>,
824807
idGenerator: () -> Int
825808
): UtModel {
826809
val requestPathModel = UtPrimitiveModel(requestPath)
@@ -870,7 +853,7 @@ object SpringModelUtils {
870853
executable = MethodId(
871854
classId = uriComponentsBuilderClassId,
872855
name = "queryParam",
873-
parameters = listOf(stringClassId, collectionClassId),
856+
parameters = listOf(stringClassId, getArrayClassIdByElementClassId(objectClassId)),
874857
returnType = uriComponentsBuilderClassId
875858
),
876859
params = listOf(name, value),

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/tree/CgVariableConstructor.kt

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import org.utbot.framework.plugin.api.util.booleanClassId
4949
import org.utbot.framework.plugin.api.util.booleanWrapperClassId
5050
import org.utbot.framework.plugin.api.util.classClassId
5151
import org.utbot.framework.plugin.api.util.defaultValueModel
52+
import org.utbot.framework.plugin.api.util.executable
5253
import org.utbot.framework.plugin.api.util.jField
5354
import org.utbot.framework.plugin.api.util.findFieldByIdOrNull
5455
import org.utbot.framework.plugin.api.util.id
@@ -188,7 +189,7 @@ open class CgVariableConstructor(val context: CgContext) :
188189
}
189190

190191
for ((fieldId, fieldModel) in model.fields) {
191-
val variableForField = getOrCreateVariable(fieldModel)
192+
val variableForField = getOrCreateVariable(fieldModel, name = fieldId.name)
192193
if (!variableForField.hasDefaultValue())
193194
setFieldValue(obj, fieldId, variableForField)
194195
}
@@ -259,9 +260,12 @@ open class CgVariableConstructor(val context: CgContext) :
259260
for (statementModel in model.modificationsChain) {
260261
when (statementModel) {
261262
is UtDirectSetFieldModel -> {
262-
val instance = declareOrGet(statementModel.instance)
263+
val instance = getOrCreateVariable(statementModel.instance)
263264
// fields here are supposed to be accessible, so we assign them directly without any checks
264-
instance[statementModel.fieldId] `=` declareOrGet(statementModel.fieldModel)
265+
instance[statementModel.fieldId] `=` getOrCreateVariable(
266+
model = statementModel.fieldModel,
267+
name = statementModel.fieldId.name,
268+
)
265269
}
266270
is UtStatementCallModel -> {
267271
val call = createCgExecutableCallFromUtExecutableCall(statementModel)
@@ -284,23 +288,22 @@ open class CgVariableConstructor(val context: CgContext) :
284288
when (statementModel) {
285289
is UtExecutableCallModel -> {
286290
val executable = statementModel.executable
291+
val paramNames = runCatching {
292+
executable.executable.parameters.map { if (it.isNamePresent) it.name else null }
293+
}.getOrNull()
287294
val params = statementModel.params
295+
val caller = statementModel.instance?.let { getOrCreateVariable(it) }
296+
val args = params.mapIndexed { i, param ->
297+
getOrCreateVariable(param, name = paramNames?.getOrNull(i))
298+
}
288299

289300
when (executable) {
290-
is MethodId -> {
291-
val caller = statementModel.instance?.let { declareOrGet(it) }
292-
val args = params.map { declareOrGet(it) }
293-
caller[executable](*args.toTypedArray())
294-
}
295-
296-
is ConstructorId -> {
297-
val args = params.map { declareOrGet(it) }
298-
executable(*args.toTypedArray())
299-
}
301+
is MethodId -> caller[executable](*args.toTypedArray())
302+
is ConstructorId -> executable(*args.toTypedArray())
300303
}
301304
}
302305
is UtDirectGetFieldModel -> {
303-
val instance = declareOrGet(statementModel.instance)
306+
val instance = getOrCreateVariable(statementModel.instance)
304307
val fieldAccess = statementModel.fieldAccess
305308
utilsClassId[getFieldValue](instance, fieldAccess.fieldId.declaringClass.canonicalName, fieldAccess.fieldId.name)
306309
}
@@ -508,13 +511,6 @@ open class CgVariableConstructor(val context: CgContext) :
508511
return newVar(Class::class.id, baseName) { init }
509512
}
510513

511-
/**
512-
* Either declares a new variable or gets it from context's cache
513-
* Returns the obtained variable
514-
*/
515-
private fun declareOrGet(model: UtModel): CgValue =
516-
valueByUtModelWrapper[model.wrap()] ?: getOrCreateVariable(model)
517-
518514
private fun basicForLoop(start: Any, until: Any, body: (i: CgExpression) -> Unit) {
519515
forLoop {
520516
val (i, init) = loopInitialization(intClassId, "i", start.resolve())

0 commit comments

Comments
 (0)