Skip to content

Commit 82a83b7

Browse files
committed
Uncommit on 30.08
1 parent 6486329 commit 82a83b7

File tree

14 files changed

+639
-114
lines changed

14 files changed

+639
-114
lines changed

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,15 @@ class UtLambdaModel(
549549
val declaringClass: ClassId,
550550
val lambdaName: String,
551551
val capturedValues: MutableList<UtModel> = mutableListOf(),
552-
) : UtReferenceModel(id, samType)
552+
) : UtReferenceModel(id, samType) {
553+
554+
val lambdaMethodId: MethodId
555+
get() = declaringClass.jClass
556+
.declaredMethods
557+
.singleOrNull { it.name == lambdaName }
558+
?.executableId // synthetic lambda methods should not have overloads, so we always expect there to be only one method with the given name
559+
?: error("More than one method with name $lambdaName found in class: ${declaringClass.canonicalName}")
560+
}
553561

554562
/**
555563
* Model for a step to obtain [UtAssembleModel].

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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,10 @@ val classToWrapper: MutableMap<TypeToBeWrapped, WrapperType> =
7878
putSootClass(java.util.HashSet::class, UtHashSet::class)
7979
putSootClass(java.util.LinkedHashSet::class, UtHashSet::class)
8080

81-
putSootClass(java.util.Map::class, UtHashMap::class)
82-
putSootClass(java.util.AbstractMap::class, UtHashMap::class)
83-
putSootClass(java.util.LinkedHashMap::class, UtHashMap::class)
84-
putSootClass(java.util.HashMap::class, UtHashMap::class)
81+
// putSootClass(java.util.Map::class, UtHashMap::class)
82+
// putSootClass(java.util.AbstractMap::class, UtHashMap::class)
83+
// putSootClass(java.util.LinkedHashMap::class, UtHashMap::class)
84+
// putSootClass(java.util.HashMap::class, UtHashMap::class)
8585

8686
putSootClass(java.util.stream.BaseStream::class, UT_STREAM.className)
8787
putSootClass(java.util.stream.Stream::class, UT_STREAM.className)
@@ -178,10 +178,10 @@ private val wrappers = mapOf(
178178
objectValue(LINKED_HASH_SET_TYPE, addr, SetWrapper())
179179
},
180180
// map wrappers
181-
wrap(java.util.Map::class) { _, addr -> objectValue(LINKED_HASH_MAP_TYPE, addr, MapWrapper()) },
182-
wrap(java.util.AbstractMap::class) { _, addr -> objectValue(LINKED_HASH_MAP_TYPE, addr, MapWrapper()) },
183-
wrap(java.util.LinkedHashMap::class) { _, addr -> objectValue(LINKED_HASH_MAP_TYPE, addr, MapWrapper()) },
184-
wrap(java.util.HashMap::class) { _, addr -> objectValue(HASH_MAP_TYPE, addr, MapWrapper()) },
181+
// wrap(java.util.Map::class) { _, addr -> objectValue(LINKED_HASH_MAP_TYPE, addr, MapWrapper()) },
182+
// wrap(java.util.AbstractMap::class) { _, addr -> objectValue(LINKED_HASH_MAP_TYPE, addr, MapWrapper()) },
183+
// wrap(java.util.LinkedHashMap::class) { _, addr -> objectValue(LINKED_HASH_MAP_TYPE, addr, MapWrapper()) },
184+
// wrap(java.util.HashMap::class) { _, addr -> objectValue(HASH_MAP_TYPE, addr, MapWrapper()) },
185185

186186
// stream wrappers
187187
wrap(java.util.stream.BaseStream::class) { _, addr -> objectValue(STREAM_TYPE, addr, CommonStreamWrapper()) },

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,8 +189,8 @@ class ValueConstructor {
189189
is UtCompositeModel -> UtConcreteValue(constructObject(model), model.classId.jClass)
190190
is UtArrayModel -> UtConcreteValue(constructArray(model))
191191
is UtAssembleModel -> UtConcreteValue(constructFromAssembleModel(model))
192+
is UtLambdaModel -> UtConcreteValue(constructFromLambdaModel(model))
192193
is UtVoidModel -> UtConcreteValue(Unit)
193-
is UtLambdaModel -> TODO("lambda model")
194194
}
195195
}
196196

@@ -337,6 +337,10 @@ class ValueConstructor {
337337
?: error("Can't assemble model: $assembleModel")
338338
}
339339

340+
private fun constructFromLambdaModel(lambdaModel: UtLambdaModel): Any {
341+
TODO()
342+
}
343+
340344
/**
341345
* Updates instance state with [UtExecutableCallModel] invocation.
342346
*/
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package org.utbot.engine.util.lambda
2+
3+
import org.utbot.framework.plugin.api.UtLambdaModel
4+
5+
internal fun constructFromLambdaModel(model: UtLambdaModel): Any {
6+
val lambdaMethodId = model.lambdaMethodId
7+
8+
return if (lambdaMethodId.isStatic) {
9+
constructStaticLambda(model)
10+
} else {
11+
constructLambda(model)
12+
}
13+
}
14+
15+
private fun constructStaticLambda(model: UtLambdaModel): Any {
16+
TODO()
17+
}
18+
19+
private fun constructLambda(model: UtLambdaModel): Any {
20+
TODO()
21+
}

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/builtin/UtilMethodBuiltins.kt

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,14 @@ import org.utbot.framework.plugin.api.util.classClassId
1414
import org.utbot.framework.plugin.api.util.id
1515
import org.utbot.framework.plugin.api.util.intClassId
1616
import org.utbot.framework.plugin.api.util.jClass
17+
import org.utbot.framework.plugin.api.util.objectArrayClassId
1718
import org.utbot.framework.plugin.api.util.objectClassId
1819
import org.utbot.framework.plugin.api.util.stringClassId
1920
import org.utbot.framework.plugin.api.util.voidClassId
2021
import sun.misc.Unsafe
22+
import java.lang.invoke.MethodHandles
23+
import java.lang.invoke.MethodType
24+
import java.lang.reflect.Method
2125

2226
/**
2327
* Set of ids of all possible util methods for a given class
@@ -178,6 +182,42 @@ internal val ClassId.buildLambdaMethodId: MethodId
178182
)
179183
)
180184

185+
internal val ClassId.getLookupInMethodId: MethodId
186+
get() = utilMethodId(
187+
name = "getLookupIn",
188+
returnType = MethodHandles.Lookup::class.id,
189+
arguments = arrayOf(classClassId)
190+
)
191+
192+
internal val ClassId.getLambdaCapturedArgumentTypesMethodId: MethodId
193+
get() = utilMethodId(
194+
name = "getLambdaCapturedArgumentTypes",
195+
returnType = arrayTypeOf(classClassId),
196+
arguments = arrayOf(arrayTypeOf(capturedArgumentClassId))
197+
)
198+
199+
internal val ClassId.getLambdaCapturedArgumentValuesMethodId: MethodId
200+
get() = utilMethodId(
201+
name = "getLambdaCapturedArgumentValues",
202+
returnType = objectArrayClassId,
203+
arguments = arrayOf(arrayTypeOf(capturedArgumentClassId))
204+
)
205+
206+
internal val ClassId.getInstantiatedMethodTypeMethodId: MethodId
207+
get() = utilMethodId(
208+
name = "getInstantiatedMethodType",
209+
returnType = MethodType::class.id,
210+
arguments = arrayOf(Method::class.id, arrayTypeOf(classClassId))
211+
)
212+
213+
internal val ClassId.getLambdaMethodMethodId: MethodId
214+
get() = utilMethodId(
215+
name = "getLambdaMethod",
216+
returnType = Method::class.id,
217+
arguments = arrayOf(classClassId, stringClassId)
218+
)
219+
220+
181221
internal val ClassId.getSingleAbstractMethodMethodId: MethodId
182222
get() = utilMethodId(
183223
name = "getSingleAbstractMethod",

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

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ import org.utbot.framework.codegen.model.constructor.TestClassContext
4545
import org.utbot.framework.codegen.model.constructor.TestClassModel
4646
import org.utbot.framework.codegen.model.constructor.builtin.buildLambdaMethodId
4747
import org.utbot.framework.codegen.model.constructor.builtin.buildStaticLambdaMethodId
48+
import org.utbot.framework.codegen.model.constructor.builtin.capturedArgumentClassId
49+
import org.utbot.framework.codegen.model.constructor.builtin.getInstantiatedMethodTypeMethodId
50+
import org.utbot.framework.codegen.model.constructor.builtin.getLambdaCapturedArgumentTypesMethodId
51+
import org.utbot.framework.codegen.model.constructor.builtin.getLambdaCapturedArgumentValuesMethodId
52+
import org.utbot.framework.codegen.model.constructor.builtin.getLambdaMethodMethodId
53+
import org.utbot.framework.codegen.model.constructor.builtin.getLookupInMethodId
4854
import org.utbot.framework.codegen.model.constructor.builtin.getSingleAbstractMethodMethodId
4955
import org.utbot.framework.codegen.model.constructor.builtin.streamsDeepEqualsMethodId
5056
import org.utbot.framework.codegen.model.tree.CgParameterKind
@@ -339,7 +345,10 @@ internal interface CgContextOwner {
339345

340346
val testClassThisInstance: CgThisInstance
341347

342-
// util methods of current test class
348+
// util methods and auxiliary classes of current test class
349+
350+
val capturedArgumentClass: ClassId
351+
get() = outerMostTestClass.capturedArgumentClassId
343352

344353
val getUnsafeInstance: MethodId
345354
get() = outerMostTestClass.getUnsafeInstanceMethodId
@@ -392,8 +401,23 @@ internal interface CgContextOwner {
392401
val buildLambda: MethodId
393402
get() = outerMostTestClass.buildLambdaMethodId
394403

404+
val getLookupIn: MethodId
405+
get() = outerMostTestClass.getLookupInMethodId
406+
395407
val getSingleAbstractMethod: MethodId
396408
get() = outerMostTestClass.getSingleAbstractMethodMethodId
409+
410+
val getLambdaCapturedArgumentTypes: MethodId
411+
get() = outerMostTestClass.getLambdaCapturedArgumentTypesMethodId
412+
413+
val getLambdaCapturedArgumentValues: MethodId
414+
get() = outerMostTestClass.getLambdaCapturedArgumentValuesMethodId
415+
416+
val getInstantiatedMethodType: MethodId
417+
get() = outerMostTestClass.getInstantiatedMethodTypeMethodId
418+
419+
val getLambdaMethod: MethodId
420+
get() = outerMostTestClass.getLambdaMethodMethodId
397421
}
398422

399423
/**

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgCallableAccessManager.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,15 @@ import org.utbot.framework.codegen.model.constructor.builtin.createInstanceMetho
1313
import org.utbot.framework.codegen.model.constructor.builtin.deepEqualsMethodId
1414
import org.utbot.framework.codegen.model.constructor.builtin.forName
1515
import org.utbot.framework.codegen.model.constructor.builtin.getArrayLengthMethodId
16+
import org.utbot.framework.codegen.model.constructor.builtin.getLambdaCapturedArgumentValuesMethodId
1617
import org.utbot.framework.codegen.model.constructor.builtin.getDeclaredConstructor
1718
import org.utbot.framework.codegen.model.constructor.builtin.getDeclaredMethod
1819
import org.utbot.framework.codegen.model.constructor.builtin.getEnumConstantByNameMethodId
1920
import org.utbot.framework.codegen.model.constructor.builtin.getFieldValueMethodId
21+
import org.utbot.framework.codegen.model.constructor.builtin.getInstantiatedMethodTypeMethodId
22+
import org.utbot.framework.codegen.model.constructor.builtin.getLambdaCapturedArgumentTypesMethodId
23+
import org.utbot.framework.codegen.model.constructor.builtin.getLambdaMethodMethodId
24+
import org.utbot.framework.codegen.model.constructor.builtin.getLookupInMethodId
2025
import org.utbot.framework.codegen.model.constructor.builtin.getSingleAbstractMethodMethodId
2126
import org.utbot.framework.codegen.model.constructor.builtin.getStaticFieldValueMethodId
2227
import org.utbot.framework.codegen.model.constructor.builtin.getTargetException
@@ -200,9 +205,14 @@ internal class CgCallableAccessManagerImpl(val context: CgContext) : CgCallableA
200205
mapsDeepEqualsMethodId,
201206
hasCustomEqualsMethodId,
202207
getArrayLengthMethodId,
208+
getLambdaCapturedArgumentTypesMethodId,
209+
getLambdaCapturedArgumentValuesMethodId,
210+
getInstantiatedMethodTypeMethodId,
211+
getLambdaMethodMethodId,
203212
getSingleAbstractMethodMethodId -> emptySet()
204-
buildStaticLambdaMethodId -> setOf(Throwable::class.id)
213+
buildStaticLambdaMethodId,
205214
buildLambdaMethodId -> setOf(Throwable::class.id)
215+
getLookupInMethodId ->setOf(IllegalAccessException::class.id, NoSuchFieldException::class.id)
206216
else -> error("Unknown util method ${this@findExceptionTypes}")
207217
}
208218
}

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgTestClassConstructor.kt

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ import org.utbot.framework.plugin.api.ExecutableId
2929
import org.utbot.framework.plugin.api.MethodId
3030
import org.utbot.framework.plugin.api.UtMethodTestSet
3131
import org.utbot.framework.codegen.model.constructor.TestClassModel
32+
import org.utbot.framework.codegen.model.tree.CgAuxiliaryClass
33+
import org.utbot.framework.codegen.model.tree.CgUtilEntity
34+
import org.utbot.framework.plugin.api.ClassId
3235
import org.utbot.framework.plugin.api.util.description
3336
import org.utbot.framework.plugin.api.util.kClass
3437
import kotlin.reflect.KClass
@@ -91,16 +94,16 @@ internal class CgTestClassConstructor(val context: CgContext) :
9194
testMethodRegions += executableUnderTestCluster
9295
}
9396

94-
val utilMethods = if (currentTestClass == outerMostTestClass)
95-
createUtilMethods()
97+
val utilEntities = if (currentTestClass == outerMostTestClass)
98+
createUtilEntities()
9699
else
97100
emptyList()
98101

99-
val additionalMethods = currentTestClassContext.cgDataProviderMethods + utilMethods
102+
val dataProviders = currentTestClassContext.cgDataProviderMethods
100103

101104
dataProvidersAndUtilMethodsRegion += CgStaticsRegion(
102-
"Data providers and utils methods",
103-
additionalMethods
105+
"Data providers and util methods",
106+
dataProviders + utilEntities
104107
)
105108
}
106109
// It is important that annotations, superclass and interfaces assignment is run after
@@ -196,33 +199,47 @@ internal class CgTestClassConstructor(val context: CgContext) :
196199
}
197200

198201
// TODO: collect imports of util methods
199-
private fun createUtilMethods(): List<CgUtilMethod> {
202+
private fun createUtilEntities(): List<CgUtilEntity> {
200203
val utilMethods = mutableListOf<CgUtilMethod>()
201-
// some util methods depend on the others
202-
// using this loop we make sure that all the
203-
// util methods dependencies are taken into account
204+
// Some util methods depend on other util methods or some auxiliary classes.
205+
// Using this loop we make sure that all the util method dependencies are taken into account.
206+
val requiredClasses = mutableSetOf<ClassId>()
204207
while (requiredUtilMethods.isNotEmpty()) {
205208
val method = requiredUtilMethods.first()
206209
requiredUtilMethods.remove(method)
207210
if (method.name !in existingMethodNames) {
208211
utilMethods += CgUtilMethod(method)
209212
importUtilMethodDependencies(method)
210213
existingMethodNames += method.name
211-
requiredUtilMethods += method.dependencies()
214+
requiredUtilMethods += method.methodDependencies()
215+
requiredClasses += method.classDependencies()
212216
}
213217
}
214-
return utilMethods
218+
val auxiliaryClasses = requiredClasses.map { CgAuxiliaryClass(it) }
219+
return utilMethods + auxiliaryClasses
215220
}
216221

217222
/**
218223
* If @receiver is an util method, then returns a list of util method ids that @receiver depends on
219224
* Otherwise, an empty list is returned
220225
*/
221-
private fun MethodId.dependencies(): List<MethodId> = when (this) {
226+
private fun MethodId.methodDependencies(): List<MethodId> = when (this) {
222227
createInstance -> listOf(getUnsafeInstance)
223228
deepEquals -> listOf(arraysDeepEquals, iterablesDeepEquals, streamsDeepEquals, mapsDeepEquals, hasCustomEquals)
224229
arraysDeepEquals, iterablesDeepEquals, streamsDeepEquals, mapsDeepEquals -> listOf(deepEquals)
225-
buildLambda, buildStaticLambda -> listOf(getSingleAbstractMethod) // TODO: check this dependency when the lambdas support is complete, maybe something will change
230+
buildLambda, buildStaticLambda -> listOf(
231+
getLookupIn, getSingleAbstractMethod, getLambdaMethod,
232+
getLambdaCapturedArgumentTypes, getInstantiatedMethodType, getLambdaCapturedArgumentValues
233+
)
234+
else -> emptyList()
235+
}
236+
237+
/**
238+
* If @receiver is an util method, then returns a list of auxiliary class ids that @receiver depends on.
239+
* Otherwise, an empty list is returned.
240+
*/
241+
private fun MethodId.classDependencies(): List<ClassId> = when (this) {
242+
buildLambda, buildStaticLambda -> listOf(capturedArgumentClass)
226243
else -> emptyList()
227244
}
228245

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

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -121,14 +121,7 @@ internal class CgVariableConstructor(val context: CgContext) :
121121
}
122122

123123
private fun constructLambda(model: UtLambdaModel, baseName: String): CgVariable {
124-
val lambdaDeclaringClass = model.declaringClass
125-
val lambdaMethodId = lambdaDeclaringClass.jClass
126-
.declaredMethods
127-
.singleOrNull { it.name == model.lambdaName }
128-
?.executableId
129-
// synthetic lambda methods should not have overloads, so we always expect there to be only one method with the given name
130-
?: error("More than one method with name ${model.lambdaName} found in class: ${lambdaDeclaringClass.canonicalName}")
131-
124+
val lambdaMethodId = model.lambdaMethodId
132125
val capturedValues = model.capturedValues
133126
return newVar(model.samType, baseName) {
134127
if (lambdaMethodId.isStatic) {

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ interface CgElement {
3838
is CgSimpleRegion<*> -> visit(element)
3939
is CgTestMethodCluster -> visit(element)
4040
is CgExecutableUnderTestCluster -> visit(element)
41+
is CgAuxiliaryClass -> visit(element)
4142
is CgUtilMethod -> visit(element)
4243
is CgTestMethod -> visit(element)
4344
is CgCustomMethod -> visit(element)
@@ -177,6 +178,10 @@ data class CgExecutableUnderTestCluster(
177178
override val content: List<CgRegion<CgMethod>>
178179
) : CgRegion<CgRegion<CgMethod>>()
179180

181+
sealed class CgUtilEntity : CgElement
182+
183+
data class CgAuxiliaryClass(val id: ClassId) : CgUtilEntity()
184+
180185
/**
181186
* This class does not inherit from [CgMethod], because it only needs an [id],
182187
* and it does not need to have info about all the other properties of [CgMethod].
@@ -185,7 +190,7 @@ data class CgExecutableUnderTestCluster(
185190
*
186191
* [id] identifier of the util method.
187192
*/
188-
data class CgUtilMethod(val id: MethodId) : CgElement
193+
data class CgUtilMethod(val id: MethodId) : CgUtilEntity()
189194

190195
// Methods
191196

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/visitor/CgAbstractRenderer.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import org.utbot.framework.codegen.model.tree.CgAbstractFieldAccess
1111
import org.utbot.framework.codegen.model.tree.CgAbstractMultilineComment
1212
import org.utbot.framework.codegen.model.tree.CgArrayElementAccess
1313
import org.utbot.framework.codegen.model.tree.CgAssignment
14+
import org.utbot.framework.codegen.model.tree.CgAuxiliaryClass
1415
import org.utbot.framework.codegen.model.tree.CgBreakStatement
1516
import org.utbot.framework.codegen.model.tree.CgComment
1617
import org.utbot.framework.codegen.model.tree.CgCommentedAnnotation
@@ -196,6 +197,13 @@ internal abstract class CgAbstractRenderer(val context: CgContext, val printer:
196197
println(regionEnd)
197198
}
198199

200+
override fun visit(element: CgAuxiliaryClass) {
201+
context.outerMostTestClass
202+
.auxiliaryClassById(element.id, context)
203+
.split("\n")
204+
.forEach { line -> println(line) }
205+
}
206+
199207
override fun visit(element: CgUtilMethod) {
200208
context.outerMostTestClass
201209
.utilMethodById(element.id, context)

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/visitor/CgKotlinRenderer.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ internal class CgKotlinRenderer(context: CgContext, printer: CgPrinter = CgPrint
469469
else -> {
470470
// we cannot access kClass for BuiltinClassId
471471
// we cannot use simple name here because this class can be not imported
472-
if (id is BuiltinClassId) id.name else id.kClass.id.asString()
472+
if (id is BuiltinClassId) id.canonicalName else id.kClass.id.asString()
473473
}
474474
}
475475
}

0 commit comments

Comments
 (0)