Skip to content

Commit 08481e4

Browse files
authored
Fix no targets for invocation for abstract this type (#1626)
1 parent f83d93b commit 08481e4

File tree

3 files changed

+93
-2
lines changed

3 files changed

+93
-2
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package org.utbot.examples.objects
2+
3+
import org.junit.jupiter.api.Test
4+
import org.junit.jupiter.api.assertThrows
5+
import org.utbot.testcheckers.eq
6+
import org.utbot.testing.UtValueTestCaseChecker
7+
8+
class AbstractAnonymousClassTest : UtValueTestCaseChecker(testClass = AbstractAnonymousClass::class) {
9+
@Test
10+
fun testNonOverriddenMethod() {
11+
check(
12+
AbstractAnonymousClass::methodWithoutOverrides,
13+
eq(1)
14+
)
15+
}
16+
17+
@Test
18+
fun testOverriddenMethod() {
19+
// check we have error during execution
20+
assertThrows<org.opentest4j.AssertionFailedError> {
21+
check(
22+
AbstractAnonymousClass::methodWithOverride,
23+
eq(0)
24+
)
25+
}
26+
}
27+
}

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

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,7 +1365,45 @@ 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+
require(possibleTypes.isNotEmpty()) {
1378+
"We do not support testing for abstract classes (or interfaces) without any non-abstract " +
1379+
"inheritors (implementors). Probably, it'll be supported in the future."
1380+
}
1381+
1382+
val possibleTypesWithNonOverriddenMethod = possibleTypes
1383+
.filterTo(mutableSetOf()) {
1384+
val methods = (it as RefType).sootClass.methods
1385+
methods.none { method ->
1386+
val methodUnderTest = environment.method
1387+
val parameterTypes = method.parameterTypes
1388+
1389+
method.name == methodUnderTest.name && parameterTypes == methodUnderTest.parameterTypes
1390+
}
1391+
}
1392+
1393+
require(possibleTypesWithNonOverriddenMethod.isNotEmpty()) {
1394+
"There is no instantiatable inheritor of the class under test that does not override " +
1395+
"a method given for testing"
1396+
}
1397+
1398+
TypeStorage.constructTypeStorageUnsafe(type, possibleTypesWithNonOverriddenMethod)
1399+
} else {
1400+
// If we create a `this` instance and its type is instantiatable,
1401+
// we should construct a type storage with single type
1402+
TypeStorage.constructTypeStorageWithSingleType(type)
1403+
}
1404+
} else {
1405+
typeStoragePossiblyWithOverriddenTypes
1406+
}
13691407
}
13701408

13711409
val typeHardConstraint = typeRegistry.typeConstraint(addr, typeStorage).all().asHardConstraint()
@@ -2238,7 +2276,7 @@ class Traverser(
22382276
if (type.sootClass.isEnum) {
22392277
createEnum(type, addr)
22402278
} else {
2241-
createObject(addr, type, useConcreteType = addr.isThisAddr, mockInfoGenerator)
2279+
createObject(addr, type, useConcreteType = false, mockInfoGenerator)
22422280
}
22432281
}
22442282
is VoidType -> voidValue

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,22 @@ 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 methodWithOverride(int x, int y) {
12+
return y + addNumber(x);
13+
}
14+
15+
public int addFortyTwo(int x) {
16+
return x + 42;
17+
}
18+
19+
public int addNumber(int x) {
20+
return x + 27;
21+
}
22+
723
public static AbstractAnonymousClass getInstance(int x) {
824
if (x % 2 == 0) {
925
return new AnonymousClassAlternative();
@@ -19,6 +35,11 @@ int constValue() {
1935
int add(int x) {
2036
return x + 15;
2137
}
38+
39+
@Override
40+
public int methodWithOverride(int x, int y) {
41+
return x + 37;
42+
}
2243
};
2344
}
2445
}
@@ -33,4 +54,9 @@ int constValue() {
3354
int add(int x) {
3455
return x + 1;
3556
}
57+
58+
@Override
59+
public int methodWithOverride(int x, int y) {
60+
return x + 17;
61+
}
3662
}

0 commit comments

Comments
 (0)