Skip to content

Commit 83341fd

Browse files
An attempt to avoid UtMethod in codegen (#602)
* An attempt to avoid UtMethod in codegen * Fix a bug with param names * Correcting indices * Use displayName for executables instead of regular name * Rename parameter for better readability Co-authored-by: Arsen Nagdalian <nagoarsen@mail.ru>
1 parent dcf607b commit 83341fd

File tree

9 files changed

+135
-106
lines changed

9 files changed

+135
-106
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/engine/Extensions.kt

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ import kotlin.reflect.jvm.javaMethod
4646
import kotlinx.collections.immutable.PersistentMap
4747
import kotlinx.collections.immutable.persistentHashMapOf
4848
import org.utbot.engine.pc.UtSolverStatusUNDEFINED
49+
import org.utbot.framework.plugin.api.ExecutableId
50+
import org.utbot.framework.plugin.api.util.executableId
4951
import soot.ArrayType
5052
import soot.PrimType
5153
import soot.RefLikeType
@@ -326,15 +328,28 @@ val <R> UtMethod<R>.signature: String
326328
return "${methodName}()"
327329
}
328330

331+
val ExecutableId.displayName: String
332+
get() {
333+
val executableName = this.name
334+
val parameters = this.parameters.joinToString(separator = ", ") { it.canonicalName }
335+
return "$executableName($parameters)"
336+
}
337+
338+
val Constructor<*>.displayName: String
339+
get() = executableId.displayName
340+
341+
val Method.displayName: String
342+
get() = executableId.displayName
343+
329344
val <R> UtMethod<R>.displayName: String
330345
get() {
331-
val methodName = this.callable.name
332-
val javaMethod = this.javaMethod ?: this.javaConstructor
333-
if (javaMethod != null) {
334-
val parameters = javaMethod.parameters.joinToString(separator = ", ") { "${it.type.canonicalName}" }
335-
return "${methodName}($parameters)"
346+
val executableId = this.javaMethod?.executableId ?: this.javaConstructor?.executableId
347+
return if (executableId != null) {
348+
executableId.displayName
349+
} else {
350+
val methodName = this.callable.name
351+
return "${methodName}()"
336352
}
337-
return "${methodName}()"
338353
}
339354

340355

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

Lines changed: 18 additions & 10 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+
paramNames: MutableMap<ExecutableId, List<String>> = mutableMapOf(),
2425
testFramework: TestFramework = TestFramework.defaultItem,
2526
mockFramework: MockFramework? = MockFramework.defaultItem,
2627
staticsMocking: StaticsMocking = StaticsMocking.defaultItem,
@@ -35,7 +36,7 @@ class CodeGenerator(
3536
) {
3637
private var context: CgContext = CgContext(
3738
classUnderTest = classUnderTest.id,
38-
paramNames = params,
39+
paramNames = paramNames,
3940
testFramework = testFramework,
4041
mockFramework = mockFramework ?: MockFramework.MOCKITO,
4142
codegenLanguage = codegenLanguage,
@@ -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

0 commit comments

Comments
 (0)