Skip to content

Commit 88ba10c

Browse files
committed
Significantly improve modifiers processing in fields modificators seacher
1 parent 122d408 commit 88ba10c

File tree

11 files changed

+45
-38
lines changed

11 files changed

+45
-38
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.utbot.examples.assemble;
2+
3+
/**
4+
* Need to be located at the same package as [AssembleTestUtils]
5+
* because requires a setter for package-private field.
6+
*/
7+
public class DefaultPackagePrivateField {
8+
int z = 10;
9+
}

utbot-framework-test/src/main/java/org/utbot/examples/assemble/defaults/DefaultFieldModifiedInConstructor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package org.utbot.examples.assemble.defaults;
22

33
public class DefaultFieldModifiedInConstructor {
4-
int z;
4+
public int z;
55

66
@SuppressWarnings("Unused")
77
DefaultFieldModifiedInConstructor(int z_) {

utbot-framework-test/src/main/java/org/utbot/examples/assemble/defaults/DefaultPackagePrivateField.java

Lines changed: 0 additions & 5 deletions
This file was deleted.

utbot-framework-test/src/test/kotlin/org/utbot/framework/assemble/AssembleModelGeneratorTests.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import org.utbot.examples.assemble.defaults.DefaultField
3535
import org.utbot.examples.assemble.defaults.DefaultFieldModifiedInConstructor
3636
import org.utbot.examples.assemble.defaults.DefaultFieldWithDirectAccessor
3737
import org.utbot.examples.assemble.defaults.DefaultFieldWithSetter
38-
import org.utbot.examples.assemble.defaults.DefaultPackagePrivateField
38+
import org.utbot.examples.assemble.DefaultPackagePrivateField
3939
import org.utbot.examples.assemble.statics.StaticField
4040
import org.utbot.framework.plugin.api.ClassId
4141
import org.utbot.framework.plugin.api.ExecutableId
@@ -58,7 +58,6 @@ import org.utbot.framework.util.SootUtils
5858
import org.utbot.framework.util.instanceCounter
5959
import org.utbot.framework.util.modelIdCounter
6060
import kotlin.reflect.full.functions
61-
import org.utbot.examples.assemble.*
6261
import org.utbot.framework.codegen.model.constructor.util.arrayTypeOf
6362

6463
/**
@@ -1448,9 +1447,9 @@ class AssembleModelGeneratorTests {
14481447
private fun createModelsAndAssert(
14491448
models: List<UtModel>,
14501449
expectedModelRepresentations: List<String?>,
1451-
assembleTestUtils: ExecutableId = AssembleTestUtils::class.id.allMethods.first(),
1450+
assembleTestDummyMethod: ExecutableId = AssembleTestUtils::class.id.allMethods.first(),
14521451
) {
1453-
val modelsMap = AssembleModelGenerator(assembleTestUtils.classId.packageName).createAssembleModels(models)
1452+
val modelsMap = AssembleModelGenerator(assembleTestDummyMethod).createAssembleModels(models)
14541453
//we sort values to fix order of models somehow (IdentityHashMap does not guarantee the order)
14551454
val assembleModels = modelsMap.values
14561455
.filterIsInstance<UtAssembleModel>()

utbot-framework-test/src/test/kotlin/org/utbot/framework/modificators/UtBotFieldModificatorsTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ internal class UtBotFieldModificatorsTest {
192192

193193
//We use sorting here to make comparing with sorted in advance expected collections easier
194194
private fun runFieldModificatorsSearch(analysisMode: AnalysisMode) =
195-
fieldsModificatorsSearcher.findModificators(analysisMode, PrimitiveModifications::class.java.packageName)
195+
fieldsModificatorsSearcher.findModificators(analysisMode, null)
196196
.map { (key, value) ->
197197
val modificatorNames = value.filterNot { it.name.startsWith("direct_set_") }.map { it.name }
198198
key.name to modificatorNames.toSortedSet()

utbot-framework/src/main/kotlin/org/utbot/engine/Resolver.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ class Resolver(
133133
private val instrumentation = mutableListOf<UtInstrumentation>()
134134
private val requiredInstanceFields = mutableMapOf<Address, Set<FieldId>>()
135135

136-
private val assembleModelGenerator = AssembleModelGenerator(methodUnderTest.classId.packageName)
136+
private val assembleModelGenerator = AssembleModelGenerator(methodUnderTest)
137137

138138
/**
139139
* Contains FieldId of the static field which is construction at the moment and null of there is no such field.

utbot-framework/src/main/kotlin/org/utbot/engine/UtBotSymbolicEngine.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,7 @@ private suspend fun ConcreteExecutor<UtConcreteExecutionResult, UtExecutionInstr
639639
methodUnderTest.signature,
640640
arrayOf(),
641641
parameters = UtConcreteExecutionData(stateBefore, instrumentation)
642-
).convertToAssemble(methodUnderTest.classId.packageName)
642+
).convertToAssemble(methodUnderTest)
643643

644644
/**
645645
* Before pushing our states for concrete execution, we have to be sure that every state is consistent.

utbot-framework/src/main/kotlin/org/utbot/external/api/UtModelFactory.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import org.utbot.framework.plugin.api.UtArrayModel
88
import org.utbot.framework.plugin.api.UtClassRefModel
99
import org.utbot.framework.plugin.api.UtCompositeModel
1010
import org.utbot.framework.plugin.api.UtModel
11+
import org.utbot.framework.plugin.api.util.executableId
1112
import org.utbot.framework.plugin.api.util.id
1213
import java.lang.reflect.Field
1314
import java.lang.reflect.Method
@@ -48,7 +49,7 @@ class UtModelFactory(
4849
classUnderTest: Class<*>,
4950
models: List<UtModel>
5051
): IdentityHashMap<UtModel, UtModel> =
51-
AssembleModelGenerator(classUnderTest.packageName)
52+
AssembleModelGenerator(methodUnderTest.executableId)
5253
.createAssembleModels(models)
5354

5455
@JvmOverloads

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

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ import java.util.IdentityHashMap
4949
*
5050
* Note: Caches class related information, can be reused if classes don't change.
5151
*/
52-
class AssembleModelGenerator(private val methodPackageName: String) {
52+
class AssembleModelGenerator(private val methodUnderTest: ExecutableId) {
5353

5454
//Instantiated models are stored to avoid cyclic references during reference graph analysis
5555
private val instantiatedModels: IdentityHashMap<UtModel, UtReferenceModel> =
@@ -256,7 +256,7 @@ class AssembleModelGenerator(private val methodPackageName: String) {
256256
if (fieldId.isFinal) {
257257
throw AssembleException("Final field $fieldId can't be set in an object of the class $classId")
258258
}
259-
if (!fieldId.type.isAccessibleFrom(methodPackageName)) {
259+
if (!fieldId.type.isAccessibleFrom(methodUnderTest.classId.packageName)) {
260260
throw AssembleException(
261261
"Field $fieldId can't be set in an object of the class $classId because its type is inaccessible"
262262
)
@@ -265,7 +265,8 @@ class AssembleModelGenerator(private val methodPackageName: String) {
265265
if (fieldId in constructorInfo.affectedFields ||
266266
(fieldId !in constructorInfo.setFields && !fieldModel.hasDefaultValue())
267267
) {
268-
val modifierCall = modifierCall(this, fieldId, assembleModel(fieldModel))
268+
val assembledModel = assembleModel(fieldModel)
269+
val modifierCall = modifierCall(this, fieldId, assembledModel)
269270
callChain.add(modifierCall)
270271
}
271272
}
@@ -397,10 +398,10 @@ class AssembleModelGenerator(private val methodPackageName: String) {
397398
}
398399

399400
private val ClassId.isVisible : Boolean
400-
get() = this.isPublic || !this.isPrivate && this.packageName.startsWith(methodPackageName)
401+
get() = this.isPublic || !this.isPrivate && this.packageName.startsWith(methodUnderTest.classId.packageName)
401402

402403
private val Constructor<*>.isVisible : Boolean
403-
get() = this.isPublic || !this.isPrivate && this.declaringClass.packageName.startsWith(methodPackageName)
404+
get() = this.isPublic || !this.isPrivate && this.declaringClass.packageName.startsWith(methodUnderTest.classId.packageName)
404405

405406
/**
406407
* Creates setter or direct setter call to set a field.
@@ -440,7 +441,7 @@ class AssembleModelGenerator(private val methodPackageName: String) {
440441
*/
441442
private fun findSettersAndDirectAccessors(classId: ClassId): Map<FieldId, StatementId> {
442443
val allModificatorsOfClass = modificatorsSearcher
443-
.findModificators(SettersAndDirectAccessors, methodPackageName)
444+
.findModificators(SettersAndDirectAccessors, methodUnderTest)
444445
.map { it.key to it.value.filter { st -> st.classId == classId } }
445446

446447
return allModificatorsOfClass

utbot-framework/src/main/kotlin/org/utbot/framework/concrete/UtExecutionInstrumentation.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import org.utbot.framework.UtSettings
88
import org.utbot.framework.assemble.AssembleModelGenerator
99
import org.utbot.framework.plugin.api.Coverage
1010
import org.utbot.framework.plugin.api.EnvironmentModels
11+
import org.utbot.framework.plugin.api.ExecutableId
1112
import org.utbot.framework.plugin.api.FieldId
1213
import org.utbot.framework.plugin.api.Instruction
1314
import org.utbot.framework.plugin.api.MissingState
@@ -98,12 +99,10 @@ class UtConcreteExecutionResult(
9899
*
99100
* @return [UtConcreteExecutionResult] with converted models.
100101
*/
101-
fun convertToAssemble(
102-
packageName: String
103-
): UtConcreteExecutionResult {
102+
fun convertToAssemble(methodUnderTest: ExecutableId): UtConcreteExecutionResult {
104103
val allModels = collectAllModels()
105104

106-
val modelsToAssembleModels = AssembleModelGenerator(packageName).createAssembleModels(allModels)
105+
val modelsToAssembleModels = AssembleModelGenerator(methodUnderTest).createAssembleModels(allModels)
107106
return updateWithAssembleModels(modelsToAssembleModels)
108107
}
109108

utbot-framework/src/main/kotlin/org/utbot/framework/modifications/UtBotFieldsModificatorsSearcher.kt

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package org.utbot.framework.modifications
22

33
import org.utbot.framework.plugin.api.ClassId
4+
import org.utbot.framework.plugin.api.ExecutableId
45
import org.utbot.framework.plugin.api.FieldId
56
import org.utbot.framework.plugin.api.StatementId
7+
import org.utbot.framework.plugin.api.util.isSubtypeOf
68

79
class UtBotFieldsModificatorsSearcher {
810

@@ -16,35 +18,36 @@ class UtBotFieldsModificatorsSearcher {
1618
* Finds field modificators.
1719
*
1820
* @param analysisMode represents which type of modificators (e.g. setters) are considered.
19-
* @param basePackageName describes a location of package-private methods that need to be considered.
21+
* @param methodUnderTest describes an analyzed method an it's location.
2022
*/
21-
fun findModificators(analysisMode: AnalysisMode, basePackageName: String? = null): Map<FieldId, Set<StatementId>> {
23+
fun findModificators(analysisMode: AnalysisMode, methodUnderTest: ExecutableId? = null): Map<FieldId, Set<StatementId>> {
2224
val modificators = findModificators(analysisMode)
2325

24-
if (basePackageName == null) {
26+
if (methodUnderTest == null) {
2527
return modificators
2628
}
2729

2830
val filteredModifications = mutableMapOf<FieldId, Set<StatementId>>()
2931
for ((fieldId, statements) in modificators) {
30-
val filteredStmts = statements.filter { stmt -> fieldId.isAccessibleBy(stmt, basePackageName!!) }
32+
val filteredStmts = statements.filter { stmt -> fieldId.isAccessibleBy(stmt, methodUnderTest!!) }
3133
filteredModifications[fieldId] = filteredStmts.toSet()
3234
}
3335

3436
return filteredModifications
3537
}
3638

37-
private fun FieldId.isAccessibleBy(statementId: StatementId, basePackageName: String): Boolean {
39+
/**
40+
* Verifies that this field is accessible with [statementId] from the location of [methodUnderTest].
41+
*/
42+
private fun FieldId.isAccessibleBy(statementId: StatementId, methodUnderTest: ExecutableId): Boolean {
43+
val basePackageName = methodUnderTest.classId.packageName
3844
val classPackageName = statementId.classId.packageName
39-
if (basePackageName == "") {
40-
return classPackageName == ""
41-
} else {
42-
if (this.isPublic) return true
43-
if (this.isProtected) return classPackageName.startsWith(basePackageName)
44-
if (this.isPackagePrivate) return classPackageName == basePackageName
45-
//for private fields no filtering based on package names is required
46-
return true
47-
}
45+
46+
if (this.isPublic) return true
47+
if (this.isProtected) return classPackageName == basePackageName || statementId.classId.isSubtypeOf(methodUnderTest.classId)
48+
if (this.isPackagePrivate) return classPackageName == basePackageName
49+
if (this.isPrivate) methodUnderTest.classId == statementId.classId
50+
return true
4851
}
4952

5053
private fun findModificators(analysisMode: AnalysisMode): Map<FieldId, Set<StatementId>> {

0 commit comments

Comments
 (0)