Skip to content

Commit 74e7a34

Browse files
Implement new approach to create variables in parametrized tests #562 (#547)
1 parent 6922b0c commit 74e7a34

File tree

13 files changed

+301
-185
lines changed

13 files changed

+301
-185
lines changed

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -610,10 +610,13 @@ val Type.classId: ClassId
610610
* [elementClassId] if this class id represents an array class, then this property
611611
* represents the class id of the array's elements. Otherwise, this property is null.
612612
*/
613-
open class ClassId(
613+
open class ClassId @JvmOverloads constructor(
614614
val name: String,
615-
val elementClassId: ClassId? = null
615+
val elementClassId: ClassId? = null,
616+
// Treat simple class ids as non-nullable
617+
open val isNullable: Boolean = false
616618
) {
619+
617620
open val canonicalName: String
618621
get() = jClass.canonicalName ?: error("ClassId $name does not have canonical name")
619622

@@ -677,10 +680,6 @@ open class ClassId(
677680
open val isSynthetic: Boolean
678681
get() = jClass.isSynthetic
679682

680-
open val isNullable: Boolean
681-
// Treat simple class ids as non-nullable
682-
get() = false
683-
684683
/**
685684
* Collects all declared methods (including private and protected) from class and all its superclasses to sequence
686685
*/
@@ -755,6 +754,7 @@ class BuiltinClassId(
755754
override val simpleName: String,
756755
// by default we assume that the class is not a member class
757756
override val simpleNameWithEnclosings: String = simpleName,
757+
override val isNullable: Boolean = false,
758758
override val isPublic: Boolean = true,
759759
override val isProtected: Boolean = false,
760760
override val isPrivate: Boolean = false,
@@ -774,7 +774,7 @@ class BuiltinClassId(
774774
-1, 0 -> ""
775775
else -> canonicalName.substring(0, index)
776776
},
777-
) : ClassId(name) {
777+
) : ClassId(name = name, isNullable = isNullable) {
778778
init {
779779
BUILTIN_CLASSES_BY_NAMES[name] = this
780780
}

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,21 @@ val idToPrimitive: Map<ClassId, Class<*>> = mapOf(
236236
*/
237237
fun isPrimitiveWrapperOrString(type: ClassId): Boolean = (type in primitiveWrappers) || (type == stringClassId)
238238

239+
/**
240+
* Returns a wrapper of a given type if it is primitive or a type itself otherwise.
241+
*/
242+
fun wrapIfPrimitive(type: ClassId): ClassId = when (type) {
243+
booleanClassId -> booleanWrapperClassId
244+
byteClassId -> byteWrapperClassId
245+
charClassId -> charWrapperClassId
246+
shortClassId -> shortWrapperClassId
247+
intClassId -> intWrapperClassId
248+
longClassId -> longWrapperClassId
249+
floatClassId -> floatWrapperClassId
250+
doubleClassId -> doubleWrapperClassId
251+
else -> type
252+
}
253+
239254
/**
240255
* Note: currently uses class$innerClass form to load classes with classloader.
241256
*/
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package org.utbot.framework.assemble
2+
3+
import org.utbot.framework.plugin.api.UtAssembleModel
4+
import org.utbot.framework.plugin.api.UtExecutableCallModel
5+
import org.utbot.framework.plugin.api.UtPrimitiveModel
6+
import org.utbot.framework.plugin.api.util.booleanClassId
7+
import org.utbot.framework.plugin.api.util.byteClassId
8+
import org.utbot.framework.plugin.api.util.charClassId
9+
import org.utbot.framework.plugin.api.util.doubleClassId
10+
import org.utbot.framework.plugin.api.util.executableId
11+
import org.utbot.framework.plugin.api.util.floatClassId
12+
import org.utbot.framework.plugin.api.util.intClassId
13+
import org.utbot.framework.plugin.api.util.longClassId
14+
import org.utbot.framework.plugin.api.util.shortClassId
15+
import org.utbot.framework.plugin.api.util.wrapIfPrimitive
16+
17+
/**
18+
* Creates [UtAssembleModel] of the wrapper for a given [UtPrimitiveModel].
19+
*/
20+
fun assemble(model: UtPrimitiveModel): UtAssembleModel {
21+
val modelType = model.classId
22+
val assembledModelType = wrapIfPrimitive(modelType)
23+
24+
val constructorCall = when (modelType) {
25+
shortClassId -> java.lang.Short::class.java.getConstructor(Short::class.java)
26+
intClassId -> java.lang.Integer::class.java.getConstructor(Int::class.java)
27+
longClassId -> java.lang.Long::class.java.getConstructor(Long::class.java)
28+
charClassId -> java.lang.Character::class.java.getConstructor(Char::class.java)
29+
byteClassId -> java.lang.Byte::class.java.getConstructor(Byte::class.java)
30+
booleanClassId -> java.lang.Boolean::class.java.getConstructor(Boolean::class.java)
31+
floatClassId -> java.lang.Float::class.java.getConstructor(Float::class.java)
32+
doubleClassId -> java.lang.Double::class.java.getConstructor(Double::class.java)
33+
else -> error("Model type $modelType is void or non-primitive")
34+
}
35+
36+
val constructorCallModel = UtExecutableCallModel(
37+
instance = null,
38+
executable = constructorCall.executableId,
39+
params = listOf(model),
40+
returnValue = null,
41+
)
42+
43+
return UtAssembleModel(
44+
id = null,
45+
classId = assembledModelType,
46+
modelName = modelType.canonicalName,
47+
instantiationChain = listOf(constructorCallModel),
48+
modificationsChain = emptyList(),
49+
)
50+
}

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/context/CgContext.kt

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ import kotlinx.collections.immutable.persistentListOf
5454
import kotlinx.collections.immutable.persistentMapOf
5555
import kotlinx.collections.immutable.persistentSetOf
5656
import org.utbot.framework.codegen.model.constructor.builtin.streamsDeepEqualsMethodId
57+
import org.utbot.framework.codegen.model.tree.CgParameterKind
5758
import org.utbot.framework.plugin.api.util.executableId
5859
import org.utbot.framework.plugin.api.util.id
5960
import org.utbot.framework.plugin.api.util.isCheckedException
@@ -70,8 +71,8 @@ import org.utbot.framework.plugin.api.util.jClass
7071
* For example, [currentTestClass] and [currentExecutable] can be reassigned
7172
* when we start generating another method or test class
7273
*
73-
* [variables] and [existingVariableNames] are 'var' properties
74-
* that can be reverted to their previous values on exit from a name scope
74+
* [existingVariableNames] is a 'var' property
75+
* that can be reverted to its previous value on exit from a name scope
7576
*
7677
* @see [CgContextOwner.withNameScope]
7778
*/
@@ -155,9 +156,6 @@ internal interface CgContextOwner {
155156
// variable names being used in the current name scope
156157
var existingVariableNames: PersistentSet<String>
157158

158-
// all declared variables in the current name scope
159-
var variables: PersistentSet<CgVariable>
160-
161159
// variables of java.lang.Class type declared in the current name scope
162160
var declaredClassRefs: PersistentMap<ClassId, CgVariable>
163161

@@ -190,6 +188,9 @@ internal interface CgContextOwner {
190188
// use it to compare stateBefore and result variables - in case of equality do not create new variable
191189
var valueByModelId: MutableMap<Int?, CgValue>
192190

191+
// parameters of the method currently being generated
192+
val currentMethodParameters: MutableMap<CgParameterKind, CgVariable>
193+
193194
val testClassCustomName: String?
194195

195196
/**
@@ -282,7 +283,6 @@ internal interface CgContextOwner {
282283
}
283284

284285
fun updateVariableScope(variable: CgVariable, model: UtModel? = null) {
285-
variables = variables.add(variable)
286286
model?.let {
287287
valueByModel[it] = variable
288288
(model as UtReferenceModel).let { refModel ->
@@ -293,7 +293,6 @@ internal interface CgContextOwner {
293293

294294
fun <R> withNameScope(block: () -> R): R {
295295
val prevVariableNames = existingVariableNames
296-
val prevVariables = variables
297296
val prevDeclaredClassRefs = declaredClassRefs
298297
val prevDeclaredExecutableRefs = declaredExecutableRefs
299298
val prevValueByModel = IdentityHashMap(valueByModel)
@@ -302,7 +301,6 @@ internal interface CgContextOwner {
302301
block()
303302
} finally {
304303
existingVariableNames = prevVariableNames
305-
variables = prevVariables
306304
declaredClassRefs = prevDeclaredClassRefs
307305
declaredExecutableRefs = prevDeclaredExecutableRefs
308306
valueByModel = prevValueByModel
@@ -413,7 +411,6 @@ internal data class CgContext(
413411
override var mockFrameworkUsed: Boolean = false,
414412
override var currentBlock: PersistentList<CgStatement> = persistentListOf(),
415413
override var existingVariableNames: PersistentSet<String> = persistentSetOf(),
416-
override var variables: PersistentSet<CgVariable> = persistentSetOf(),
417414
override var declaredClassRefs: PersistentMap<ClassId, CgVariable> = persistentMapOf(),
418415
override var declaredExecutableRefs: PersistentMap<ExecutableId, CgVariable> = persistentMapOf(),
419416
override var thisInstance: CgValue? = null,
@@ -454,5 +451,7 @@ internal data class CgContext(
454451

455452
override var valueByModelId: MutableMap<Int?, CgValue> = mutableMapOf()
456453

454+
override val currentMethodParameters: MutableMap<CgParameterKind, CgVariable> = mutableMapOf()
455+
457456
override val testClassThisInstance: CgThisInstance = CgThisInstance(currentTestClass)
458457
}

0 commit comments

Comments
 (0)