Skip to content

Commit 38a24f8

Browse files
committed
An attempt to avoid UtMethod in codegen
1 parent 64e8170 commit 38a24f8

File tree

8 files changed

+103
-84
lines changed

8 files changed

+103
-84
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: 18 additions & 20 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.JUNIT5_PARAMETERIZED_PACKAGE
@@ -93,6 +92,7 @@ import org.utbot.framework.fields.ExecutionStateAnalyzer
9392
import org.utbot.framework.fields.FieldPath
9493
import org.utbot.framework.plugin.api.BuiltinClassId
9594
import org.utbot.framework.plugin.api.BuiltinMethodId
95+
import org.utbot.framework.plugin.api.CgMethodTestSet
9696
import org.utbot.framework.plugin.api.ClassId
9797
import org.utbot.framework.plugin.api.CodegenLanguage
9898
import org.utbot.framework.plugin.api.ConcreteExecutionFailureException
@@ -113,8 +113,6 @@ import org.utbot.framework.plugin.api.UtExecution
113113
import org.utbot.framework.plugin.api.UtExecutionFailure
114114
import org.utbot.framework.plugin.api.UtExecutionSuccess
115115
import org.utbot.framework.plugin.api.UtExplicitlyThrownException
116-
import org.utbot.framework.plugin.api.UtMethod
117-
import org.utbot.framework.plugin.api.UtMethodTestSet
118116
import org.utbot.framework.plugin.api.UtModel
119117
import org.utbot.framework.plugin.api.UtNewInstanceInstrumentation
120118
import org.utbot.framework.plugin.api.UtNullModel
@@ -129,6 +127,7 @@ import org.utbot.framework.plugin.api.util.booleanClassId
129127
import org.utbot.framework.plugin.api.util.doubleArrayClassId
130128
import org.utbot.framework.plugin.api.util.doubleClassId
131129
import org.utbot.framework.plugin.api.util.doubleWrapperClassId
130+
import org.utbot.framework.plugin.api.util.executable
132131
import org.utbot.framework.plugin.api.util.field
133132
import org.utbot.framework.plugin.api.util.floatArrayClassId
134133
import org.utbot.framework.plugin.api.util.floatClassId
@@ -155,7 +154,6 @@ import org.utbot.framework.util.isUnit
155154
import org.utbot.summary.SummarySentenceConstants.TAB
156155
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
157156
import java.lang.reflect.InvocationTargetException
158-
import kotlin.reflect.jvm.javaType
159157

160158
private const val DEEP_EQUALS_MAX_DEPTH = 5 // TODO move it to plugin settings?
161159

@@ -1136,11 +1134,11 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
11361134
}
11371135
}
11381136

1139-
fun createTestMethod(utMethod: UtMethod<*>, execution: UtExecution): CgTestMethod =
1137+
fun createTestMethod(executableId: ExecutableId, execution: UtExecution): CgTestMethod =
11401138
withTestMethodScope(execution) {
1141-
val testMethodName = nameGenerator.testMethodNameFor(utMethod, execution.testMethodName)
1139+
val testMethodName = nameGenerator.testMethodNameFor(executableId, execution.testMethodName)
11421140
// TODO: remove this line when SAT-1273 is completed
1143-
execution.displayName = execution.displayName?.let { "${utMethod.callable.name}: $it" }
1141+
execution.displayName = execution.displayName?.let { "${executableId.name}: $it" }
11441142
testMethod(testMethodName, execution.displayName) {
11451143
rememberInitialStaticFields()
11461144
val stateAnalyzer = ExecutionStateAnalyzer(execution)
@@ -1155,7 +1153,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
11551153
}
11561154
// build arguments
11571155
for ((index, param) in execution.stateBefore.parameters.withIndex()) {
1158-
val name = paramNames[utMethod]?.get(index)
1156+
val name = paramNames[executableId]?.get(index)
11591157
methodArguments += variableConstructor.getOrCreateVariable(param, name)
11601158
}
11611159
rememberInitialEnvironmentState(modificationInfo)
@@ -1215,7 +1213,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
12151213
private val expectedResultVarName = "expectedResult"
12161214
private val expectedErrorVarName = "expectedError"
12171215

1218-
fun createParameterizedTestMethod(testSet: UtMethodTestSet, dataProviderMethodName: String): CgTestMethod {
1216+
fun createParameterizedTestMethod(testSet: CgMethodTestSet, dataProviderMethodName: String): CgTestMethod {
12191217
//TODO: orientation on generic execution may be misleading, but what is the alternative?
12201218
//may be a heuristic to select a model with minimal number of internal nulls should be used
12211219
val genericExecution = testSet.executions
@@ -1267,11 +1265,11 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
12671265
}
12681266

12691267
private fun createParameterDeclarations(
1270-
testSet: UtMethodTestSet,
1268+
testSet: CgMethodTestSet,
12711269
genericExecution: UtExecution,
12721270
): List<CgParameterDeclaration> {
1273-
val methodUnderTest = testSet.method
1274-
val methodUnderTestParameters = testSet.method.callable.parameters
1271+
val executableUnderTest = testSet.executableId
1272+
val executableUnderTestParameters = testSet.executableId.executable.parameters
12751273

12761274
return mutableListOf<CgParameterDeclaration>().apply {
12771275
// this instance
@@ -1290,9 +1288,9 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
12901288
}
12911289
// arguments
12921290
for (index in genericExecution.stateBefore.parameters.indices) {
1293-
val argumentName = paramNames[methodUnderTest]?.get(index)
1294-
val paramIndex = if (methodUnderTest.isStatic) index else index + 1
1295-
val paramType = methodUnderTestParameters[paramIndex].type.javaType
1291+
val argumentName = paramNames[executableUnderTest]?.get(index)
1292+
val paramIndex = if (executableUnderTest is MethodId && executableUnderTest.isStatic) index else index + 1
1293+
val paramType = executableUnderTestParameters[paramIndex].parameterizedType
12961294

12971295
val argumentType = when {
12981296
paramType is Class<*> && paramType.isArray -> paramType.id
@@ -1353,7 +1351,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
13531351
* Standard logic for generating each test case parameter code is used.
13541352
*/
13551353
fun createParameterizedTestDataProvider(
1356-
testSet: UtMethodTestSet,
1354+
testSet: CgMethodTestSet,
13571355
dataProviderMethodName: String
13581356
): CgParameterizedTestDataProviderMethod {
13591357
val dataProviderStatements = mutableListOf<CgStatement>()
@@ -1376,7 +1374,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
13761374
}
13771375

13781376
for ((paramIndex, paramModel) in execution.stateBefore.parameters.withIndex()) {
1379-
val argumentName = paramNames[testSet.method]?.get(paramIndex)
1377+
val argumentName = paramNames[testSet.executableId]?.get(paramIndex)
13801378
arguments += variableConstructor.getOrCreateVariable(paramModel, argumentName)
13811379
}
13821380

@@ -1572,7 +1570,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
15721570
)
15731571
}
15741572

1575-
private fun containsFailureExecution(testSet: UtMethodTestSet) =
1573+
private fun containsFailureExecution(testSet: CgMethodTestSet) =
15761574
testSet.executions.any { it.result is UtExecutionFailure }
15771575

15781576
/**
@@ -1670,7 +1668,7 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c
16701668
return testMethod
16711669
}
16721670

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

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

0 commit comments

Comments
 (0)