Skip to content

Commit e64c04f

Browse files
committed
Apply review fixes
1 parent 49814bf commit e64c04f

File tree

11 files changed

+257
-223
lines changed

11 files changed

+257
-223
lines changed

utbot-framework/src/main/kotlin/org/utbot/framework/assemble/AssembleModelGenerator.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -343,23 +343,23 @@ class AssembleModelGenerator(private val basePackageName: String) {
343343
private fun assembleMockCompositeModel(compositeModel: UtCompositeModel): UtCompositeModel {
344344
// We have to create a model before the construction of the fields to avoid
345345
// infinite recursion when some mock contains itself as a field.
346-
val assembledModel = UtCompositeModel(
346+
val assembledCompositeModel = UtCompositeModel(
347347
compositeModel.id,
348348
compositeModel.classId,
349349
isMock = true,
350350
)
351351

352-
instantiatedModels[compositeModel] = assembledModel
352+
instantiatedModels[compositeModel] = assembledCompositeModel
353353

354354
val fields = compositeModel.fields.mapValues { assembleModel(it.value) }.toMutableMap()
355355
val mockBehaviour = compositeModel.mocks
356356
.mapValues { models -> models.value.map { assembleModel(it) } }
357357
.toMutableMap()
358358

359-
assembledModel.fields += fields
360-
assembledModel.mocks += mockBehaviour
359+
assembledCompositeModel.fields += fields
360+
assembledCompositeModel.mocks += mockBehaviour
361361

362-
return assembledModel
362+
return assembledCompositeModel
363363
}
364364

365365
/**

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ import org.utbot.framework.codegen.domain.StaticsMocking
99
import org.utbot.framework.codegen.domain.TestFramework
1010
import org.utbot.framework.codegen.domain.models.CgMethodTestSet
1111
import org.utbot.framework.codegen.domain.context.CgContext
12-
import org.utbot.framework.codegen.domain.models.TestClassModelBuilder
12+
import org.utbot.framework.codegen.domain.models.SimpleTestClassModelBuilder
13+
import org.utbot.framework.codegen.domain.models.SpringTestClassModelBuilder
14+
import org.utbot.framework.codegen.domain.models.TestClassModel
1315
import org.utbot.framework.codegen.renderer.CgAbstractRenderer
1416
import org.utbot.framework.codegen.reports.TestsGenerationReport
1517
import org.utbot.framework.codegen.tree.CgSimpleTestClassConstructor
@@ -75,7 +77,9 @@ open class CodeGenerator(
7577
context.withTestClassFileScope {
7678
val astConstructor = CgSimpleTestClassConstructor(context)
7779
val renderer = CgAbstractRenderer.makeRenderer(context)
78-
val testClassModelBuilder = TestClassModelBuilder(context.isSpringClass)
80+
81+
val testClassModelBuilder =
82+
if (context.isSpringClass) SpringTestClassModelBuilder() else SimpleTestClassModelBuilder()
7983

8084
val testClassModel = testClassModelBuilder.createClassModel(classUnderTest, cgTestSets)
8185

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import org.utbot.framework.codegen.domain.models.CgMethodTestSet
2626
import org.utbot.framework.codegen.domain.builtin.TestClassUtilMethodProvider
2727
import org.utbot.framework.codegen.domain.builtin.UtilClassFileMethodProvider
2828
import org.utbot.framework.codegen.domain.builtin.UtilMethodProvider
29-
import org.utbot.framework.codegen.domain.models.TestClassModel
29+
import org.utbot.framework.codegen.domain.models.SimpleTestClassModel
3030
import org.utbot.framework.codegen.domain.models.CgParameterKind
3131
import org.utbot.framework.codegen.services.access.Block
3232
import org.utbot.framework.codegen.tree.EnvironmentFieldStateCache
@@ -295,7 +295,7 @@ interface CgContextOwner {
295295
* This method does almost all the same as [withTestClassScope], but for nested test classes.
296296
* The difference is that instead of working with [outerMostTestClassContext] it works with [currentTestClassContext].
297297
*/
298-
fun <R> withNestedClassScope(testClassModel: TestClassModel, block: () -> R): R
298+
fun <R> withNestedClassScope(testClassModel: SimpleTestClassModel, block: () -> R): R
299299

300300
/**
301301
* Set [mockFrameworkUsed] flag to true if the block is successfully executed
@@ -434,7 +434,7 @@ interface CgContextOwner {
434434
*/
435435
data class CgContext(
436436
override val classUnderTest: ClassId,
437-
override val isSpringClass: Boolean = false,
437+
override val isSpringClass: Boolean = true,
438438
val generateUtilClassFile: Boolean = false,
439439
override var currentExecutable: ExecutableId? = null,
440440
override val collectedExceptions: MutableSet<ClassId> = mutableSetOf(),
@@ -542,7 +542,7 @@ data class CgContext(
542542
}
543543
}
544544

545-
override fun <R> withNestedClassScope(testClassModel: TestClassModel, block: () -> R): R {
545+
override fun <R> withNestedClassScope(testClassModel: SimpleTestClassModel, block: () -> R): R {
546546
val previousCurrentTestClassInfo = currentTestClassContext
547547
val previousCurrentTestClass = currentTestClass
548548
currentTestClass = createClassIdForNestedClass(testClassModel)
@@ -555,7 +555,7 @@ data class CgContext(
555555
}
556556
}
557557

558-
private fun createClassIdForNestedClass(testClassModel: TestClassModel): ClassId {
558+
private fun createClassIdForNestedClass(testClassModel: SimpleTestClassModel): ClassId {
559559
val simpleName = "${testClassModel.classUnderTest.simpleName}Test"
560560
return BuiltinClassId(
561561
canonicalName = currentTestClass.canonicalName + "." + simpleName,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package org.utbot.framework.codegen.domain.models
2+
3+
import org.utbot.framework.plugin.api.ClassId
4+
import org.utbot.framework.plugin.api.util.enclosingClass
5+
6+
open class SimpleTestClassModelBuilder {
7+
open fun createClassModel(classUnderTest: ClassId, testSets: List<CgMethodTestSet>): TestClassModel {
8+
// For each class stores list of methods declared in this class (methods from nested classes are excluded)
9+
val class2methodTestSets = testSets.groupBy { it.executableId.classId }
10+
11+
val classesWithMethodsUnderTest = testSets
12+
.map { it.executableId.classId }
13+
.distinct()
14+
15+
// For each class stores list of its "direct" nested classes
16+
val class2nestedClasses = mutableMapOf<ClassId, MutableSet<ClassId>>()
17+
18+
for (classId in classesWithMethodsUnderTest) {
19+
var currentClass = classId
20+
var enclosingClass = currentClass.enclosingClass
21+
// while we haven't reached the top of nested class hierarchy or the main class under test
22+
while (enclosingClass != null && currentClass != classUnderTest) {
23+
class2nestedClasses.getOrPut(enclosingClass) { mutableSetOf() } += currentClass
24+
currentClass = enclosingClass
25+
enclosingClass = enclosingClass.enclosingClass
26+
}
27+
}
28+
29+
return constructRecursively(classUnderTest, class2methodTestSets, class2nestedClasses)
30+
}
31+
32+
private fun constructRecursively(
33+
clazz: ClassId,
34+
class2methodTestSets: Map<ClassId, List<CgMethodTestSet>>,
35+
class2nestedClasses: Map<ClassId, Set<ClassId>>
36+
): SimpleTestClassModel {
37+
val currentNestedClasses = class2nestedClasses.getOrDefault(clazz, listOf())
38+
val currentMethodTestSets = class2methodTestSets.getOrDefault(clazz, listOf())
39+
return SimpleTestClassModel(
40+
clazz,
41+
currentMethodTestSets,
42+
currentNestedClasses.map {
43+
constructRecursively(it, class2methodTestSets, class2nestedClasses)
44+
}
45+
)
46+
}
47+
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package org.utbot.framework.codegen.domain.models
2+
3+
import org.utbot.framework.plugin.api.ClassId
4+
import org.utbot.framework.plugin.api.UtArrayModel
5+
import org.utbot.framework.plugin.api.UtAssembleModel
6+
import org.utbot.framework.plugin.api.UtClassRefModel
7+
import org.utbot.framework.plugin.api.UtCompositeModel
8+
import org.utbot.framework.plugin.api.UtDirectSetFieldModel
9+
import org.utbot.framework.plugin.api.UtEnumConstantModel
10+
import org.utbot.framework.plugin.api.UtExecutableCallModel
11+
import org.utbot.framework.plugin.api.UtExecutionSuccess
12+
import org.utbot.framework.plugin.api.UtLambdaModel
13+
import org.utbot.framework.plugin.api.UtModel
14+
import org.utbot.framework.plugin.api.UtNullModel
15+
import org.utbot.framework.plugin.api.UtPrimitiveModel
16+
import org.utbot.framework.plugin.api.UtVoidModel
17+
18+
class SpringTestClassModelBuilder: SimpleTestClassModelBuilder() {
19+
20+
override fun createClassModel(classUnderTest: ClassId, testSets: List<CgMethodTestSet>): SpringTestClassModel {
21+
val baseModel = super.createClassModel(classUnderTest, testSets)
22+
val mockedClasses = collectMockedClassIds(classUnderTest, testSets)
23+
24+
return SpringTestClassModel(
25+
baseModel.classUnderTest,
26+
baseModel.methodTestSets,
27+
baseModel.nestedClasses,
28+
classUnderTest,
29+
mockedClasses,
30+
)
31+
}
32+
33+
private fun collectMockedClassIds(
34+
classUnderTest: ClassId,
35+
testSets: List<CgMethodTestSet>,
36+
): Set<ClassId> {
37+
val allModelsInExecution = mutableListOf<UtModel>()
38+
39+
for (testSet in testSets) {
40+
for (execution in testSet.executions) {
41+
execution.stateBefore.thisInstance?.let { allModelsInExecution += it }
42+
execution.stateAfter.thisInstance?.let { allModelsInExecution += it }
43+
44+
allModelsInExecution += execution.stateBefore.parameters
45+
allModelsInExecution += execution.stateAfter.parameters
46+
47+
(execution.result as? UtExecutionSuccess)?.model?.let { allModelsInExecution += it }
48+
}
49+
}
50+
51+
val allConstructedModels = mutableSetOf<UtModel>()
52+
allModelsInExecution.forEach { model -> collectRecursively(model, allConstructedModels) }
53+
54+
return allConstructedModels
55+
.filter { it.isMockComposite() || it.isMockAssemble() }
56+
.map { it.classId }
57+
.filter { it != classUnderTest }
58+
.toSet()
59+
60+
}
61+
62+
private fun collectRecursively(currentModel: UtModel, allModels: MutableSet<UtModel>) {
63+
if (currentModel in allModels) {
64+
return
65+
}
66+
67+
allModels += currentModel
68+
69+
when (currentModel) {
70+
is UtNullModel,
71+
is UtPrimitiveModel,
72+
is UtClassRefModel,
73+
is UtVoidModel,
74+
is UtEnumConstantModel -> {}
75+
is UtLambdaModel -> {
76+
currentModel.capturedValues.forEach { collectRecursively(it, allModels) }
77+
}
78+
is UtArrayModel -> {
79+
currentModel.stores.values.forEach { collectRecursively(it, allModels) }
80+
if (currentModel.stores.count() < currentModel.length) {
81+
collectRecursively(currentModel.constModel, allModels)
82+
}
83+
}
84+
is UtCompositeModel -> {
85+
currentModel.fields.values.forEach { collectRecursively(it, allModels) }
86+
currentModel.mocks.values.asSequence().flatten().forEach { collectRecursively(it, allModels) }
87+
}
88+
is UtAssembleModel -> {
89+
currentModel.origin?.let { collectRecursively(it, allModels) }
90+
91+
currentModel.instantiationCall.instance?.let { collectRecursively(it, allModels) }
92+
currentModel.instantiationCall.params.forEach { collectRecursively(it, allModels) }
93+
94+
currentModel.modificationsChain.forEach { stmt ->
95+
stmt.instance?.let { collectRecursively(it, allModels) }
96+
when (stmt) {
97+
is UtExecutableCallModel -> stmt.params.forEach { collectRecursively(it, allModels) }
98+
is UtDirectSetFieldModel -> collectRecursively(stmt.fieldModel, allModels)
99+
}
100+
}
101+
}
102+
//Python, JavaScript, Go models are not required in Spring
103+
}
104+
}
105+
106+
private fun UtModel.isMockComposite(): Boolean = this is UtCompositeModel && this.isMock
107+
108+
//TODO: Having an assemble model often means that we do not use its origin, so is this composite mock redundant?
109+
private fun UtModel.isMockAssemble(): Boolean = this is UtAssembleModel && this.origin?.isMock == true
110+
}

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

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,34 @@ package org.utbot.framework.codegen.domain.models
22

33
import org.utbot.framework.plugin.api.ClassId
44

5-
// TODO: seems like this class needs to be renamed
65
/**
76
* Stores method test sets in a structure that replicates structure of their methods in [classUnderTest].
87
* I.e., if some method is declared in nested class of [classUnderTest], its testset will be put
98
* in [TestClassModel] in one of [nestedClasses]
9+
*/
10+
abstract class TestClassModel(
11+
val classUnderTest: ClassId,
12+
val methodTestSets: List<CgMethodTestSet>,
13+
val nestedClasses: List<SimpleTestClassModel>,
14+
)
15+
16+
open class SimpleTestClassModel(
17+
classUnderTest: ClassId,
18+
methodTestSets: List<CgMethodTestSet>,
19+
nestedClasses: List<SimpleTestClassModel> = listOf(),
20+
): TestClassModel(classUnderTest, methodTestSets, nestedClasses)
21+
22+
/**
23+
* Extended [SimpleTestClassModel] for Spring analysis reasons
1024
*
1125
* @param injectingMocksClass a class to inject other mocks into
1226
* @param mockedClasses variables of test class to represent mocked instances
1327
*/
14-
class TestClassModel(
15-
val classUnderTest: ClassId,
16-
val methodTestSets: List<CgMethodTestSet>,
17-
val nestedClasses: List<TestClassModel> = listOf(),
28+
class SpringTestClassModel(
29+
classUnderTest: ClassId,
30+
methodTestSets: List<CgMethodTestSet>,
31+
nestedClasses: List<SimpleTestClassModel>,
1832
val injectingMocksClass: ClassId? = null,
1933
val mockedClasses: Set<ClassId> = setOf(),
20-
)
34+
): TestClassModel(classUnderTest, methodTestSets, nestedClasses)
35+

0 commit comments

Comments
 (0)