Skip to content

Commit b144498

Browse files
committed
Add support for class fields rendering with annotations
1 parent d3a6d77 commit b144498

File tree

8 files changed

+75
-101
lines changed

8 files changed

+75
-101
lines changed

utbot-framework-api/src/main/kotlin/org/utbot/framework/UtSettings.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ object UtSettings : AbstractSettings(logger, defaultKeyForSettingsPath, defaultS
280280
* @see runInstrumentedProcessWithDebug
281281
* @see org.utbot.intellij.plugin.process.EngineProcess
282282
*/
283-
var runEngineProcessWithDebug by getBooleanProperty(true)
283+
var runEngineProcessWithDebug by getBooleanProperty(false)
284284

285285
/**
286286
* The engine process JDWP agent's port of the instrumented process.

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,14 +161,14 @@ class CgClassBody(
161161

162162
/**
163163
* Field of a class.
164-
* @property classId [ClassId] of the field owner class.
165164
* @property declaration declaration itself.
166165
* @property annotation optional annotation.
166+
* @property classId [ClassId] of the field owner class.
167167
*/
168168
class CgFieldDeclaration(
169-
val classId: ClassId,
170169
val declaration: CgDeclaration,
171170
val annotation: CgAnnotation? = null,
171+
val classId: ClassId? = null,
172172
) : CgElement
173173

174174
/**

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.utbot.framework.codegen.domain.models
22

33
import org.utbot.framework.plugin.api.ClassId
4+
import org.utbot.framework.plugin.api.UtModel
45

56
/**
67
* Stores method test sets in a structure that replicates structure of their methods in [classUnderTest].
@@ -29,7 +30,7 @@ class SpringTestClassModel(
2930
classUnderTest: ClassId,
3031
methodTestSets: List<CgMethodTestSet>,
3132
nestedClasses: List<SimpleTestClassModel>,
32-
val injectingMocksClass: ClassId? = null,
33-
val mockedClasses: Set<ClassId> = setOf(),
33+
val injectedMockModels: List<UtModel> = listOf(),
34+
val mockedModels: List<UtModel> = listOf(),
3435
): TestClassModel(classUnderTest, methodTestSets, nestedClasses)
3536

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

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,27 +21,28 @@ class SpringTestClassModelBuilder: TestClassModelBuilder() {
2121

2222
override fun createTestClassModel(classUnderTest: ClassId, testSets: List<CgMethodTestSet>): SpringTestClassModel {
2323
val baseModel = SimpleTestClassModelBuilder().createTestClassModel(classUnderTest, testSets)
24-
val mockedClasses = collectMockedClassIds(classUnderTest, testSets)
24+
val (injectedModels, mockedModels) = collectInjectedAndMockedModels(classUnderTest, testSets)
2525

2626
return SpringTestClassModel(
2727
baseModel.classUnderTest,
2828
baseModel.methodTestSets,
2929
baseModel.nestedClasses,
30-
classUnderTest,
31-
mockedClasses,
30+
injectedModels,
31+
mockedModels,
3232
)
3333
}
3434

35-
private fun collectMockedClassIds(
35+
private fun collectInjectedAndMockedModels(
3636
classUnderTest: ClassId,
3737
testSets: List<CgMethodTestSet>,
38-
): Set<ClassId> {
38+
): Pair<List<UtModel>, List<UtModel>> {
39+
val thisInstances = mutableListOf<UtModel>()
3940
val allModelsInExecution = mutableListOf<UtModel>()
4041

4142
for (testSet in testSets) {
4243
for (execution in testSet.executions) {
43-
execution.stateBefore.thisInstance?.let { allModelsInExecution += it }
44-
execution.stateAfter.thisInstance?.let { allModelsInExecution += it }
44+
execution.stateBefore.thisInstance?.let { allModelsInExecution += it; thisInstances += it }
45+
execution.stateAfter.thisInstance?.let { allModelsInExecution += it; thisInstances += it }
4546

4647
allModelsInExecution += execution.stateBefore.parameters
4748
allModelsInExecution += execution.stateAfter.parameters
@@ -53,22 +54,19 @@ class SpringTestClassModelBuilder: TestClassModelBuilder() {
5354
val allConstructedModels = mutableSetOf<UtModel>()
5455
allModelsInExecution.forEach { model -> collectRecursively(model, allConstructedModels) }
5556

56-
// make it a return of the current method
57-
listOfUtModels += allConstructedModels
57+
val injectedModels = thisInstances.distinct()
58+
val mockedModels = allConstructedModels
5859
.filter { it.isMockComposite() || it.isMockAssemble() }
59-
.filter { it.classId != classUnderTest }
60+
.filter { it != classUnderTest }
6061
.distinct()
6162

62-
return allConstructedModels
63-
.filter { it.isMockComposite() || it.isMockAssemble() }
64-
.map { it.classId }
65-
.filter { it != classUnderTest }
66-
.toSet()
63+
return injectedModels to mockedModels
6764

6865
}
6966

7067
private fun collectRecursively(currentModel: UtModel, allModels: MutableSet<UtModel>) {
71-
if (currentModel in allModels) {
68+
// TODO: come up with a better way to compare UtCompositeModels
69+
if (allModels.any { it === currentModel }) {
7270
return
7371
}
7472

@@ -115,8 +113,4 @@ class SpringTestClassModelBuilder: TestClassModelBuilder() {
115113

116114
//TODO: Having an assemble model often means that we do not use its origin, so is this composite mock redundant?
117115
private fun UtModel.isMockAssemble(): Boolean = this is UtAssembleModel && this.origin?.isMock == true
118-
119-
companion object {
120-
val listOfUtModels = mutableListOf<UtModel>()
121-
}
122116
}

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

Lines changed: 43 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@ package org.utbot.framework.codegen.tree
22

33
import org.utbot.framework.codegen.domain.builtin.TestClassUtilMethodProvider
44
import org.utbot.framework.codegen.domain.builtin.closeMethodId
5+
import org.utbot.framework.codegen.domain.builtin.injectMocksClassId
6+
import org.utbot.framework.codegen.domain.builtin.mockClassId
57
import org.utbot.framework.codegen.domain.builtin.openMocksMethodId
68
import org.utbot.framework.codegen.domain.context.CgContext
79
import org.utbot.framework.codegen.domain.models.CgAssignment
810
import org.utbot.framework.codegen.domain.models.CgClassBody
911
import org.utbot.framework.codegen.domain.models.CgDeclaration
12+
import org.utbot.framework.codegen.domain.models.CgFieldDeclaration
1013
import org.utbot.framework.codegen.domain.models.CgFrameworkUtilMethod
1114
import org.utbot.framework.codegen.domain.models.CgMethod
1215
import org.utbot.framework.codegen.domain.models.CgMethodCall
@@ -18,7 +21,9 @@ import org.utbot.framework.codegen.domain.models.CgStatementExecutableCall
1821
import org.utbot.framework.codegen.domain.models.CgStaticsRegion
1922
import org.utbot.framework.codegen.domain.models.CgVariable
2023
import org.utbot.framework.codegen.domain.models.SpringTestClassModel
24+
import org.utbot.framework.plugin.api.ClassId
2125
import org.utbot.framework.plugin.api.UtCompositeModel
26+
import org.utbot.framework.plugin.api.UtModel
2227
import org.utbot.framework.plugin.api.util.id
2328
import org.utbot.framework.plugin.api.util.objectClassId
2429

@@ -32,69 +37,11 @@ class CgSpringTestClassConstructor(context: CgContext): CgAbstractTestClassConst
3237

3338
// TODO: support inner classes here
3439

35-
// TODO: create class variables with Mock/InjectMock annotations using testClassModel
36-
37-
val vc = CgComponents.getVariableConstructorBy(context)
38-
val ng = CgComponents.getNameGeneratorBy(context)
39-
40-
// outer things
41-
val listOfInjectMocksUtModels =
42-
testClassModel
43-
.methodTestSets
44-
.flatMap { testSet ->
45-
testSet.executions.map { execution -> execution.stateBefore.thisInstance!! }
46-
}
47-
48-
49-
val mockModels = SpringTestClassModelBuilder.listOfUtModels
50-
//
51-
52-
// inject mock field region
53-
54-
val groupedUtModelsByClassIdInjectMock = listOfInjectMocksUtModels.groupBy { it.classId }
55-
56-
val annotationInjectMock = CgComponents.getStatementConstructorBy(context).annotation(injectMocksClassId)
57-
58-
groupedUtModelsByClassIdInjectMock.forEach { (classId, listOfUtModels) ->
59-
val name = ng.nameFrom(classId)
60-
val declaration =
61-
CgDeclaration(
62-
classId,
63-
name, // is not a mock...
64-
null
65-
)
66-
67-
fields += CgFieldDeclaration(mockClassId, declaration, annotationInjectMock)
68-
val value = vc.getOrCreateVariable(listOfUtModels.first(), name)
69-
CgSpringVariableConstructor.injectingMocksModelsVariables += listOfUtModels to value
70-
}
71-
72-
// endregion
73-
74-
75-
76-
// mock fields region
77-
78-
val groupedUtModelsByClassIdMock = mockModels.groupBy { it.classId }
79-
80-
val annotationMock = CgComponents.getStatementConstructorBy(context).annotation(mockClassId)
81-
82-
groupedUtModelsByClassIdMock.forEach { (classId, listOfUtModels) ->
83-
val name = ng.nameFrom(classId)
84-
val declaration =
85-
CgDeclaration(
86-
classId,
87-
name + "Mock",
88-
null
89-
)
90-
fields += CgFieldDeclaration(mockClassId, declaration, annotationMock)
91-
val value = vc.getOrCreateVariable(listOfUtModels.first(), name)
92-
CgSpringVariableConstructor.mockedModelsVariables += listOfUtModels to value
93-
}
94-
95-
// endregion
96-
40+
val groupedInjectedModelsByClassId = testClassModel.injectedMockModels.groupBy { it.classId }
41+
fields += constructClassFields(groupedInjectedModelsByClassId, injectMocksClassId, isMock = false)
9742

43+
val groupedMockedModelsByClassId = testClassModel.mockedModels.groupBy { it.classId }
44+
fields += constructClassFields(groupedMockedModelsByClassId, mockClassId, isMock = true)
9845

9946
val (closeableField, closeableMethods) = constructMockitoCloseables()
10047
fields += closeableField
@@ -139,7 +86,37 @@ class CgSpringTestClassConstructor(context: CgContext): CgAbstractTestClassConst
13986
return if (regions.any()) regions else null
14087
}
14188

142-
private fun constructMockitoCloseables(): Pair<CgDeclaration, CgMethodsCluster> {
89+
private fun constructClassFields(
90+
groupedModelsByClassId: Map<ClassId, List<UtModel>>,
91+
annotationClassId: ClassId,
92+
isMock: Boolean
93+
): MutableList<CgFieldDeclaration> {
94+
val constructedDeclarations = mutableListOf<CgFieldDeclaration>()
95+
96+
val annotation = statementConstructor.annotation(annotationClassId)
97+
groupedModelsByClassId.forEach { (classId, listOfUtModels) ->
98+
val name = nameGenerator.nameFrom(classId) + if (isMock) "Mock" else ""
99+
val declaration =
100+
CgDeclaration(
101+
classId,
102+
name,
103+
null
104+
)
105+
106+
constructedDeclarations += CgFieldDeclaration(declaration, annotation)
107+
108+
val createdValue = variableConstructor.getOrCreateVariable(listOfUtModels.first(), name)
109+
when (annotationClassId) {
110+
injectMocksClassId -> CgSpringVariableConstructor.injectedMocksModelsVariables += listOfUtModels to createdValue
111+
mockClassId -> CgSpringVariableConstructor.mockedModelsVariables += listOfUtModels to createdValue
112+
else -> error("Unexpected annotation ClassId")
113+
}
114+
}
115+
116+
return constructedDeclarations
117+
}
118+
119+
private fun constructMockitoCloseables(): Pair<CgFieldDeclaration, CgMethodsCluster> {
143120
val mockitoCloseableVarName = "mockitoCloseable"
144121
val mockitoCloseableVarType = java.lang.AutoCloseable::class.id
145122

@@ -151,7 +128,8 @@ class CgSpringTestClassConstructor(context: CgContext): CgAbstractTestClassConst
151128

152129
val mockitoCloseableVariable =
153130
variableConstructor.getOrCreateVariable(mockitoCloseableModel, mockitoCloseableVarName)
154-
val mockitoCloseableField = CgDeclaration(mockitoCloseableVarType, mockitoCloseableVarName, initializer = null)
131+
val mockitoCloseableDeclaration = CgDeclaration(mockitoCloseableVarType, mockitoCloseableVarName, initializer = null)
132+
val mockitoCloseableFieldDeclaration = CgFieldDeclaration(mockitoCloseableDeclaration)
155133

156134
importIfNeeded(openMocksMethodId)
157135

@@ -189,6 +167,6 @@ class CgSpringTestClassConstructor(context: CgContext): CgAbstractTestClassConst
189167
listOf(CgSimpleRegion("Mocking utils", listOf(beforeMethod, afterMethod)))
190168
)
191169

192-
return mockitoCloseableField to methodCluster
170+
return mockitoCloseableFieldDeclaration to methodCluster
193171
}
194172
}

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

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,8 @@ class CgSpringVariableConstructor(context: CgContext) : CgVariableConstructor(co
1313
private val mockFrameworkManager = CgComponents.getMockFrameworkManagerBy(context)
1414

1515
override fun getOrCreateVariable(model: UtModel, name: String?): CgValue {
16-
val alreadyCreatedMock = mockedModelsVariables
17-
.filter { it.key.contains(model) }
18-
.firstOrNull()
19-
?.value
20-
21-
val alreadyCreatedInjectMocks = injectingMocksModelsVariables
22-
.filter { it.key.contains(model) }
23-
.firstOrNull()
24-
?.value
16+
val alreadyCreatedMock = findCgValueByModel(model, mockedModelsVariables)
17+
val alreadyCreatedInjectMocks = findCgValueByModel(model, injectedMocksModelsVariables)
2518

2619
if (alreadyCreatedInjectMocks != null) {
2720
val compModel = model as UtCompositeModel
@@ -44,8 +37,15 @@ class CgSpringVariableConstructor(context: CgContext) : CgVariableConstructor(co
4437
return super.getOrCreateVariable(model, name)
4538
}
4639

40+
41+
private fun findCgValueByModel(model: UtModel, collection: Map<List<UtModel>, CgValue>): CgValue? =
42+
collection
43+
.filter { it.key.contains(model) }
44+
.firstOrNull()
45+
?.value
46+
4747
companion object {
4848
val mockedModelsVariables: MutableMap<List<UtModel>, CgValue> = mutableMapOf()
49-
val injectingMocksModelsVariables: MutableMap<List<UtModel>, CgValue> = mutableMapOf()
49+
val injectedMocksModelsVariables: MutableMap<List<UtModel>, CgValue> = mutableMapOf()
5050
}
5151
}

utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/process/EngineProcess.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ class EngineProcess private constructor(val project: Project, private val classN
102102
private fun suspendValue(): String = if (UtSettings.suspendEngineProcessExecutionInDebugMode) "y" else "n"
103103

104104
private val debugArgument: String?
105-
get() = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=${suspendValue()},quiet=y,address=${UtSettings.engineProcessDebugPort}"
105+
get() = "-agentlib:jdwp=transport=dt_socket,server=n,suspend=${suspendValue()},quiet=y,address=${UtSettings.engineProcessDebugPort}"
106106
.takeIf { UtSettings.runEngineProcessWithDebug }
107107

108108
private val javaExecutablePathString: Path

utbot-js/src/main/kotlin/framework/codegen/model/constructor/visitor/CgJsRenderer.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import org.utbot.framework.codegen.domain.models.CgFieldAccess
2323
import org.utbot.framework.codegen.domain.models.CgFieldDeclaration
2424
import org.utbot.framework.codegen.domain.models.CgForLoop
2525
import org.utbot.framework.codegen.domain.models.CgFormattedString
26+
import org.utbot.framework.codegen.domain.models.CgFrameworkUtilMethod
2627
import org.utbot.framework.codegen.domain.models.CgGetJavaClass
2728
import org.utbot.framework.codegen.domain.models.CgGetKotlinClass
2829
import org.utbot.framework.codegen.domain.models.CgGetLength

0 commit comments

Comments
 (0)