Skip to content

Commit 32c4e95

Browse files
committed
An attempt to avoid UtMethod in codegen
1 parent dcf607b commit 32c4e95

File tree

8 files changed

+104
-85
lines changed

8 files changed

+104
-85
lines changed

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,22 @@ data class UtMethodTestSet(
9898
val clustersInfo: List<Pair<UtClusterInfo?, IntRange>> = listOf(null to executions.indices)
9999
)
100100

101+
data class CgMethodTestSet private constructor(
102+
val executableId: ExecutableId,
103+
val executions: List<UtExecution> = emptyList(),
104+
val jimpleBody: JimpleBody? = null,
105+
val errors: Map<String, Int> = emptyMap(),
106+
val clustersInfo: List<Pair<UtClusterInfo?, IntRange>> = listOf(null to executions.indices)
107+
) {
108+
constructor(from: UtMethodTestSet) : this(
109+
from.method.callable.executableId,
110+
from.executions,
111+
from.jimpleBody,
112+
from.errors,
113+
from.clustersInfo
114+
)
115+
}
116+
101117
data class Step(
102118
val stmt: Stmt,
103119
val depth: Int,

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

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,16 @@ import org.utbot.framework.codegen.model.constructor.tree.CgTestClassConstructor
1212
import org.utbot.framework.codegen.model.constructor.tree.TestsGenerationReport
1313
import org.utbot.framework.codegen.model.tree.CgTestClassFile
1414
import org.utbot.framework.codegen.model.visitor.CgAbstractRenderer
15+
import org.utbot.framework.plugin.api.CgMethodTestSet
1516
import org.utbot.framework.plugin.api.CodegenLanguage
17+
import org.utbot.framework.plugin.api.ExecutableId
1618
import org.utbot.framework.plugin.api.MockFramework
17-
import org.utbot.framework.plugin.api.UtMethod
1819
import org.utbot.framework.plugin.api.UtMethodTestSet
1920
import org.utbot.framework.plugin.api.util.id
2021

2122
class CodeGenerator(
2223
private val classUnderTest: Class<*>,
23-
params: MutableMap<UtMethod<*>, List<String>> = mutableMapOf(),
24+
params: MutableMap<ExecutableId, List<String>> = mutableMapOf(),
2425
testFramework: TestFramework = TestFramework.defaultItem,
2526
mockFramework: MockFramework? = MockFramework.defaultItem,
2627
staticsMocking: StaticsMocking = StaticsMocking.defaultItem,
@@ -57,13 +58,20 @@ class CodeGenerator(
5758
fun generateAsStringWithTestReport(
5859
testSets: Collection<UtMethodTestSet>,
5960
testClassCustomName: String? = null,
60-
): TestsCodeWithTestReport =
61-
withCustomContext(testClassCustomName) {
62-
context.withClassScope {
63-
val testClassFile = CgTestClassConstructor(context).construct(testSets)
64-
TestsCodeWithTestReport(renderClassFile(testClassFile), testClassFile.testsGenerationReport)
65-
}
66-
}
61+
): TestsCodeWithTestReport {
62+
val cgTestSets = testSets.map { CgMethodTestSet(it) }.toList()
63+
return generateAsStringWithTestReport(cgTestSets, testClassCustomName)
64+
}
65+
66+
fun generateAsStringWithTestReport(
67+
cgTestSets: List<CgMethodTestSet>,
68+
testClassCustomName: String? = null,
69+
): TestsCodeWithTestReport = withCustomContext(testClassCustomName) {
70+
context.withClassScope {
71+
val testClassFile = CgTestClassConstructor(context).construct(cgTestSets)
72+
TestsCodeWithTestReport(renderClassFile(testClassFile), testClassFile.testsGenerationReport)
73+
}
74+
}
6775

6876
/**
6977
* Wrapper function that configures context as needed for utbot-online:

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

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,8 @@ import org.utbot.framework.plugin.api.FieldId
4242
import org.utbot.framework.plugin.api.MethodId
4343
import org.utbot.framework.plugin.api.MockFramework
4444
import org.utbot.framework.plugin.api.UtExecution
45-
import org.utbot.framework.plugin.api.UtMethod
4645
import org.utbot.framework.plugin.api.UtModel
4746
import org.utbot.framework.plugin.api.UtReferenceModel
48-
import org.utbot.framework.plugin.api.UtMethodTestSet
4947
import java.util.IdentityHashMap
5048
import kotlinx.collections.immutable.PersistentList
5149
import kotlinx.collections.immutable.PersistentMap
@@ -55,7 +53,7 @@ import kotlinx.collections.immutable.persistentMapOf
5553
import kotlinx.collections.immutable.persistentSetOf
5654
import org.utbot.framework.codegen.model.constructor.builtin.streamsDeepEqualsMethodId
5755
import org.utbot.framework.codegen.model.tree.CgParameterKind
58-
import org.utbot.framework.plugin.api.util.executableId
56+
import org.utbot.framework.plugin.api.CgMethodTestSet
5957
import org.utbot.framework.plugin.api.util.id
6058
import org.utbot.framework.plugin.api.util.isCheckedException
6159
import org.utbot.framework.plugin.api.util.isSubtypeOf
@@ -121,7 +119,7 @@ internal interface CgContextOwner {
121119
val prevStaticFieldValues: MutableMap<FieldId, CgVariable>
122120

123121
// names of parameters of methods under test
124-
val paramNames: Map<UtMethod<*>, List<String>>
122+
val paramNames: Map<ExecutableId, List<String>>
125123

126124
// UtExecution we currently generate a test method for.
127125
// It is null when no test method is being generated at the moment.
@@ -176,7 +174,7 @@ internal interface CgContextOwner {
176174
// map from a set of tests for a method to another map
177175
// which connects code generation error message
178176
// with the number of times it occurred
179-
val codeGenerationErrors: MutableMap<UtMethodTestSet, MutableMap<String, Int>>
177+
val codeGenerationErrors: MutableMap<CgMethodTestSet, MutableMap<String, Int>>
180178

181179
// package for generated test class
182180
val testClassPackageName: String
@@ -233,8 +231,8 @@ internal interface CgContextOwner {
233231
currentBlock = currentBlock.add(it)
234232
}
235233

236-
fun updateCurrentExecutable(method: UtMethod<*>) {
237-
currentExecutable = method.callable.executableId
234+
fun updateCurrentExecutable(executableId: ExecutableId) {
235+
currentExecutable = executableId
238236
}
239237

240238
fun addExceptionIfNeeded(exception: ClassId) {
@@ -399,7 +397,7 @@ internal data class CgContext(
399397
override val testMethods: MutableList<CgTestMethod> = mutableListOf(),
400398
override val existingMethodNames: MutableSet<String> = mutableSetOf(),
401399
override val prevStaticFieldValues: MutableMap<FieldId, CgVariable> = mutableMapOf(),
402-
override val paramNames: Map<UtMethod<*>, List<String>>,
400+
override val paramNames: Map<ExecutableId, List<String>>,
403401
override var currentExecution: UtExecution? = null,
404402
override val testFramework: TestFramework,
405403
override val mockFramework: MockFramework,
@@ -415,7 +413,7 @@ internal data class CgContext(
415413
override var declaredExecutableRefs: PersistentMap<ExecutableId, CgVariable> = persistentMapOf(),
416414
override var thisInstance: CgValue? = null,
417415
override val methodArguments: MutableList<CgValue> = mutableListOf(),
418-
override val codeGenerationErrors: MutableMap<UtMethodTestSet, MutableMap<String, Int>> = mutableMapOf(),
416+
override val codeGenerationErrors: MutableMap<CgMethodTestSet, MutableMap<String, Int>> = mutableMapOf(),
419417
override val testClassPackageName: String = classUnderTest.packageName,
420418
override var shouldOptimizeImports: Boolean = false,
421419
override var testClassCustomName: String? = null,

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/name/CgNameGenerator.kt

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@ import org.utbot.framework.codegen.model.constructor.util.infiniteInts
77
import org.utbot.framework.plugin.api.ClassId
88
import org.utbot.framework.plugin.api.CodegenLanguage
99
import org.utbot.framework.plugin.api.ConstructorId
10+
import org.utbot.framework.plugin.api.ExecutableId
1011
import org.utbot.framework.plugin.api.MethodId
11-
import org.utbot.framework.plugin.api.UtMethod
12-
import org.utbot.framework.plugin.api.util.executableId
1312
import org.utbot.framework.plugin.api.util.isArray
1413

1514
/**
@@ -45,7 +44,7 @@ internal interface CgNameGenerator {
4544
/**
4645
* Generate a new test method name.
4746
*/
48-
fun testMethodNameFor(method: UtMethod<*>, customName: String? = null): String
47+
fun testMethodNameFor(executableId: ExecutableId, customName: String? = null): String
4948

5049
/**
5150
* Generates a new parameterized test method name by data provider method name.
@@ -55,12 +54,12 @@ internal interface CgNameGenerator {
5554
/**
5655
* Generates a new data for parameterized test provider method name
5756
*/
58-
fun dataProviderMethodNameFor(method: UtMethod<*>): String
57+
fun dataProviderMethodNameFor(executableId: ExecutableId): String
5958

6059
/**
6160
* Generate a new error method name
6261
*/
63-
fun errorMethodNameFor(method: UtMethod<*>): String
62+
fun errorMethodNameFor(executableId: ExecutableId): String
6463
}
6564

6665
/**
@@ -86,10 +85,10 @@ internal class CgNameGeneratorImpl(private val context: CgContext)
8685
return variableName(baseName.decapitalize(), isMock)
8786
}
8887

89-
override fun testMethodNameFor(method: UtMethod<*>, customName: String?): String {
90-
val executableName = when (val id = method.callable.executableId) {
91-
is ConstructorId -> id.classId.prettifiedName // TODO: maybe we need some suffix e.g. "Ctor"?
92-
is MethodId -> id.name
88+
override fun testMethodNameFor(executableId: ExecutableId, customName: String?): String {
89+
val executableName = when (executableId) {
90+
is ConstructorId -> executableId.classId.prettifiedName // TODO: maybe we need some suffix e.g. "Ctor"?
91+
is MethodId -> executableId.name
9392
}
9493
// no index suffix allowed only when there's a vacant custom name
9594
val name = if (customName != null && customName !in existingMethodNames) {
@@ -107,17 +106,17 @@ internal class CgNameGeneratorImpl(private val context: CgContext)
107106
override fun parameterizedTestMethodName(dataProviderMethodName: String) =
108107
dataProviderMethodName.replace(dataProviderMethodPrefix, "parameterizedTestsFor")
109108

110-
override fun dataProviderMethodNameFor(method: UtMethod<*>): String {
111-
val indexedName = nextIndexedMethodName(method.callable.name.capitalize(), skipOne = true)
109+
override fun dataProviderMethodNameFor(executableId: ExecutableId): String {
110+
val indexedName = nextIndexedMethodName(executableId.name.capitalize(), skipOne = true)
112111

113112
existingMethodNames += indexedName
114113
return "$dataProviderMethodPrefix$indexedName"
115114
}
116115

117-
override fun errorMethodNameFor(method: UtMethod<*>): String {
118-
val executableName = when (val id = method.callable.executableId) {
119-
is ConstructorId -> id.classId.prettifiedName
120-
is MethodId -> id.name
116+
override fun errorMethodNameFor(executableId: ExecutableId): String {
117+
val executableName = when (executableId) {
118+
is ConstructorId -> executableId.classId.prettifiedName
119+
is MethodId -> executableId.name
121120
}
122121
val newName = when (val base = "test${executableName.capitalize()}_errors") {
123122
!in existingMethodNames -> base

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

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package org.utbot.framework.codegen.model.constructor.tree
22

33
import org.utbot.common.PathUtil
44
import org.utbot.common.packageName
5-
import org.utbot.engine.isStatic
65
import org.utbot.framework.assemble.assemble
76
import org.utbot.framework.codegen.ForceStaticMocking
87
import org.utbot.framework.codegen.Junit4
@@ -86,6 +85,7 @@ import org.utbot.framework.fields.ExecutionStateAnalyzer
8685
import org.utbot.framework.fields.FieldPath
8786
import org.utbot.framework.plugin.api.BuiltinClassId
8887
import org.utbot.framework.plugin.api.BuiltinMethodId
88+
import org.utbot.framework.plugin.api.CgMethodTestSet
8989
import org.utbot.framework.plugin.api.ClassId
9090
import org.utbot.framework.plugin.api.CodegenLanguage
9191
import org.utbot.framework.plugin.api.ConcreteExecutionFailureException
@@ -106,8 +106,6 @@ import org.utbot.framework.plugin.api.UtExecution
106106
import org.utbot.framework.plugin.api.UtExecutionFailure
107107
import org.utbot.framework.plugin.api.UtExecutionSuccess
108108
import org.utbot.framework.plugin.api.UtExplicitlyThrownException
109-
import org.utbot.framework.plugin.api.UtMethod
110-
import org.utbot.framework.plugin.api.UtMethodTestSet
111109
import org.utbot.framework.plugin.api.UtModel
112110
import org.utbot.framework.plugin.api.UtNewInstanceInstrumentation
113111
import org.utbot.framework.plugin.api.UtNullModel
@@ -123,6 +121,7 @@ import org.utbot.framework.plugin.api.util.builtinStaticMethodId
123121
import org.utbot.framework.plugin.api.util.doubleArrayClassId
124122
import org.utbot.framework.plugin.api.util.doubleClassId
125123
import org.utbot.framework.plugin.api.util.doubleWrapperClassId
124+
import org.utbot.framework.plugin.api.util.executable
126125
import org.utbot.framework.plugin.api.util.field
127126
import org.utbot.framework.plugin.api.util.floatArrayClassId
128127
import org.utbot.framework.plugin.api.util.floatClassId
@@ -149,7 +148,6 @@ import org.utbot.framework.util.isUnit
149148
import org.utbot.summary.SummarySentenceConstants.TAB
150149
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
151150
import java.lang.reflect.InvocationTargetException
152-
import kotlin.reflect.jvm.javaType
153151

154152
private const val DEEP_EQUALS_MAX_DEPTH = 5 // TODO move it to plugin settings?
155153

@@ -1086,11 +1084,11 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
10861084
}
10871085
}
10881086

1089-
fun createTestMethod(utMethod: UtMethod<*>, execution: UtExecution): CgTestMethod =
1087+
fun createTestMethod(executableId: ExecutableId, execution: UtExecution): CgTestMethod =
10901088
withTestMethodScope(execution) {
1091-
val testMethodName = nameGenerator.testMethodNameFor(utMethod, execution.testMethodName)
1089+
val testMethodName = nameGenerator.testMethodNameFor(executableId, execution.testMethodName)
10921090
// TODO: remove this line when SAT-1273 is completed
1093-
execution.displayName = execution.displayName?.let { "${utMethod.callable.name}: $it" }
1091+
execution.displayName = execution.displayName?.let { "${executableId.name}: $it" }
10941092
testMethod(testMethodName, execution.displayName) {
10951093
rememberInitialStaticFields()
10961094
val stateAnalyzer = ExecutionStateAnalyzer(execution)
@@ -1105,7 +1103,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
11051103
}
11061104
// build arguments
11071105
for ((index, param) in execution.stateBefore.parameters.withIndex()) {
1108-
val name = paramNames[utMethod]?.get(index)
1106+
val name = paramNames[executableId]?.get(index)
11091107
methodArguments += variableConstructor.getOrCreateVariable(param, name)
11101108
}
11111109
rememberInitialEnvironmentState(modificationInfo)
@@ -1165,7 +1163,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
11651163
private val expectedResultVarName = "expectedResult"
11661164
private val expectedErrorVarName = "expectedError"
11671165

1168-
fun createParameterizedTestMethod(testSet: UtMethodTestSet, dataProviderMethodName: String): CgTestMethod {
1166+
fun createParameterizedTestMethod(testSet: CgMethodTestSet, dataProviderMethodName: String): CgTestMethod {
11691167
//TODO: orientation on generic execution may be misleading, but what is the alternative?
11701168
//may be a heuristic to select a model with minimal number of internal nulls should be used
11711169
val genericExecution = testSet.executions
@@ -1217,11 +1215,11 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
12171215
}
12181216

12191217
private fun createParameterDeclarations(
1220-
testSet: UtMethodTestSet,
1218+
testSet: CgMethodTestSet,
12211219
genericExecution: UtExecution,
12221220
): List<CgParameterDeclaration> {
1223-
val methodUnderTest = testSet.method
1224-
val methodUnderTestParameters = testSet.method.callable.parameters
1221+
val executableUnderTest = testSet.executableId
1222+
val executableUnderTestParameters = testSet.executableId.executable.parameters
12251223

12261224
return mutableListOf<CgParameterDeclaration>().apply {
12271225
// this instance
@@ -1240,9 +1238,9 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
12401238
}
12411239
// arguments
12421240
for (index in genericExecution.stateBefore.parameters.indices) {
1243-
val argumentName = paramNames[methodUnderTest]?.get(index)
1244-
val paramIndex = if (methodUnderTest.isStatic) index else index + 1
1245-
val paramType = methodUnderTestParameters[paramIndex].type.javaType
1241+
val argumentName = paramNames[executableUnderTest]?.get(index)
1242+
val paramIndex = if (executableUnderTest is MethodId && executableUnderTest.isStatic) index else index + 1
1243+
val paramType = executableUnderTestParameters[paramIndex].parameterizedType
12461244

12471245
val argumentType = when {
12481246
paramType is Class<*> && paramType.isArray -> paramType.id
@@ -1310,7 +1308,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
13101308
* Standard logic for generating each test case parameter code is used.
13111309
*/
13121310
fun createParameterizedTestDataProvider(
1313-
testSet: UtMethodTestSet,
1311+
testSet: CgMethodTestSet,
13141312
dataProviderMethodName: String
13151313
): CgParameterizedTestDataProviderMethod {
13161314
return withDataProviderScope {
@@ -1335,14 +1333,14 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
13351333
}
13361334
}
13371335

1338-
private fun createExecutionArguments(testSet: UtMethodTestSet, execution: UtExecution): List<CgExpression> {
1336+
private fun createExecutionArguments(testSet: CgMethodTestSet, execution: UtExecution): List<CgExpression> {
13391337
val arguments = mutableListOf<CgExpression>()
13401338
execution.stateBefore.thisInstance?.let {
13411339
arguments += variableConstructor.getOrCreateVariable(it)
13421340
}
13431341

13441342
for ((paramIndex, paramModel) in execution.stateBefore.parameters.withIndex()) {
1345-
val argumentName = paramNames[testSet.method]?.get(paramIndex)
1343+
val argumentName = paramNames[testSet.executableId]?.get(paramIndex)
13461344
arguments += variableConstructor.getOrCreateVariable(paramModel, argumentName)
13471345
}
13481346

@@ -1567,7 +1565,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
15671565
arguments = arrayOf(objectArrayClassId)
15681566
)
15691567

1570-
private fun containsFailureExecution(testSet: UtMethodTestSet) =
1568+
private fun containsFailureExecution(testSet: CgMethodTestSet) =
15711569
testSet.executions.any { it.result is UtExecutionFailure }
15721570

15731571

@@ -1668,7 +1666,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
16681666
}
16691667
}
16701668

1671-
fun errorMethod(method: UtMethod<*>, errors: Map<String, Int>): CgRegion<CgMethod> {
1669+
fun errorMethod(method: ExecutableId, errors: Map<String, Int>): CgRegion<CgMethod> {
16721670
val name = nameGenerator.errorMethodNameFor(method)
16731671
val body = block {
16741672
comment("Couldn't generate some tests. List of errors:")
@@ -1697,7 +1695,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
16971695
}
16981696
}
16991697
val errorTestMethod = CgErrorTestMethod(name, body)
1700-
return CgSimpleRegion("Errors report for ${method.callable.name}", listOf(errorTestMethod))
1698+
return CgSimpleRegion("Errors report for ${method.name}", listOf(errorTestMethod))
17011699
}
17021700

17031701
private fun getJvmReportDocumentation(jvmReportPath: String): String {

0 commit comments

Comments
 (0)