Skip to content

Commit 0be6fcb

Browse files
Kamenev YuryDamtev
authored andcommitted
Disabled concrete enums processing for when initializing from external statics
1 parent 37b5211 commit 0be6fcb

3 files changed

Lines changed: 93 additions & 17 deletions

File tree

utbot-framework/src/main/kotlin/org/utbot/engine/util/statics/concrete/EnumConcreteUtils.kt

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import soot.SootClass
1515
import soot.SootField
1616
import soot.SootMethod
1717
import soot.Type
18+
import soot.Value
1819
import soot.jimple.StaticFieldRef
1920
import soot.jimple.Stmt
2021
import soot.jimple.internal.JAssignStmt
@@ -154,18 +155,23 @@ fun SootClass.isEnumAffectingExternalStatics(typeResolver: TypeResolver): Boolea
154155
// enum <clinit> active body contains <init> invocations so we can check only <clinit>
155156
val staticInitializer = staticInitializerOrNull() ?: return false
156157

157-
return staticInitializer.isAffectingExternalStatics(this, mutableSetOf(), typeResolver)
158+
val implementedInterfaces = typeResolver
159+
.findOrConstructAncestorsIncludingTypes(type)
160+
.filter { type -> type.sootClass.isInterface }
161+
162+
return staticInitializer.isTouchingExternalStatics(this, mutableSetOf(), implementedInterfaces)
158163
}
159164

160165
/**
161-
* Returns whether [this] method affects any statics from any types except [currentClass] and its interfaces.
166+
* Returns whether [this] method touches any statics from any types
167+
* except [currentClass] and its interfaces in [currentClassImplementedInterfaces].
162168
*
163-
* NOTE: see org.utbot.examples.enums.ClassWithEnum.EnumWithStaticAffectingInit for examples.
169+
* NOTE: see org.utbot.examples.enums.ClassWithEnum.{EnumWithStaticAffectingInit, OuterStaticUsageEnum} for examples.
164170
*/
165-
fun SootMethod.isAffectingExternalStatics(
171+
fun SootMethod.isTouchingExternalStatics(
166172
currentClass: SootClass,
167173
alreadyProcessed: MutableSet<SootMethod>,
168-
typeResolver: TypeResolver
174+
currentClassImplementedInterfaces: List<Type>
169175
): Boolean {
170176
if (this in alreadyProcessed) {
171177
return false
@@ -187,28 +193,48 @@ fun SootMethod.isAffectingExternalStatics(
187193
when (it) {
188194
is JAssignStmt -> {
189195
val leftOp = it.leftOp
196+
val rightOp = it.rightOp
190197

191-
if (leftOp !is StaticFieldRef) {
192-
return@any false
193-
}
194-
195-
val declaringClass = leftOp.field.declaringClass
198+
val assigningOuterStatics =
199+
isExternalStaticField(leftOp, currentClassImplementedInterfaces, currentClass)
196200

197-
val currentClassImplementedInterfaces = typeResolver
198-
.findOrConstructAncestorsIncludingTypes(currentClass.type)
199-
.filter { type -> type.sootClass.isInterface }
200-
val inImplementedInterfaces = declaringClass.type in currentClassImplementedInterfaces
201+
val assignmentFromOuterStatics =
202+
isExternalStaticField(rightOp, currentClassImplementedInterfaces, currentClass)
201203

202-
// check that no system statics are affected (but implemented interfaces fields are allowed)
203-
!(inImplementedInterfaces || declaringClass == currentClass)
204+
assigningOuterStatics || assignmentFromOuterStatics
204205
}
205206
else -> {
206207
if (it.containsInvokeExpr()) {
207-
it.invokeExpr.method.isAffectingExternalStatics(currentClass, alreadyProcessed, typeResolver)
208+
it.invokeExpr.method.isTouchingExternalStatics(
209+
currentClass,
210+
alreadyProcessed,
211+
currentClassImplementedInterfaces
212+
)
208213
} else {
209214
false
210215
}
211216
}
212217
}
213218
}
214219
}
220+
221+
/**
222+
* Determines whether [fieldRef] is static field not from [currentClass]
223+
* (except static fields from all interfaces implemented by [currentClass], stored in [currentClassImplementedInterfaces]).
224+
*/
225+
private fun isExternalStaticField(
226+
fieldRef: Value,
227+
currentClassImplementedInterfaces: List<Type>,
228+
currentClass: SootClass
229+
): Boolean {
230+
if (fieldRef !is StaticFieldRef) {
231+
return false
232+
}
233+
234+
val declaringClass = fieldRef.field.declaringClass
235+
236+
val classInImplementedInterfaces =
237+
declaringClass.type in currentClassImplementedInterfaces
238+
239+
return !(classInImplementedInterfaces || declaringClass == currentClass)
240+
}

utbot-framework/src/test/kotlin/org/utbot/examples/enums/ClassWithEnumTest.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,4 +174,24 @@ class ClassWithEnumTest : AbstractTestCaseGeneratorTest(testClass = ClassWithEnu
174174
)
175175
}
176176
}
177+
178+
@Test
179+
fun testAffectSystemStaticAndUseInitEnumFromIt() {
180+
check(
181+
ClassWithEnum::affectSystemStaticAndInitEnumFromItAndReturnField,
182+
eq(1),
183+
{ r -> r == true },
184+
coverage = DoNotCalculate
185+
)
186+
}
187+
188+
@Test
189+
fun testAffectSystemStaticAndInitEnumFromItAndGetItFromEnumFun() {
190+
check(
191+
ClassWithEnum::affectSystemStaticAndInitEnumFromItAndGetItFromEnumFun,
192+
eq(1),
193+
{ r -> r == true },
194+
coverage = DoNotCalculate
195+
)
196+
}
177197
}

utbot-sample/src/main/java/org/utbot/examples/enums/ClassWithEnum.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,4 +208,34 @@ enum EnumImplementingInterface implements InterfaceWithField {
208208
I_INHERITOR, J_INHERITOR, K_INHERITOR, L_INHERITOR,
209209
M_INHERITOR, N_INHERITOR, O_INHERITOR, P_INHERITOR,
210210
}
211+
212+
boolean affectSystemStaticAndInitEnumFromItAndReturnField() {
213+
int prevStaticValue = ClassWithEnum.staticInt;
214+
staticInt++;
215+
216+
return OuterStaticUsageEnum.A.y != prevStaticValue;
217+
}
218+
219+
boolean affectSystemStaticAndInitEnumFromItAndGetItFromEnumFun() {
220+
int prevStaticValue = ClassWithEnum.staticInt;
221+
staticInt++;
222+
223+
return OuterStaticUsageEnum.A.getOuterStatic() != prevStaticValue;
224+
}
225+
226+
static int staticInt = 0;
227+
228+
enum OuterStaticUsageEnum {
229+
A;
230+
231+
int y;
232+
233+
OuterStaticUsageEnum() {
234+
y = staticInt;
235+
}
236+
237+
int getOuterStatic() {
238+
return staticInt;
239+
}
240+
}
211241
}

0 commit comments

Comments
 (0)