Skip to content

Commit 5961d80

Browse files
IlyaMuravjovEgorkaKulikov
authored andcommitted
Introduce UtilMethodProviderPlaceholder (#2717)
1 parent a7ce884 commit 5961d80

File tree

5 files changed

+201
-59
lines changed

5 files changed

+201
-59
lines changed

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

Lines changed: 123 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ import kotlin.contracts.contract
5757
import org.utbot.common.isAbstract
5858
import org.utbot.framework.plugin.api.mapper.UtModelMapper
5959
import org.utbot.framework.plugin.api.mapper.map
60+
import org.utbot.framework.plugin.api.mapper.mapModelIfExists
61+
import org.utbot.framework.plugin.api.mapper.mapModels
6062
import org.utbot.framework.plugin.api.mapper.mapPreservingType
6163
import org.utbot.framework.plugin.api.util.SpringModelUtils
6264
import org.utbot.framework.process.OpenModulesContainer
@@ -73,6 +75,11 @@ data class UtMethodTestSet(
7375
val clustersInfo: List<Pair<UtClusterInfo?, IntRange>> = listOf(null to executions.indices)
7476
)
7577

78+
fun UtMethodTestSet.mapModels(mapper: UtModelMapper): UtMethodTestSet =
79+
copy(executions = executions.map { it.mapModels(mapper) })
80+
81+
fun Collection<UtMethodTestSet>.mapModels(mapper: UtModelMapper) = map { it.mapModels(mapper) }
82+
7683
data class Step(
7784
val stmt: Stmt,
7885
val depth: Int,
@@ -145,11 +152,70 @@ abstract class UtExecution(
145152
displayName: String? = this.displayName,
146153
): UtExecution
147154

155+
open fun mapModels(mapper: UtModelMapper) = copy(
156+
stateBefore = stateBefore.mapModels(mapper),
157+
stateAfter = stateAfter.mapModels(mapper),
158+
result = result.mapModelIfExists(mapper)
159+
)
160+
148161
val executableToCall get() = stateBefore.executableToCall
149162
}
150163

151-
interface UtExecutionWithInstrumentation {
152-
val instrumentation: List<UtInstrumentation>
164+
abstract class UtExecutionWithInstrumentation(
165+
stateBefore: EnvironmentModels,
166+
stateAfter: EnvironmentModels,
167+
result: UtExecutionResult,
168+
coverage: Coverage? = null,
169+
summary: List<DocStatement>? = null,
170+
testMethodName: String? = null,
171+
displayName: String? = null,
172+
val instrumentation: List<UtInstrumentation>,
173+
) : UtExecution(
174+
stateBefore = stateBefore,
175+
stateAfter = stateAfter,
176+
result = result,
177+
coverage = coverage,
178+
summary = summary,
179+
testMethodName = testMethodName,
180+
displayName = displayName,
181+
) {
182+
abstract fun copy(
183+
stateBefore: EnvironmentModels = this.stateBefore,
184+
stateAfter: EnvironmentModels = this.stateAfter,
185+
result: UtExecutionResult = this.result,
186+
coverage: Coverage? = this.coverage,
187+
summary: List<DocStatement>? = this.summary,
188+
testMethodName: String? = this.testMethodName,
189+
displayName: String? = this.displayName,
190+
instrumentation: List<UtInstrumentation> = this.instrumentation,
191+
): UtExecution
192+
193+
override fun copy(
194+
stateBefore: EnvironmentModels,
195+
stateAfter: EnvironmentModels,
196+
result: UtExecutionResult,
197+
coverage: Coverage?,
198+
summary: List<DocStatement>?,
199+
testMethodName: String?,
200+
displayName: String?,
201+
): UtExecution = copy(
202+
stateBefore = stateBefore,
203+
stateAfter = stateAfter,
204+
result = result,
205+
instrumentation = instrumentation,
206+
coverage = coverage,
207+
summary = summary,
208+
testMethodName = testMethodName,
209+
displayName = displayName,
210+
)
211+
212+
override fun mapModels(mapper: UtModelMapper): UtExecution =
213+
copy(
214+
stateBefore = stateBefore.mapModels(mapper),
215+
stateAfter = stateAfter.mapModels(mapper),
216+
result = result.mapModelIfExists(mapper),
217+
instrumentation = instrumentation.map { it.mapModels(mapper) },
218+
)
153219
}
154220

155221
/**
@@ -167,15 +233,24 @@ class UtSymbolicExecution(
167233
stateBefore: EnvironmentModels,
168234
stateAfter: EnvironmentModels,
169235
result: UtExecutionResult,
170-
override val instrumentation: List<UtInstrumentation>,
236+
instrumentation: List<UtInstrumentation>,
171237
val path: MutableList<Step>,
172238
val fullPath: List<Step>,
173239
coverage: Coverage? = null,
174240
summary: List<DocStatement>? = null,
175241
testMethodName: String? = null,
176242
displayName: String? = null,
177243
/** Convenient view of the full symbolic path */ val symbolicSteps: List<SymbolicStep> = listOf(),
178-
) : UtExecution(stateBefore, stateAfter, result, coverage, summary, testMethodName, displayName), UtExecutionWithInstrumentation {
244+
) : UtExecutionWithInstrumentation(
245+
stateBefore,
246+
stateAfter,
247+
result,
248+
coverage,
249+
summary,
250+
testMethodName,
251+
displayName,
252+
instrumentation
253+
) {
179254
/**
180255
* By design the 'before' and 'after' states contain info about the same fields.
181256
* It means that it is not possible for a field to be present at 'before' and to be absent at 'after'.
@@ -193,7 +268,8 @@ class UtSymbolicExecution(
193268
coverage: Coverage?,
194269
summary: List<DocStatement>?,
195270
testMethodName: String?,
196-
displayName: String?
271+
displayName: String?,
272+
instrumentation: List<UtInstrumentation>,
197273
): UtExecution = UtSymbolicExecution(
198274
stateBefore = stateBefore,
199275
stateAfter = stateAfter,
@@ -1369,19 +1445,49 @@ class BuiltinMethodId(
13691445
name: String,
13701446
returnType: ClassId,
13711447
parameters: List<ClassId>,
1372-
bypassesSandbox: Boolean = false,
1373-
// by default we assume that the builtin method is non-static and public
1374-
isStatic: Boolean = false,
1375-
isPublic: Boolean = true,
1376-
isProtected: Boolean = false,
1377-
isPrivate: Boolean = false
1448+
bypassesSandbox: Boolean,
1449+
override val modifiers: Int,
13781450
) : MethodId(classId, name, returnType, parameters, bypassesSandbox) {
1379-
override val modifiers: Int = ModifierFactory {
1380-
static = isStatic
1381-
public = isPublic
1382-
private = isPrivate
1383-
protected = isProtected
1384-
}
1451+
constructor(
1452+
classId: ClassId,
1453+
name: String,
1454+
returnType: ClassId,
1455+
parameters: List<ClassId>,
1456+
bypassesSandbox: Boolean = false,
1457+
// by default, we assume that the builtin method is non-static and public
1458+
isStatic: Boolean = false,
1459+
isPublic: Boolean = true,
1460+
isProtected: Boolean = false,
1461+
isPrivate: Boolean = false
1462+
) : this(
1463+
classId = classId,
1464+
name = name,
1465+
returnType = returnType,
1466+
parameters = parameters,
1467+
bypassesSandbox = bypassesSandbox,
1468+
modifiers = ModifierFactory {
1469+
static = isStatic
1470+
public = isPublic
1471+
private = isPrivate
1472+
protected = isProtected
1473+
}
1474+
)
1475+
1476+
fun copy(
1477+
classId: ClassId = this.classId,
1478+
name: String = this.name,
1479+
returnType: ClassId = this.returnType,
1480+
parameters: List<ClassId> = this.parameters,
1481+
bypassesSandbox: Boolean = this.bypassesSandbox,
1482+
modifiers: Int = this.modifiers,
1483+
) = BuiltinMethodId(
1484+
classId = classId,
1485+
name = name,
1486+
returnType = returnType,
1487+
parameters = parameters,
1488+
bypassesSandbox = bypassesSandbox,
1489+
modifiers = modifiers,
1490+
)
13851491
}
13861492

13871493
class BuiltinConstructorId(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package org.utbot.framework.codegen.domain.builtin
2+
3+
import org.utbot.framework.plugin.api.BuiltinMethodId
4+
import org.utbot.framework.plugin.api.ClassId
5+
import org.utbot.framework.plugin.api.UtAssembleModel
6+
import org.utbot.framework.plugin.api.UtExecutableCallModel
7+
import org.utbot.framework.plugin.api.UtModel
8+
import org.utbot.framework.plugin.api.UtStatementCallModel
9+
import org.utbot.framework.plugin.api.UtStatementModel
10+
11+
/**
12+
* Can be used in `UtModel`s to denote class containing util methods,
13+
* before actual [ClassId] containing these methods has been determined.
14+
*
15+
* At the very start of the code generation, [utilClassIdPlaceholder] is
16+
* replaced with actual [ClassId] containing util methods.
17+
*/
18+
val utilClassIdPlaceholder = utJavaUtilsClassId
19+
object UtilMethodProviderPlaceholder : UtilMethodProvider(utilClassIdPlaceholder)
20+
21+
fun UtModel.shallowlyFixUtilClassIds(actualUtilClassId: ClassId) = when (this) {
22+
is UtAssembleModel -> UtAssembleModel(
23+
id = id,
24+
classId = classId,
25+
modelName = modelName,
26+
instantiationCall = instantiationCall.shallowlyFixUtilClassId(actualUtilClassId),
27+
origin = origin,
28+
modificationsChainProvider = { modificationsChain.map { it.shallowlyFixUtilClassId(actualUtilClassId) } }
29+
)
30+
else -> this
31+
}
32+
33+
private fun UtStatementModel.shallowlyFixUtilClassId(actualUtilClassId: ClassId) =
34+
when (this) {
35+
is UtExecutableCallModel -> shallowlyFixUtilClassId(actualUtilClassId)
36+
else -> this
37+
}
38+
39+
private fun UtStatementCallModel.shallowlyFixUtilClassId(actualUtilClassId: ClassId) =
40+
when (this) {
41+
is UtExecutableCallModel -> {
42+
val executable = executable
43+
if (executable.classId == utilClassIdPlaceholder && executable is BuiltinMethodId) {
44+
copy(executable = executable.copy(classId = actualUtilClassId))
45+
} else {
46+
this
47+
}
48+
}
49+
else -> this
50+
}

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/generator/AbstractCodeGenerator.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package org.utbot.framework.codegen.generator
22

33
import mu.KotlinLogging
4+
import org.utbot.framework.codegen.domain.builtin.shallowlyFixUtilClassIds
45
import org.utbot.framework.codegen.domain.context.CgContext
56
import org.utbot.framework.codegen.domain.models.CgClassFile
67
import org.utbot.framework.codegen.domain.models.CgMethodTestSet
78
import org.utbot.framework.codegen.renderer.CgAbstractRenderer
89
import org.utbot.framework.plugin.api.UtMethodTestSet
10+
import org.utbot.framework.plugin.api.mapModels
11+
import org.utbot.framework.plugin.api.mapper.UtModelDeepMapper
912
import java.time.LocalDateTime
1013
import java.time.format.DateTimeFormatter
1114

@@ -42,6 +45,11 @@ abstract class AbstractCodeGenerator(params: CodeGeneratorParams) {
4245
testSets: Collection<UtMethodTestSet>,
4346
testClassCustomName: String? = null,
4447
): CodeGeneratorResult {
48+
@Suppress("NAME_SHADOWING")
49+
val testSets = testSets.mapModels(UtModelDeepMapper { model ->
50+
model.shallowlyFixUtilClassIds(actualUtilClassId = context.utilsClassId)
51+
})
52+
4553
val cgTestSets = testSets.map { CgMethodTestSet(it) }.toList()
4654
return withCustomContext(testClassCustomName) {
4755
context.withTestClassFileScope {

utbot-java-fuzzing/src/main/kotlin/org/utbot/fuzzer/UtFuzzedExecution.kt

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,17 @@ class UtFuzzedExecution(
2222
displayName: String? = null,
2323
val fuzzingValues: List<FuzzedValue>? = null,
2424
val fuzzedMethodDescription: FuzzedMethodDescription? = null,
25-
override val instrumentation: List<UtInstrumentation> = emptyList(),
26-
) : UtExecution(stateBefore, stateAfter, result, coverage, summary, testMethodName, displayName), UtExecutionWithInstrumentation {
25+
instrumentation: List<UtInstrumentation> = emptyList(),
26+
) : UtExecutionWithInstrumentation(
27+
stateBefore,
28+
stateAfter,
29+
result,
30+
coverage,
31+
summary,
32+
testMethodName,
33+
displayName,
34+
instrumentation
35+
) {
2736
/**
2837
* By design the 'before' and 'after' states contain info about the same fields.
2938
* It means that it is not possible for a field to be present at 'before' and to be absent at 'after'.
@@ -39,7 +48,8 @@ class UtFuzzedExecution(
3948
coverage: Coverage?,
4049
summary: List<DocStatement>?,
4150
testMethodName: String?,
42-
displayName: String?
51+
displayName: String?,
52+
instrumentation: List<UtInstrumentation>,
4353
): UtExecution {
4454
return UtFuzzedExecution(
4555
stateBefore,

utbot-usvm/src/main/kotlin/org/utbot/usvm/converter/UtUsvmExecution.kt

Lines changed: 7 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@ import org.utbot.framework.plugin.api.UtExecution
77
import org.utbot.framework.plugin.api.UtExecutionResult
88
import org.utbot.framework.plugin.api.UtExecutionWithInstrumentation
99
import org.utbot.framework.plugin.api.UtInstrumentation
10-
import org.utbot.framework.plugin.api.mapper.UtModelMapper
11-
import org.utbot.framework.plugin.api.mapper.mapModelIfExists
12-
import org.utbot.framework.plugin.api.mapper.mapModels
1310

1411
class UtUsvmExecution(
1512
stateBefore: EnvironmentModels,
@@ -19,24 +16,26 @@ class UtUsvmExecution(
1916
summary: List<DocStatement>? = emptyList(),
2017
testMethodName: String? = null,
2118
displayName: String? = null,
22-
override val instrumentation: List<UtInstrumentation>
23-
) : UtExecution(
19+
instrumentation: List<UtInstrumentation>
20+
) : UtExecutionWithInstrumentation(
2421
stateBefore,
2522
stateAfter,
2623
result,
2724
coverage,
2825
summary,
2926
testMethodName,
30-
displayName
31-
), UtExecutionWithInstrumentation {
27+
displayName,
28+
instrumentation,
29+
) {
3230
override fun copy(
3331
stateBefore: EnvironmentModels,
3432
stateAfter: EnvironmentModels,
3533
result: UtExecutionResult,
3634
coverage: Coverage?,
3735
summary: List<DocStatement>?,
3836
testMethodName: String?,
39-
displayName: String?
37+
displayName: String?,
38+
instrumentation: List<UtInstrumentation>,
4039
): UtExecution = UtUsvmExecution(
4140
stateBefore,
4241
stateAfter,
@@ -47,35 +46,4 @@ class UtUsvmExecution(
4746
displayName,
4847
instrumentation,
4948
)
50-
51-
fun copy(
52-
stateBefore: EnvironmentModels = this.stateBefore,
53-
stateAfter: EnvironmentModels = this.stateAfter,
54-
result: UtExecutionResult = this.result,
55-
coverage: Coverage? = this.coverage,
56-
summary: List<DocStatement>? = this.summary,
57-
testMethodName: String? = this.testMethodName,
58-
displayName: String? = this.displayName,
59-
instrumentation: List<UtInstrumentation> = this.instrumentation,
60-
) = UtUsvmExecution(
61-
stateBefore,
62-
stateAfter,
63-
result,
64-
coverage,
65-
summary,
66-
testMethodName,
67-
displayName,
68-
instrumentation,
69-
)
7049
}
71-
72-
fun UtUsvmExecution.mapModels(mapper: UtModelMapper) = copy(
73-
stateBefore = stateBefore.mapModels(mapper),
74-
stateAfter = stateAfter.mapModels(mapper),
75-
result = result.mapModelIfExists(mapper),
76-
coverage = this.coverage,
77-
summary = this.summary,
78-
testMethodName = this.testMethodName,
79-
displayName = this.displayName,
80-
instrumentation = instrumentation.map { it.mapModels(mapper) },
81-
)

0 commit comments

Comments
 (0)