Skip to content

Commit 9a7d73c

Browse files
committed
Split CgMethodTestSet.executableId into executableUnderTest and executablesToCall
1 parent 871d176 commit 9a7d73c

File tree

12 files changed

+81
-45
lines changed

12 files changed

+81
-45
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ abstract class UtExecution(
142142
testMethodName: String? = this.testMethodName,
143143
displayName: String? = this.displayName,
144144
): UtExecution
145+
146+
val executableToCall get() = stateBefore.executableToCall
145147
}
146148

147149
/**

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/models/CgMethodTestSet.kt

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,15 @@ import org.utbot.framework.plugin.api.util.objectClassId
1212
import org.utbot.framework.plugin.api.util.voidClassId
1313
import org.utbot.fuzzer.UtFuzzedExecution
1414

15-
data class CgMethodTestSet constructor(
16-
val executableId: ExecutableId,
15+
data class CgMethodTestSet(
16+
val executableUnderTest: ExecutableId,
1717
val errors: Map<String, Int> = emptyMap(),
1818
val clustersInfo: List<Pair<UtClusterInfo?, IntRange>>,
1919
) {
20+
val executablesToCall get() =
21+
executions.map { it.executableToCall ?: executableUnderTest }
22+
.distinctBy { it.classId to it.signature }
23+
2024
var executions: List<UtExecution> = emptyList()
2125
private set
2226

@@ -55,8 +59,11 @@ data class CgMethodTestSet constructor(
5559
*
5660
* Tries to find a unique result type in testSets or
5761
* gets executable return type.
62+
*
63+
* Returns `null` if there are multiple distinct [executablesToCall].
5864
*/
59-
fun resultType(): ClassId {
65+
fun getCommonResultTypeOrNull(): ClassId? {
66+
val executableId = executablesToCall.singleOrNull() ?: return null
6067
return when (executableId.returnType) {
6168
voidClassId -> executableId.returnType
6269
else -> {

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/domain/models/builders/SimpleTestClassModelBuilder.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ open class SimpleTestClassModelBuilder(context: CgContext): TestClassModelBuilde
1212
testSets: List<CgMethodTestSet>,
1313
): SimpleTestClassModel {
1414
// For each class stores list of methods declared in this class (methods from nested classes are excluded)
15-
val class2methodTestSets = testSets.groupBy { it.executableId.classId }
15+
val class2methodTestSets = testSets.groupBy { it.executableUnderTest.classId }
1616

1717
val classesWithMethodsUnderTest = testSets
18-
.map { it.executableId.classId }
18+
.map { it.executableUnderTest.classId }
1919
.distinct()
2020

2121
// For each class stores list of its "direct" nested classes

utbot-framework/src/main/kotlin/org/utbot/framework/codegen/reports/TestsGenerationReport.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,12 @@ data class TestsGenerationReport(
5353
}
5454

5555
fun addMethodErrors(testSet: CgMethodTestSet, errors: Map<String, Int>) {
56-
this.executables += testSet.executableId
57-
this.errors[testSet.executableId] = errors
56+
this.executables += testSet.executableUnderTest
57+
this.errors[testSet.executableUnderTest] = errors
5858
}
5959

6060
fun addTestsByType(testSet: CgMethodTestSet, testMethods: List<CgTestMethod>) {
61-
with(testSet.executableId) {
61+
with(testSet.executableUnderTest) {
6262
executables += this
6363

6464
testMethods.forEach {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ abstract class CgAbstractSpringTestClassConstructor(context: CgContext) :
3939
constructAdditionalTestMethods()?.let { methodRegions += it }
4040

4141
for ((testSetIndex, testSet) in testClassModel.methodTestSets.withIndex()) {
42-
updateExecutableUnderTest(testSet.executableId)
42+
updateExecutableUnderTest(testSet.executableUnderTest)
4343
withTestSetIdScope(testSetIndex) {
4444
val currentMethodUnderTestRegions = constructTestSet(testSet) ?: return@withTestSetIdScope
4545
val executableUnderTestCluster = CgMethodsCluster(
@@ -74,7 +74,7 @@ abstract class CgAbstractSpringTestClassConstructor(context: CgContext) :
7474

7575
val errors = testSet.allErrors
7676
if (errors.isNotEmpty()) {
77-
regions += methodConstructor.errorMethod(testSet.executableId, errors)
77+
regions += methodConstructor.errorMethod(testSet, errors)
7878
testsGenerationReport.addMethodErrors(testSet, errors)
7979
}
8080

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ abstract class CgAbstractTestClassConstructor<T : TestClassModel>(val context: C
8989
testSet: CgMethodTestSet,
9090
regions: MutableList<CgRegion<CgMethod>>
9191
) {
92-
val (methodUnderTest, _, clustersInfo) = testSet
92+
val (_, _, clustersInfo) = testSet
9393

9494
for ((clusterSummary, executionIndices) in clustersInfo) {
9595
val currentTestCaseTestMethods = mutableListOf<CgTestMethod>()
@@ -102,7 +102,7 @@ abstract class CgAbstractTestClassConstructor<T : TestClassModel>(val context: C
102102

103103
for (i in checkedRange) {
104104
withExecutionIdScope(i) {
105-
currentTestCaseTestMethods += methodConstructor.createTestMethod(methodUnderTest, testSet.executions[i])
105+
currentTestCaseTestMethods += methodConstructor.createTestMethod(testSet, testSet.executions[i])
106106
}
107107
}
108108

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

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1421,14 +1421,14 @@ open class CgMethodConstructor(val context: CgContext) : CgContextOwner by conte
14211421
}
14221422
}
14231423

1424-
open fun createTestMethod(executableId: ExecutableId, execution: UtExecution): CgTestMethod =
1424+
open fun createTestMethod(testSet: CgMethodTestSet, execution: UtExecution): CgTestMethod =
14251425
withTestMethodScope(execution) {
1426-
val testMethodName = nameGenerator.testMethodNameFor(executableId, execution.testMethodName)
1426+
val testMethodName = nameGenerator.testMethodNameFor(testSet.executableUnderTest, execution.testMethodName)
14271427
if (execution.testMethodName == null) {
14281428
execution.testMethodName = testMethodName
14291429
}
14301430
// TODO: remove this line when SAT-1273 is completed
1431-
execution.displayName = execution.displayName?.let { "${executableId.name}: $it" }
1431+
execution.displayName = execution.displayName?.let { "${testSet.executableUnderTest.name}: $it" }
14321432
testMethod(testMethodName, execution.displayName) {
14331433
//Enum constants are static, but there is no need to store and recover value for them
14341434
val statics = currentExecution!!.stateBefore
@@ -1450,7 +1450,7 @@ open class CgMethodConstructor(val context: CgContext) : CgContextOwner by conte
14501450
}
14511451
// build arguments
14521452
for ((index, param) in execution.stateBefore.parameters.withIndex()) {
1453-
val name = paramNames[executableId]?.get(index)
1453+
val name = paramNames[execution.executableToCall ?: testSet.executableUnderTest]?.get(index)
14541454
methodArguments += variableConstructor.getOrCreateVariable(param, name)
14551455
}
14561456

@@ -1523,7 +1523,11 @@ open class CgMethodConstructor(val context: CgContext) : CgContextOwner by conte
15231523
private val expectedResultVarName = "expectedResult"
15241524
private val expectedErrorVarName = "expectedError"
15251525

1526-
fun createParameterizedTestMethod(testSet: CgMethodTestSet, dataProviderMethodName: String): CgTestMethod {
1526+
/**
1527+
* Returns `null` if parameterized test method can't be created for [testSet]
1528+
* (for example, when there are multiple distinct [CgMethodTestSet.executablesToCall]).
1529+
*/
1530+
fun createParameterizedTestMethod(testSet: CgMethodTestSet, dataProviderMethodName: String): CgTestMethod? {
15271531
//TODO: orientation on generic execution may be misleading, but what is the alternative?
15281532
//may be a heuristic to select a model with minimal number of internal nulls should be used
15291533
val genericExecution = chooseGenericExecution(testSet.executions)
@@ -1539,7 +1543,8 @@ open class CgMethodConstructor(val context: CgContext) : CgContextOwner by conte
15391543
return withTestMethodScope(genericExecution) {
15401544
val testName = nameGenerator.parameterizedTestMethodName(dataProviderMethodName)
15411545
withNameScope {
1542-
val testParameterDeclarations = createParameterDeclarations(testSet, genericExecution)
1546+
val testParameterDeclarations =
1547+
createParameterDeclarations(testSet, genericExecution) ?: return@withNameScope null
15431548

15441549
methodType = PARAMETRIZED
15451550
testMethod(
@@ -1609,12 +1614,16 @@ open class CgMethodConstructor(val context: CgContext) : CgContextOwner by conte
16091614
.firstOrNull { it.result is UtExecutionSuccess } ?: executions.first()
16101615
}
16111616

1617+
/**
1618+
* Returns `null` if parameter declarations can't be created for [testSet]
1619+
* (for example, when there are multiple distinct [CgMethodTestSet.executablesToCall]).
1620+
*/
16121621
private fun createParameterDeclarations(
16131622
testSet: CgMethodTestSet,
16141623
genericExecution: UtExecution,
1615-
): List<CgParameterDeclaration> {
1616-
val executableUnderTest = testSet.executableId
1617-
val executableUnderTestParameters = testSet.executableId.executable.parameters
1624+
): List<CgParameterDeclaration>? {
1625+
val executableToCall = testSet.executablesToCall.singleOrNull() ?: return null
1626+
val executableUnderTestParameters = executableToCall.executable.parameters
16181627

16191628
return mutableListOf<CgParameterDeclaration>().apply {
16201629
// this instance
@@ -1633,7 +1642,7 @@ open class CgMethodConstructor(val context: CgContext) : CgContextOwner by conte
16331642

16341643
// arguments
16351644
for (index in genericExecution.stateBefore.parameters.indices) {
1636-
val argumentName = paramNames[executableUnderTest]?.get(index)
1645+
val argumentName = paramNames[executableToCall]?.get(index)
16371646
val paramType = executableUnderTestParameters[index].parameterizedType
16381647

16391648
val argumentType = when {
@@ -1669,7 +1678,7 @@ open class CgMethodConstructor(val context: CgContext) : CgContextOwner by conte
16691678
}
16701679
}
16711680

1672-
val expectedResultClassId = wrapTypeIfRequired(testSet.resultType())
1681+
val expectedResultClassId = wrapTypeIfRequired(testSet.getCommonResultTypeOrNull() ?: return null)
16731682
if (expectedResultClassId != voidClassId) {
16741683
val wrappedType = wrapIfPrimitive(expectedResultClassId)
16751684
//We are required to wrap the type of expected result if it is primitive
@@ -1747,7 +1756,7 @@ open class CgMethodConstructor(val context: CgContext) : CgContextOwner by conte
17471756
}
17481757

17491758
for ((paramIndex, paramModel) in execution.stateBefore.parameters.withIndex()) {
1750-
val argumentName = paramNames[testSet.executableId]?.get(paramIndex)
1759+
val argumentName = paramNames[execution.executableToCall ?: testSet.executableUnderTest]?.get(paramIndex)
17511760
arguments += variableConstructor.getOrCreateVariable(paramModel, argumentName)
17521761
}
17531762

@@ -1950,8 +1959,8 @@ open class CgMethodConstructor(val context: CgContext) : CgContextOwner by conte
19501959
}
19511960
}
19521961

1953-
fun errorMethod(executable: ExecutableId, errors: Map<String, Int>): CgRegion<CgMethod> {
1954-
val name = nameGenerator.errorMethodNameFor(executable)
1962+
fun errorMethod(testSet: CgMethodTestSet, errors: Map<String, Int>): CgRegion<CgMethod> {
1963+
val name = nameGenerator.errorMethodNameFor(testSet.executableUnderTest)
19551964
val body = block {
19561965
comment("Couldn't generate some tests. List of errors:")
19571966
comment()
@@ -1979,7 +1988,7 @@ open class CgMethodConstructor(val context: CgContext) : CgContextOwner by conte
19791988
}
19801989
}
19811990
val errorTestMethod = CgErrorTestMethod(name, body)
1982-
return CgSimpleRegion("Errors report for ${executable.name}", listOf(errorTestMethod))
1991+
return CgSimpleRegion("Errors report for ${testSet.executableUnderTest.name}", listOf(errorTestMethod))
19831992
}
19841993

19851994
private fun CgExecutableCall.wrapReflectiveCall() {

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

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ open class CgSimpleTestClassConstructor(context: CgContext): CgAbstractTestClass
5050
}
5151

5252
for ((testSetIndex, testSet) in notYetConstructedTestSets.withIndex()) {
53-
updateExecutableUnderTest(testSet.executableId)
53+
updateExecutableUnderTest(testSet.executableUnderTest)
5454
withTestSetIdScope(testSetIndex) {
5555
val currentMethodUnderTestRegions = constructTestSet(testSet) ?: return@withTestSetIdScope
5656
val executableUnderTestCluster = CgMethodsCluster(
@@ -96,14 +96,16 @@ open class CgSimpleTestClassConstructor(context: CgContext): CgAbstractTestClass
9696
createParametrizedTestAndDataProvider(
9797
testSet,
9898
regions
99-
)
99+
).let { parametrizedTestCreatedSuccessfully ->
100+
if (!parametrizedTestCreatedSuccessfully) createTest(testSet, regions)
101+
}
100102
}
101103
}.onFailure { e -> processFailure(testSet, e) }
102104
}
103105

104106
val errors = testSet.allErrors
105107
if (errors.isNotEmpty()) {
106-
regions += methodConstructor.errorMethod(testSet.executableId, errors)
108+
regions += methodConstructor.errorMethod(testSet, errors)
107109
testsGenerationReport.addMethodErrors(testSet, errors)
108110
}
109111

@@ -119,17 +121,21 @@ open class CgSimpleTestClassConstructor(context: CgContext): CgAbstractTestClass
119121
return testSets
120122
}
121123

124+
/**
125+
* Returns `false` if parameterized test method can't be created for [testSet]
126+
* (for example, when there are multiple distinct [CgMethodTestSet.executablesToCall]).
127+
*/
122128
private fun createParametrizedTestAndDataProvider(
123129
testSet: CgMethodTestSet,
124130
regions: MutableList<CgRegion<CgMethod>>
125-
) {
131+
) : Boolean {
126132
val (methodUnderTest, _, _) = testSet
127133

128134
for (preparedTestSet in testSet.prepareTestSetsForParameterizedTestGeneration()) {
129-
val dataProviderMethodName = nameGenerator.dataProviderMethodNameFor(preparedTestSet.executableId)
135+
val dataProviderMethodName = nameGenerator.dataProviderMethodNameFor(preparedTestSet.executableUnderTest)
130136

131137
val parameterizedTestMethod =
132-
methodConstructor.createParameterizedTestMethod(preparedTestSet, dataProviderMethodName)
138+
methodConstructor.createParameterizedTestMethod(preparedTestSet, dataProviderMethodName) ?: return false
133139

134140
testFrameworkManager.addDataProvider(
135141
methodConstructor.createParameterizedTestDataProvider(preparedTestSet, dataProviderMethodName)
@@ -150,6 +156,8 @@ open class CgSimpleTestClassConstructor(context: CgContext): CgAbstractTestClass
150156
"FUZZER: Tests for method ${methodUnderTest.humanReadableName} that cannot be presented as parameterized",
151157
collectFuzzerTestsForParameterizedMode(testSet),
152158
)
159+
160+
return true
153161
}
154162

155163
/**
@@ -164,7 +172,7 @@ open class CgSimpleTestClassConstructor(context: CgContext): CgAbstractTestClass
164172
.withIndex()
165173
.forEach { (index, execution) ->
166174
withExecutionIdScope(index) {
167-
testMethods += methodConstructor.createTestMethod(testSet.executableId, execution)
175+
testMethods += methodConstructor.createTestMethod(testSet, execution)
168176
}
169177
}
170178

@@ -184,7 +192,7 @@ open class CgSimpleTestClassConstructor(context: CgContext): CgAbstractTestClass
184192
.withIndex()
185193
.forEach { (index, execution) ->
186194
withExecutionIdScope(index) {
187-
testMethods += methodConstructor.createTestMethod(testSet.executableId, execution)
195+
testMethods += methodConstructor.createTestMethod(testSet, execution)
188196
}
189197
}
190198

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import org.utbot.framework.codegen.domain.models.CgValue
77
import org.utbot.framework.plugin.api.ClassId
88
import org.utbot.framework.plugin.api.UtModel
99
import org.utbot.framework.plugin.api.UtSpringContextModel
10+
import org.utbot.framework.plugin.api.UtSpringMockMvcResultActionsModel
1011
import org.utbot.framework.plugin.api.util.stringClassId
1112

1213
class CgSpringVariableConstructor(context: CgContext) : CgVariableConstructor(context) {
@@ -35,4 +36,12 @@ class CgSpringVariableConstructor(context: CgContext) : CgVariableConstructor(co
3536
valueByUtModelWrapper[UtSpringContextModel.wrap()] = it
3637
}
3738
}
39+
40+
override fun constructValueByModel(model: UtModel, name: String?): CgValue = when (model) {
41+
is UtSpringMockMvcResultActionsModel -> CgLiteral(
42+
model.classId,
43+
"UtSpringMockMvcResult(${model.status}, ${model.errorMessage}, ${model.contentAsString}, ${model.viewName})"
44+
)
45+
else -> super.constructValueByModel(model, name)
46+
}
3847
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ open class CgVariableConstructor(val context: CgContext) :
9595
constructValueByModel(model, name)
9696
}
9797

98-
private fun constructValueByModel(model: UtModel, name: String?): CgValue {
98+
open fun constructValueByModel(model: UtModel, name: String?): CgValue {
9999
// name could be taken from existing names, or be specified manually, or be created from generator
100100
val baseName = name ?: nameGenerator.nameFrom(model.classId)
101101

utbot-js/src/main/kotlin/framework/codegen/model/constructor/tree/JsCgMethodConstructor.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ class JsCgMethodConstructor(ctx: CgContext) : CgMethodConstructor(ctx) {
2222
testFrameworkManager.assertEquals(expected, actual)
2323
}
2424

25-
override fun createTestMethod(executableId: ExecutableId, execution: UtExecution): CgTestMethod =
25+
override fun createTestMethod(testSet: CgMethodTestSet, execution: UtExecution): CgTestMethod =
2626
withTestMethodScope(execution) {
27-
val testMethodName = nameGenerator.testMethodNameFor(executableId, execution.testMethodName)
28-
execution.displayName = execution.displayName?.let { "${executableId.name}: $it" }
27+
val testMethodName = nameGenerator.testMethodNameFor(testSet.executableUnderTest, execution.testMethodName)
28+
execution.displayName = execution.displayName?.let { "${testSet.executableUnderTest.name}: $it" }
2929
testMethod(testMethodName, execution.displayName) {
3030
val statics = currentExecution!!.stateBefore.statics
3131
rememberInitialStaticFields(statics)
@@ -37,7 +37,7 @@ class JsCgMethodConstructor(ctx: CgContext) : CgMethodConstructor(ctx) {
3737
}
3838
// build arguments
3939
for ((index, param) in execution.stateBefore.parameters.withIndex()) {
40-
val name = paramNames[executableId]?.get(index)
40+
val name = paramNames[execution.executableToCall ?: testSet.executableUnderTest]?.get(index)
4141
methodArguments += variableConstructor.getOrCreateVariable(param, name)
4242
}
4343
recordActualResult()

0 commit comments

Comments
 (0)