Skip to content

Implement new approach to create variables in parametrized tests #547

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 20, 2022
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 @@ -610,10 +610,13 @@ val Type.classId: ClassId
* [elementClassId] if this class id represents an array class, then this property
* represents the class id of the array's elements. Otherwise, this property is null.
*/
open class ClassId(
open class ClassId @JvmOverloads constructor(
val name: String,
val elementClassId: ClassId? = null
val elementClassId: ClassId? = null,
// Treat simple class ids as non-nullable
open val isNullable: Boolean = false
) {

open val canonicalName: String
get() = jClass.canonicalName ?: error("ClassId $name does not have canonical name")

Expand Down Expand Up @@ -677,10 +680,6 @@ open class ClassId(
open val isSynthetic: Boolean
get() = jClass.isSynthetic

open val isNullable: Boolean
// Treat simple class ids as non-nullable
get() = false

/**
* Collects all declared methods (including private and protected) from class and all its superclasses to sequence
*/
Expand Down Expand Up @@ -755,6 +754,7 @@ class BuiltinClassId(
override val simpleName: String,
// by default we assume that the class is not a member class
override val simpleNameWithEnclosings: String = simpleName,
override val isNullable: Boolean = false,
override val isPublic: Boolean = true,
override val isProtected: Boolean = false,
override val isPrivate: Boolean = false,
Expand All @@ -774,7 +774,7 @@ class BuiltinClassId(
-1, 0 -> ""
else -> canonicalName.substring(0, index)
},
) : ClassId(name) {
) : ClassId(name = name, isNullable = isNullable) {
init {
BUILTIN_CLASSES_BY_NAMES[name] = this
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,21 @@ val idToPrimitive: Map<ClassId, Class<*>> = mapOf(
*/
fun isPrimitiveWrapperOrString(type: ClassId): Boolean = (type in primitiveWrappers) || (type == stringClassId)

/**
* Returns a wrapper of a given type if it is primitive or a type itself otherwise.
*/
fun wrapIfPrimitive(type: ClassId): ClassId = when (type) {
booleanClassId -> booleanWrapperClassId
byteClassId -> byteWrapperClassId
charClassId -> charWrapperClassId
shortClassId -> shortWrapperClassId
intClassId -> intWrapperClassId
longClassId -> longWrapperClassId
floatClassId -> floatWrapperClassId
doubleClassId -> doubleWrapperClassId
else -> type
}

/**
* Note: currently uses class$innerClass form to load classes with classloader.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package org.utbot.framework.assemble

import org.utbot.framework.plugin.api.UtAssembleModel
import org.utbot.framework.plugin.api.UtExecutableCallModel
import org.utbot.framework.plugin.api.UtPrimitiveModel
import org.utbot.framework.plugin.api.util.booleanClassId
import org.utbot.framework.plugin.api.util.byteClassId
import org.utbot.framework.plugin.api.util.charClassId
import org.utbot.framework.plugin.api.util.doubleClassId
import org.utbot.framework.plugin.api.util.executableId
import org.utbot.framework.plugin.api.util.floatClassId
import org.utbot.framework.plugin.api.util.intClassId
import org.utbot.framework.plugin.api.util.longClassId
import org.utbot.framework.plugin.api.util.shortClassId
import org.utbot.framework.plugin.api.util.wrapIfPrimitive

/**
* Creates [UtAssembleModel] of the wrapper for a given [UtPrimitiveModel].
*/
fun assemble(model: UtPrimitiveModel): UtAssembleModel {
val modelType = model.classId
val assembledModelType = wrapIfPrimitive(modelType)

val constructorCall = when (modelType) {
shortClassId -> java.lang.Short::class.java.getConstructor(Short::class.java)
intClassId -> java.lang.Integer::class.java.getConstructor(Int::class.java)
longClassId -> java.lang.Long::class.java.getConstructor(Long::class.java)
charClassId -> java.lang.Character::class.java.getConstructor(Char::class.java)
byteClassId -> java.lang.Byte::class.java.getConstructor(Byte::class.java)
booleanClassId -> java.lang.Boolean::class.java.getConstructor(Boolean::class.java)
floatClassId -> java.lang.Float::class.java.getConstructor(Float::class.java)
doubleClassId -> java.lang.Double::class.java.getConstructor(Double::class.java)
else -> error("Model type $modelType is void or non-primitive")
}

val constructorCallModel = UtExecutableCallModel(
instance = null,
executable = constructorCall.executableId,
params = listOf(model),
returnValue = null,
)

return UtAssembleModel(
id = null,
classId = assembledModelType,
modelName = modelType.canonicalName,
instantiationChain = listOf(constructorCallModel),
modificationsChain = emptyList(),
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.collections.immutable.persistentSetOf
import org.utbot.framework.codegen.model.constructor.builtin.streamsDeepEqualsMethodId
import org.utbot.framework.codegen.model.tree.CgParameterKind
import org.utbot.framework.plugin.api.util.executableId
import org.utbot.framework.plugin.api.util.id
import org.utbot.framework.plugin.api.util.isCheckedException
Expand All @@ -70,8 +71,8 @@ import org.utbot.framework.plugin.api.util.jClass
* For example, [currentTestClass] and [currentExecutable] can be reassigned
* when we start generating another method or test class
*
* [variables] and [existingVariableNames] are 'var' properties
* that can be reverted to their previous values on exit from a name scope
* [existingVariableNames] is a 'var' property
* that can be reverted to its previous value on exit from a name scope
*
* @see [CgContextOwner.withNameScope]
*/
Expand Down Expand Up @@ -155,9 +156,6 @@ internal interface CgContextOwner {
// variable names being used in the current name scope
var existingVariableNames: PersistentSet<String>

// all declared variables in the current name scope
var variables: PersistentSet<CgVariable>

// variables of java.lang.Class type declared in the current name scope
var declaredClassRefs: PersistentMap<ClassId, CgVariable>

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

// parameters of the method currently being generated
val currentMethodParameters: MutableMap<CgParameterKind, CgVariable>

val testClassCustomName: String?

/**
Expand Down Expand Up @@ -282,7 +283,6 @@ internal interface CgContextOwner {
}

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

fun <R> withNameScope(block: () -> R): R {
val prevVariableNames = existingVariableNames
val prevVariables = variables
val prevDeclaredClassRefs = declaredClassRefs
val prevDeclaredExecutableRefs = declaredExecutableRefs
val prevValueByModel = IdentityHashMap(valueByModel)
Expand All @@ -302,7 +301,6 @@ internal interface CgContextOwner {
block()
} finally {
existingVariableNames = prevVariableNames
variables = prevVariables
declaredClassRefs = prevDeclaredClassRefs
declaredExecutableRefs = prevDeclaredExecutableRefs
valueByModel = prevValueByModel
Expand Down Expand Up @@ -413,7 +411,6 @@ internal data class CgContext(
override var mockFrameworkUsed: Boolean = false,
override var currentBlock: PersistentList<CgStatement> = persistentListOf(),
override var existingVariableNames: PersistentSet<String> = persistentSetOf(),
override var variables: PersistentSet<CgVariable> = persistentSetOf(),
override var declaredClassRefs: PersistentMap<ClassId, CgVariable> = persistentMapOf(),
override var declaredExecutableRefs: PersistentMap<ExecutableId, CgVariable> = persistentMapOf(),
override var thisInstance: CgValue? = null,
Expand Down Expand Up @@ -454,5 +451,7 @@ internal data class CgContext(

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

override val currentMethodParameters: MutableMap<CgParameterKind, CgVariable> = mutableMapOf()

override val testClassThisInstance: CgThisInstance = CgThisInstance(currentTestClass)
}
Loading