Skip to content

Commit f6c2b49

Browse files
committed
Fix no targets for invocation for abstract this type
1 parent 31713eb commit f6c2b49

File tree

3 files changed

+58
-2
lines changed

3 files changed

+58
-2
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package org.utbot.examples.objects
2+
3+
import org.junit.jupiter.api.Test
4+
import org.utbot.testcheckers.eq
5+
import org.utbot.testing.UtValueTestCaseChecker
6+
7+
class AbstractAnonymousClassTest : UtValueTestCaseChecker(testClass = AbstractAnonymousClass::class) {
8+
@Test
9+
fun testNonOverriddenMethod() {
10+
check(
11+
AbstractAnonymousClass::methodWithoutOverrides,
12+
eq(1)
13+
)
14+
}
15+
}

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

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,7 +1365,40 @@ class Traverser(
13651365
possibleConcreteTypes
13661366
)
13671367
} else {
1368-
typeStoragePossiblyWithOverriddenTypes
1368+
if (addr.isThisAddr) {
1369+
val possibleTypes = typeStoragePossiblyWithOverriddenTypes.possibleConcreteTypes
1370+
val isTypeInappropriate = type.sootClass?.isInappropriate == true
1371+
1372+
// If we're trying to construct this instance and it has an inappropriate type,
1373+
// we won't be able to instantiate its instance in resulting tests.
1374+
// Therefore, we have to test one of its inheritors that does not override
1375+
// the method under test
1376+
if (isTypeInappropriate) {
1377+
val possibleTypesWithNonOverriddenMethod = possibleTypes
1378+
.filterTo(mutableSetOf()) {
1379+
val methods = (it as RefType).sootClass.methods
1380+
methods.none { method ->
1381+
val methodUnderTest = environment.method
1382+
val parameterTypes = method.parameterTypes
1383+
1384+
method.name == methodUnderTest.name && parameterTypes == methodUnderTest.parameterTypes
1385+
}
1386+
}
1387+
1388+
require(possibleTypesWithNonOverriddenMethod.isNotEmpty()) {
1389+
"We do not support testing for abstract classes (or interfaces) without any non-abstract " +
1390+
"inheritors (implementors). Probably, it'll be supported in the future."
1391+
}
1392+
1393+
TypeStorage.constructTypeStorageUnsafe(type, possibleTypesWithNonOverriddenMethod)
1394+
} else {
1395+
// If we create a `this` instance and its type is instantiatable,
1396+
// we should construct a type storage with single type
1397+
TypeStorage.constructTypeStorageWithSingleType(type)
1398+
}
1399+
} else {
1400+
typeStoragePossiblyWithOverriddenTypes
1401+
}
13691402
}
13701403

13711404
val typeHardConstraint = typeRegistry.typeConstraint(addr, typeStorage).all().asHardConstraint()
@@ -2238,7 +2271,7 @@ class Traverser(
22382271
if (type.sootClass.isEnum) {
22392272
createEnum(type, addr)
22402273
} else {
2241-
createObject(addr, type, useConcreteType = addr.isThisAddr, mockInfoGenerator)
2274+
createObject(addr, type, useConcreteType = false, mockInfoGenerator)
22422275
}
22432276
}
22442277
is VoidType -> voidValue

utbot-sample/src/main/java/org/utbot/examples/objects/AbstractAnonymousClass.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ abstract class AbstractAnonymousClass {
44
abstract int constValue();
55
abstract int add(int x);
66

7+
public int methodWithoutOverrides(int x, int y) {
8+
return y + addFortyTwo(x);
9+
}
10+
11+
public int addFortyTwo(int x) {
12+
return x + 42;
13+
}
14+
715
public static AbstractAnonymousClass getInstance(int x) {
816
if (x % 2 == 0) {
917
return new AnonymousClassAlternative();

0 commit comments

Comments
 (0)