Skip to content

Commit 8296c59

Browse files
Refactor: change instantiationChain to instantiationCall and rewrite UtAssembleModel constructor
1 parent 9c4b884 commit 8296c59

File tree

24 files changed

+228
-218
lines changed

24 files changed

+228
-218
lines changed

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

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -471,26 +471,52 @@ data class UtArrayModel(
471471
/**
472472
* Model for complex objects with assemble instructions.
473473
*
474-
* @param instantiationChain is a chain of [UtStatementModel] to instantiate represented object
475-
* @param modificationsChain is a chain of [UtStatementModel] to construct object state
474+
* The default constructor is made private to enforce using a safe constructor.
475+
*
476+
* @param instantiationCall is an [UtExecutableCallModel] to instantiate represented object.
477+
* @param modificationsChain is a chain of [UtStatementModel] to construct object state.
476478
*/
477-
data class UtAssembleModel(
479+
data class UtAssembleModel private constructor(
478480
override val id: Int?,
479481
override val classId: ClassId,
480482
override val modelName: String,
481-
val instantiationChain: List<UtStatementModel> = emptyList(),
482-
val modificationsChain: List<UtStatementModel> = emptyList(),
483-
val origin: UtCompositeModel? = null
483+
val instantiationCall: UtExecutableCallModel,
484+
val modificationsChain: List<UtStatementModel>,
485+
val origin: UtCompositeModel?
484486
) : UtReferenceModel(id, classId, modelName) {
485-
val allStatementsChain
486-
get() = instantiationChain + modificationsChain
487-
val finalInstantiationModel
488-
get() = instantiationChain.lastOrNull()
487+
488+
/**
489+
* Creates a new [UtAssembleModel].
490+
*
491+
* Please note, that it's the caller responsibility to properly cache [UtModel]s to prevent an infinite recursion.
492+
* The order of the calling:
493+
* 1. [instantiationCall]
494+
* 2. [constructor]
495+
* 3. [modificationsChainProvider]. Possible caching should be made at the beginning of this method.
496+
*
497+
* @param instantiationCall defines the single instruction, which provides a [UtAssembleModel]. It could be a
498+
* constructor or a method of another class, which returns the object of the [classId] type.
499+
*
500+
* @param modificationsChainProvider used for creating modifying statements. Its receiver corresponds to newly
501+
* created [UtAssembleModel], so you can use it for caching and for creating [UtExecutableCallModel]s with it
502+
* as [UtExecutableCallModel.instance].
503+
*/
504+
constructor(
505+
id: Int?,
506+
classId: ClassId,
507+
modelName: String,
508+
instantiationCall: UtExecutableCallModel,
509+
origin: UtCompositeModel? = null,
510+
modificationsChainProvider: UtAssembleModel.() -> List<UtStatementModel> = { emptyList() }
511+
) : this(id, classId, modelName, instantiationCall, mutableListOf(), origin) {
512+
val modificationChainStatements = modificationsChainProvider()
513+
(modificationsChain as MutableList<UtStatementModel>).addAll(modificationChainStatements)
514+
}
489515

490516
override fun toString() = withToStringThreadLocalReentrancyGuard {
491517
buildString {
492518
append("UtAssembleModel(${classId.simpleName} $modelName) ")
493-
append(instantiationChain.joinToString(" "))
519+
append(instantiationCall)
494520
if (modificationsChain.isNotEmpty()) {
495521
append(" ")
496522
append(modificationsChain.joinToString(" "))
@@ -562,7 +588,6 @@ sealed class UtStatementModel(
562588
* Step of assemble instruction that calls executable.
563589
*
564590
* Contains executable to call, call parameters and an instance model before call.
565-
* Return value is used for tracking objects and call others methods with these tracking objects as parameters.
566591
*/
567592
data class UtExecutableCallModel(
568593
override val instance: UtReferenceModel?,

utbot-framework-test/src/test/kotlin/org/utbot/examples/models/ModelsIdEqualityChecker.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ internal class ModelsIdEqualityChecker : UtModelTestCaseChecker(
129129

130130
private fun UtReferenceModel.findFieldId(): Int? {
131131
this as UtAssembleModel
132-
val fieldModel = this.allStatementsChain
132+
val fieldModel = this.modificationsChain
133133
.filterIsInstance<UtDirectSetFieldModel>()
134134
.single()
135135
.fieldModel

utbot-framework/src/main/kotlin/org/utbot/engine/CollectionWrappers.kt

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -119,21 +119,15 @@ abstract class BaseContainerWrapper(containerClassName: String) : BaseOverridden
119119

120120
val classId = chooseClassIdWithConstructor(wrapper.type.sootClass.id)
121121

122-
val instantiationChain = mutableListOf<UtStatementModel>()
123-
val modificationsChain = mutableListOf<UtStatementModel>()
124-
125-
UtAssembleModel(addr, classId, modelName, instantiationChain, modificationsChain)
126-
.apply {
127-
instantiationChain += UtExecutableCallModel(
128-
instance = null,
129-
executable = constructorId(classId),
130-
params = emptyList()
131-
)
122+
val instantiationCall = UtExecutableCallModel(
123+
instance = null,
124+
executable = constructorId(classId),
125+
params = emptyList()
126+
)
132127

133-
modificationsChain += parameterModels.map {
134-
UtExecutableCallModel(this, modificationMethodId, it)
135-
}
136-
}
128+
UtAssembleModel(addr, classId, modelName, instantiationCall) {
129+
parameterModels.map { UtExecutableCallModel(this, modificationMethodId, it) }
130+
}
137131
}
138132

139133
/**

utbot-framework/src/main/kotlin/org/utbot/engine/ObjectWrappers.kt

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -241,17 +241,15 @@ data class ThrowableWrapper(val throwable: Throwable) : WrapperInterface {
241241
val addr = resolver.holder.concreteAddr(wrapper.addr)
242242
val modelName = nextModelName(throwable.javaClass.simpleName.decapitalize())
243243

244-
val instantiationChain = mutableListOf<UtStatementModel>()
245-
return UtAssembleModel(addr, classId, modelName, instantiationChain)
246-
.apply {
247-
instantiationChain += when (val message = throwable.message) {
248-
null -> UtExecutableCallModel(null, constructorId(classId), emptyList())
249-
else -> UtExecutableCallModel(
250-
null,
251-
constructorId(classId, stringClassId),
252-
listOf(UtPrimitiveModel(message))
253-
)
254-
}
255-
}
244+
val instantiationCall = when (val message = throwable.message) {
245+
null -> UtExecutableCallModel(null, constructorId(classId), emptyList())
246+
else -> UtExecutableCallModel(
247+
null,
248+
constructorId(classId, stringClassId),
249+
listOf(UtPrimitiveModel(message))
250+
)
251+
}
252+
253+
return UtAssembleModel(addr, classId, modelName, instantiationCall)
256254
}
257255
}

utbot-framework/src/main/kotlin/org/utbot/engine/OptionalWrapper.kt

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,8 @@ class OptionalWrapper(private val utOptionalClass: UtOptionalClass) : BaseOverri
9090
val addr = holder.concreteAddr(wrapper.addr)
9191
val modelName = nextModelName(baseModelName)
9292

93-
val instantiationChain = mutableListOf<UtStatementModel>()
94-
val modificationsChain = mutableListOf<UtStatementModel>()
95-
return UtAssembleModel(addr, classId, modelName, instantiationChain, modificationsChain)
96-
.apply {
97-
instantiationChain += instantiationFactoryCallModel(classId, wrapper)
98-
}
93+
val instantiationCall = instantiationFactoryCallModel(classId, wrapper)
94+
return UtAssembleModel(addr, classId, modelName, instantiationCall)
9995
}
10096

10197
private fun Resolver.instantiationFactoryCallModel(classId: ClassId, wrapper: ObjectValue) : UtExecutableCallModel {

utbot-framework/src/main/kotlin/org/utbot/engine/Resolver.kt

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -550,11 +550,8 @@ class Resolver(
550550
val baseModelName = primitiveClassId.name
551551
val constructorId = constructorId(classId, primitiveClassId)
552552
val valueModel = fields[FieldId(classId, "value")] ?: primitiveClassId.defaultValueModel()
553-
val instantiationChain = mutableListOf<UtExecutableCallModel>()
554-
UtAssembleModel(addr, classId, nextModelName(baseModelName), instantiationChain)
555-
.apply {
556-
instantiationChain += UtExecutableCallModel(null, constructorId, listOf(valueModel))
557-
}
553+
val instantiationCall = UtExecutableCallModel(null, constructorId, listOf(valueModel))
554+
UtAssembleModel(addr, classId, nextModelName(baseModelName), instantiationCall)
558555
}
559556
}
560557

utbot-framework/src/main/kotlin/org/utbot/engine/SecurityManagerWrapper.kt

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ package org.utbot.engine
22

33
import org.utbot.engine.overrides.security.UtSecurityManager
44
import org.utbot.framework.plugin.api.UtAssembleModel
5+
import org.utbot.framework.plugin.api.UtExecutableCallModel
56
import org.utbot.framework.plugin.api.UtModel
6-
import org.utbot.framework.plugin.api.UtStatementModel
77
import org.utbot.framework.plugin.api.classId
8+
import org.utbot.framework.plugin.api.util.executableId
89
import org.utbot.framework.util.nextModelName
910
import soot.Scene
1011
import soot.SootClass
@@ -27,9 +28,13 @@ class SecurityManagerWrapper : BaseOverriddenWrapper(utSecurityManagerClass.name
2728
val addr = holder.concreteAddr(wrapper.addr)
2829
val modelName = nextModelName(baseModelName)
2930

30-
val instantiationChain = mutableListOf<UtStatementModel>()
31-
val modificationChain = mutableListOf<UtStatementModel>()
32-
return UtAssembleModel(addr, classId, modelName, instantiationChain, modificationChain)
31+
val instantiationCall = UtExecutableCallModel(
32+
null,
33+
System::getSecurityManager.executableId,
34+
emptyList()
35+
)
36+
37+
return UtAssembleModel(addr, classId, modelName, instantiationCall)
3338
}
3439

3540
companion object {

utbot-framework/src/main/kotlin/org/utbot/engine/StreamWrappers.kt

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -61,23 +61,19 @@ abstract class StreamWrapper(
6161
val modelName = nextModelName(baseModelName)
6262
val parametersArrayModel = resolveElementsAsArrayModel(wrapper)
6363

64-
val instantiationChain = mutableListOf<UtStatementModel>()
65-
val modificationsChain = emptyList<UtStatementModel>()
66-
67-
UtAssembleModel(addr, utStreamClass.overriddenStreamClassId, modelName, instantiationChain, modificationsChain)
68-
.apply {
69-
val (builder, params) = if (parametersArrayModel == null || parametersArrayModel.length == 0) {
70-
streamEmptyMethodId to emptyList()
71-
} else {
72-
streamOfMethodId to listOf(parametersArrayModel)
73-
}
74-
75-
instantiationChain += UtExecutableCallModel(
76-
instance = null,
77-
executable = builder,
78-
params = params
79-
)
80-
}
64+
val (builder, params) = if (parametersArrayModel == null || parametersArrayModel.length == 0) {
65+
streamEmptyMethodId to emptyList()
66+
} else {
67+
streamOfMethodId to listOf(parametersArrayModel)
68+
}
69+
70+
val instantiationCall = UtExecutableCallModel(
71+
instance = null,
72+
executable = builder,
73+
params = params
74+
)
75+
76+
UtAssembleModel(addr, utStreamClass.overriddenStreamClassId, modelName, instantiationCall)
8177
}
8278

8379
override fun chooseClassIdWithConstructor(classId: ClassId): ClassId = error("No constructor for Stream")

utbot-framework/src/main/kotlin/org/utbot/engine/Strings.kt

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -179,16 +179,12 @@ class StringWrapper : BaseOverriddenWrapper(utStringClass.name) {
179179
val charValues = CharArray(length) { (values.stores[it] as UtPrimitiveModel).value as Char }
180180
val stringModel = UtPrimitiveModel(String(charValues))
181181

182-
val instantiationChain = mutableListOf<UtStatementModel>()
183-
val modificationsChain = mutableListOf<UtStatementModel>()
184-
return UtAssembleModel(addr, classId, modelName, instantiationChain, modificationsChain)
185-
.apply {
186-
instantiationChain += UtExecutableCallModel(
187-
instance = null,
188-
constructorId(classId, STRING_TYPE.classId),
189-
listOf(stringModel)
190-
)
191-
}
182+
val instantiationCall = UtExecutableCallModel(
183+
instance = null,
184+
constructorId(classId, STRING_TYPE.classId),
185+
listOf(stringModel)
186+
)
187+
return UtAssembleModel(addr, classId, modelName, instantiationCall)
192188
}
193189
}
194190

@@ -332,18 +328,13 @@ sealed class UtAbstractStringBuilderWrapper(className: String) : BaseOverriddenW
332328

333329
val charValues = CharArray(length) { (values.stores[it] as UtPrimitiveModel).value as Char }
334330
val stringModel = UtPrimitiveModel(String(charValues))
335-
336-
val instantiationChain = mutableListOf<UtStatementModel>()
337-
val modificationsChain = mutableListOf<UtStatementModel>()
338331
val constructorId = constructorId(wrapper.type.classId, STRING_TYPE.classId)
339-
return UtAssembleModel(addr, wrapper.type.classId, modelName, instantiationChain, modificationsChain)
340-
.apply {
341-
instantiationChain += UtExecutableCallModel(
342-
instance = null,
343-
constructorId,
344-
listOf(stringModel)
345-
)
346-
}
332+
val instantiationChain = UtExecutableCallModel(
333+
instance = null,
334+
constructorId,
335+
listOf(stringModel)
336+
)
337+
return UtAssembleModel(addr, wrapper.type.classId, modelName, instantiationChain)
347338
}
348339

349340
private val SootClass.valueField: SootField

utbot-framework/src/main/kotlin/org/utbot/engine/ValueConstructor.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ class ValueConstructor {
328328
private fun constructFromAssembleModel(assembleModel: UtAssembleModel): Any {
329329
constructedObjects[assembleModel]?.let { return it }
330330

331-
val instantiationExecutableCall = assembleModel.instantiationChain.single() as UtExecutableCallModel
331+
val instantiationExecutableCall = assembleModel.instantiationCall
332332
val result = updateWithExecutableCallModel(instantiationExecutableCall)
333333
checkNotNull(result) {
334334
"Tracked instance can't be null for call ${instantiationExecutableCall.executable} in model $assembleModel"

utbot-framework/src/main/kotlin/org/utbot/framework/assemble/AssembleModelGenerator.kt

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -234,24 +234,20 @@ class AssembleModelGenerator(private val methodPackageName: String) {
234234
try {
235235
val modelName = nextModelName(compositeModel.classId.jClass.simpleName.decapitalize())
236236

237-
val instantiationChain = mutableListOf<UtStatementModel>()
238-
val modificationsChain = mutableListOf<UtStatementModel>()
237+
val constructorId = findBestConstructorOrNull(compositeModel)
238+
?: throw AssembleException("No default constructor to instantiate an object of the class ${compositeModel.id}")
239+
240+
val constructorInfo = constructorAnalyzer.analyze(constructorId)
241+
242+
val instantiationCall = constructorCall(compositeModel, constructorInfo)
239243
return UtAssembleModel(
240244
compositeModel.id,
241245
compositeModel.classId,
242246
modelName,
243-
instantiationChain,
244-
modificationsChain,
247+
instantiationCall,
245248
compositeModel
246-
).apply {
247-
248-
val constructorId = findBestConstructorOrNull(compositeModel)
249-
?: throw AssembleException("No default constructor to instantiate an object of the class $classId")
250-
251-
val constructorInfo = constructorAnalyzer.analyze(constructorId)
252-
249+
) {
253250
instantiatedModels[compositeModel] = this
254-
instantiationChain += constructorCall(compositeModel, constructorInfo)
255251

256252
compositeModel.fields.forEach { (fieldId, fieldModel) ->
257253
if (fieldId.isStatic) {
@@ -274,7 +270,7 @@ class AssembleModelGenerator(private val methodPackageName: String) {
274270
}
275271
}
276272

277-
modificationsChain += callChain.toList()
273+
callChain.toList()
278274
}
279275
} catch (e: AssembleException) {
280276
instantiatedModels.remove(compositeModel)
@@ -288,28 +284,39 @@ class AssembleModelGenerator(private val methodPackageName: String) {
288284
private fun assembleAssembleModel(modelBefore: UtAssembleModel): UtModel {
289285
instantiatedModels[modelBefore]?.let { return it }
290286

291-
val instantiationChain = mutableListOf<UtStatementModel>()
292-
val modificationChain = mutableListOf<UtStatementModel>()
293287

294-
return modelBefore.copy(
295-
instantiationChain = instantiationChain,
296-
modificationsChain = modificationChain,
288+
return UtAssembleModel(
289+
modelBefore.id,
290+
modelBefore.classId,
291+
modelBefore.modelName,
292+
assembleExecutableCallModel(modelBefore.instantiationCall),
293+
modelBefore.origin
297294
).apply {
298295
instantiatedModels[modelBefore] = this
299-
300-
instantiationChain += modelBefore.instantiationChain.map { assembleStatementModel(it) }
301-
modificationChain += modelBefore.modificationsChain.map { assembleStatementModel(it) }
296+
modelBefore.modificationsChain.map { assembleStatementModel(it) }
302297
}
303298
}
304299

305300
/**
306301
* Assembles internal structure of [UtStatementModel].
307302
*/
308303
private fun assembleStatementModel(statementModel: UtStatementModel): UtStatementModel = when (statementModel) {
309-
is UtExecutableCallModel -> statementModel.copy(params = statementModel.params.map { assembleModel(it) })
310-
is UtDirectSetFieldModel -> statementModel.copy(fieldModel = assembleModel(statementModel.fieldModel))
304+
is UtExecutableCallModel -> assembleExecutableCallModel(statementModel)
305+
is UtDirectSetFieldModel -> assembleDirectSetFieldModel(statementModel)
311306
}
312307

308+
private fun assembleDirectSetFieldModel(statementModel: UtDirectSetFieldModel) =
309+
statementModel.copy(
310+
instance = statementModel.instance.let { assembleModel(it) as UtReferenceModel },
311+
fieldModel = assembleModel(statementModel.fieldModel)
312+
)
313+
314+
private fun assembleExecutableCallModel(statementModel: UtExecutableCallModel) =
315+
statementModel.copy(
316+
instance = statementModel.instance?.let { assembleModel(it) as UtReferenceModel },
317+
params = statementModel.params.map { assembleModel(it) }
318+
)
319+
313320
/**
314321
* Assembles internal structure of [UtCompositeModel] if it represents a mock.
315322
*/

utbot-framework/src/main/kotlin/org/utbot/framework/assemble/AssemblePrimitiveWrapper.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ fun assemble(model: UtPrimitiveModel): UtAssembleModel {
4343
id = null,
4444
classId = assembledModelType,
4545
modelName = modelType.canonicalName,
46-
instantiationChain = listOf(constructorCallModel),
47-
modificationsChain = emptyList(),
46+
instantiationCall = constructorCallModel,
4847
)
4948
}

0 commit comments

Comments
 (0)