From 7e6602bc629dcb62a7b5a146a36dabd80b54b887 Mon Sep 17 00:00:00 2001 From: Rustam Sadykov Date: Mon, 19 Sep 2022 16:16:32 +0300 Subject: [PATCH 1/3] fix wrapper concrete types --- .../org/utbot/engine/ArrayObjectWrappers.kt | 9 +++++++- .../org/utbot/engine/CollectionWrappers.kt | 10 ++++++++- .../src/main/kotlin/org/utbot/engine/Mocks.kt | 15 +++++++------ .../kotlin/org/utbot/engine/ObjectWrappers.kt | 21 +++++++++++++------ .../org/utbot/engine/OptionalWrapper.kt | 5 ++++- .../utbot/engine/SecurityManagerWrapper.kt | 4 ++++ .../kotlin/org/utbot/engine/StreamWrappers.kt | 4 ++++ .../main/kotlin/org/utbot/engine/Strings.kt | 16 +++++++++++--- .../kotlin/org/utbot/engine/SymbolicValue.kt | 7 +++++-- 9 files changed, 71 insertions(+), 20 deletions(-) diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/ArrayObjectWrappers.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/ArrayObjectWrappers.kt index 6671f25ac2..4c444f9c9b 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/ArrayObjectWrappers.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/ArrayObjectWrappers.kt @@ -25,7 +25,6 @@ import org.utbot.framework.plugin.api.UtModel import org.utbot.framework.plugin.api.UtNullModel import org.utbot.framework.plugin.api.UtPrimitiveModel import org.utbot.framework.plugin.api.getIdOrThrow -import org.utbot.framework.plugin.api.idOrNull import org.utbot.framework.plugin.api.util.id import org.utbot.framework.plugin.api.util.objectArrayClassId import org.utbot.framework.plugin.api.util.objectClassId @@ -34,6 +33,7 @@ import soot.Scene import soot.SootClass import soot.SootField import soot.SootMethod +import soot.Type val rangeModifiableArrayId: ClassId = RangeModifiableUnlimitedArray::class.id @@ -264,6 +264,9 @@ class RangeModifiableUnlimitedArrayWrapper : WrapperInterface { return resultModel } + override fun getPotentialPossibleTypes(type: Type): Set = + setOf(ARRAY_OBJECT_TYPE) + companion object { internal val rangeModifiableArrayClass: SootClass get() = Scene.v().getSootClass(rangeModifiableArrayId.name) @@ -277,6 +280,7 @@ class RangeModifiableUnlimitedArrayWrapper : WrapperInterface { } val associativeArrayId: ClassId = AssociativeArray::class.id +val associativeArrayType: Type = Scene.v().getSootClass(AssociativeArray::class.java.canonicalName).type class AssociativeArrayWrapper : WrapperInterface { @@ -415,6 +419,9 @@ class AssociativeArrayWrapper : WrapperInterface { return model } + override fun getPotentialPossibleTypes(type: Type): Set = + setOf(associativeArrayType) + private fun Traverser.getStorageArrayField(addr: UtAddrExpression) = getArrayField(addr, associativeArrayClass, storageField) diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/CollectionWrappers.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/CollectionWrappers.kt index 40add8087f..bbda8a7633 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/CollectionWrappers.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/CollectionWrappers.kt @@ -26,20 +26,22 @@ import org.utbot.framework.plugin.api.UtNullModel import org.utbot.framework.plugin.api.UtStatementModel import org.utbot.framework.plugin.api.classId import org.utbot.framework.plugin.api.getIdOrThrow -import org.utbot.framework.util.graph import org.utbot.framework.plugin.api.id import org.utbot.framework.plugin.api.util.booleanClassId import org.utbot.framework.plugin.api.util.constructorId import org.utbot.framework.plugin.api.util.id import org.utbot.framework.plugin.api.util.methodId import org.utbot.framework.plugin.api.util.objectClassId +import org.utbot.framework.util.graph import org.utbot.framework.util.nextModelName +import soot.ArrayType import soot.IntType import soot.RefType import soot.Scene import soot.SootClass import soot.SootField import soot.SootMethod +import soot.Type abstract class BaseOverriddenWrapper(protected val overriddenClassName: String) : WrapperInterface { val overriddenClass: SootClass = Scene.v().getSootClass(overriddenClassName) @@ -130,6 +132,9 @@ abstract class BaseContainerWrapper(containerClassName: String) : BaseOverridden } } + override fun getPotentialPossibleTypes(type: Type): Set = + setOf(Scene.v().getSootClass(chooseClassIdWithConstructor(type.classId).canonicalName).type) + /** * Method returns list of parameter models that will be passed to [modificationMethodId] * while construction modification chain in [UtAssembleModel] for the specified [wrapper] @@ -398,6 +403,9 @@ private val UT_GENERIC_ASSOCIATIVE_CLASS private val UT_GENERIC_ASSOCIATIVE_SET_EQUAL_GENERIC_TYPE_SIGNATURE = UT_GENERIC_ASSOCIATIVE_CLASS.getMethodByName(UtGenericAssociative<*, *>::setEqualGenericType.name).signature +val ARRAY_OBJECT_TYPE: Type + get() = ArrayType.v(OBJECT_TYPE, 1) + val ARRAY_LIST_TYPE: RefType get() = Scene.v().getSootClass(java.util.ArrayList::class.java.canonicalName).type val LINKED_LIST_TYPE: RefType diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/Mocks.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/Mocks.kt index 83690318cf..5c26161223 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/Mocks.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/Mocks.kt @@ -1,11 +1,15 @@ package org.utbot.engine +import java.util.concurrent.atomic.AtomicInteger +import kotlin.reflect.KFunction2 +import kotlin.reflect.KFunction5 +import kotlinx.collections.immutable.persistentListOf import org.utbot.api.mock.UtMock -import org.utbot.common.packageName import org.utbot.engine.overrides.UtArrayMock import org.utbot.engine.overrides.UtLogicMock import org.utbot.engine.overrides.UtOverrideMock import org.utbot.engine.pc.UtAddrExpression +import org.utbot.engine.util.mockListeners.MockListenerController import org.utbot.framework.plugin.api.ClassId import org.utbot.framework.plugin.api.FieldId import org.utbot.framework.plugin.api.MethodId @@ -14,17 +18,13 @@ import org.utbot.framework.plugin.api.id import org.utbot.framework.plugin.api.util.id import org.utbot.framework.plugin.api.util.isRefType import org.utbot.framework.util.executableId -import java.util.concurrent.atomic.AtomicInteger -import kotlin.reflect.KFunction2 -import kotlin.reflect.KFunction5 -import kotlinx.collections.immutable.persistentListOf -import org.utbot.engine.util.mockListeners.MockListenerController import org.utbot.framework.util.isInaccessibleViaReflection import soot.BooleanType import soot.RefType import soot.Scene import soot.SootClass import soot.SootMethod +import soot.Type /** * Generates mock with address provided. @@ -307,6 +307,9 @@ class UtMockWrapper( override fun value(resolver: Resolver, wrapper: ObjectValue): UtModel = TODO("value on mock called: $this") + override fun getPotentialPossibleTypes(type: Type): Set = + setOf(this.type) + override fun toString() = "UtMock(type=$type, target=$mockInfo)" } diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/ObjectWrappers.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/ObjectWrappers.kt index 87e7470496..fa0db83864 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/ObjectWrappers.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/ObjectWrappers.kt @@ -1,5 +1,11 @@ package org.utbot.engine +import java.util.Optional +import java.util.OptionalDouble +import java.util.OptionalInt +import java.util.OptionalLong +import java.util.concurrent.CopyOnWriteArrayList +import kotlin.reflect.KClass import org.utbot.common.WorkaroundReason.MAKE_SYMBOLIC import org.utbot.common.workaround import org.utbot.engine.UtListClass.UT_ARRAY_LIST @@ -34,12 +40,7 @@ import soot.RefType import soot.Scene import soot.SootClass import soot.SootMethod -import java.util.Optional -import java.util.OptionalDouble -import java.util.OptionalInt -import java.util.OptionalLong -import java.util.concurrent.CopyOnWriteArrayList -import kotlin.reflect.KClass +import soot.Type typealias TypeToBeWrapped = RefType typealias WrapperType = RefType @@ -222,6 +223,11 @@ interface WrapperInterface { ): List fun value(resolver: Resolver, wrapper: ObjectValue): UtModel + + /** + * Returns list of types that can be produced by [value] method. + */ + fun getPotentialPossibleTypes(type: Type): Set } // TODO: perhaps we have to have wrapper around concrete value here @@ -252,4 +258,7 @@ data class ThrowableWrapper(val throwable: Throwable) : WrapperInterface { return UtAssembleModel(addr, classId, modelName, instantiationCall) } + + override fun getPotentialPossibleTypes(type: Type): Set = + setOf(Scene.v().getSootClass(throwable.javaClass.canonicalName).type) } \ No newline at end of file diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/OptionalWrapper.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/OptionalWrapper.kt index 7fc3930ba5..ba76eb559a 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/OptionalWrapper.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/OptionalWrapper.kt @@ -16,7 +16,6 @@ import org.utbot.framework.plugin.api.UtAssembleModel import org.utbot.framework.plugin.api.UtExecutableCallModel import org.utbot.framework.plugin.api.UtNullModel import org.utbot.framework.plugin.api.UtPrimitiveModel -import org.utbot.framework.plugin.api.UtStatementModel import org.utbot.framework.plugin.api.classId import org.utbot.framework.plugin.api.id import org.utbot.framework.plugin.api.util.defaultValueModel @@ -27,6 +26,7 @@ import org.utbot.framework.plugin.api.util.objectClassId import org.utbot.framework.util.nextModelName import soot.Scene import soot.SootMethod +import soot.Type /** * Auxiliary enum class for specifying an implementation for [OptionalWrapper], that it will use. @@ -94,6 +94,9 @@ class OptionalWrapper(private val utOptionalClass: UtOptionalClass) : BaseOverri return UtAssembleModel(addr, classId, modelName, instantiationCall) } + override fun getPotentialPossibleTypes(type: Type): Set = + setOf(type) + private fun Resolver.instantiationFactoryCallModel(classId: ClassId, wrapper: ObjectValue) : UtExecutableCallModel { val valueField = FieldId(overriddenClass.id, "value") val isPresentFieldId = FieldId(overriddenClass.id, "isPresent") diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/SecurityManagerWrapper.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/SecurityManagerWrapper.kt index 33f8511dfa..728b233f26 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/SecurityManagerWrapper.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/SecurityManagerWrapper.kt @@ -10,6 +10,7 @@ import org.utbot.framework.util.nextModelName import soot.Scene import soot.SootClass import soot.SootMethod +import soot.Type class SecurityManagerWrapper : BaseOverriddenWrapper(utSecurityManagerClass.name) { private val baseModelName: String = "securityManager" @@ -37,6 +38,9 @@ class SecurityManagerWrapper : BaseOverriddenWrapper(utSecurityManagerClass.name return UtAssembleModel(addr, classId, modelName, instantiationCall) } + override fun getPotentialPossibleTypes(type: Type): Set = + setOf(type) + companion object { val utSecurityManagerClass: SootClass get() = Scene.v().getSootClass(UtSecurityManager::class.qualifiedName) diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/StreamWrappers.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/StreamWrappers.kt index 992e3ac694..922785d57e 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/StreamWrappers.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/StreamWrappers.kt @@ -16,6 +16,7 @@ import org.utbot.framework.plugin.api.util.objectClassId import org.utbot.framework.util.nextModelName import soot.RefType import soot.Scene +import soot.Type /** * Auxiliary enum class for specifying an implementation for [CommonStreamWrapper], that it will use. @@ -76,6 +77,9 @@ abstract class StreamWrapper( UtAssembleModel(addr, utStreamClass.overriddenStreamClassId, modelName, instantiationCall) } + override fun getPotentialPossibleTypes(type: Type): Set = + setOf(STREAM_TYPE) + override fun chooseClassIdWithConstructor(classId: ClassId): ClassId = error("No constructor for Stream") override val modificationMethodId: MethodId diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/Strings.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/Strings.kt index 08a6083c36..4eba001fe6 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/Strings.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/Strings.kt @@ -1,6 +1,9 @@ package org.utbot.engine import com.github.curiousoddman.rgxgen.RgxGen +import kotlin.math.max +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.persistentSetOf import org.utbot.common.unreachableBranch import org.utbot.engine.overrides.strings.UtNativeString import org.utbot.engine.overrides.strings.UtString @@ -43,15 +46,13 @@ import org.utbot.framework.plugin.api.util.charClassId import org.utbot.framework.plugin.api.util.constructorId import org.utbot.framework.plugin.api.util.defaultValueModel import org.utbot.framework.util.nextModelName -import kotlin.math.max -import kotlinx.collections.immutable.persistentListOf -import kotlinx.collections.immutable.persistentSetOf import soot.CharType import soot.IntType import soot.Scene import soot.SootClass import soot.SootField import soot.SootMethod +import soot.Type val utStringClass: SootClass get() = Scene.v().getSootClass(UtString::class.qualifiedName) @@ -186,6 +187,9 @@ class StringWrapper : BaseOverriddenWrapper(utStringClass.name) { ) return UtAssembleModel(addr, classId, modelName, instantiationCall) } + + override fun getPotentialPossibleTypes(type: Type): Set = + setOf(STRING_TYPE) } internal val utNativeStringClass = Scene.v().getSootClass(UtNativeString::class.qualifiedName) @@ -281,6 +285,9 @@ class UtNativeStringWrapper : WrapperInterface { } override fun value(resolver: Resolver, wrapper: ObjectValue): UtModel = UtNullModel(STRING_TYPE.classId) + + override fun getPotentialPossibleTypes(type: Type): Set = + setOf(STRING_TYPE) } sealed class UtAbstractStringBuilderWrapper(className: String) : BaseOverriddenWrapper(className) { @@ -337,6 +344,9 @@ sealed class UtAbstractStringBuilderWrapper(className: String) : BaseOverriddenW return UtAssembleModel(addr, wrapper.type.classId, modelName, instantiationCall) } + override fun getPotentialPossibleTypes(type: Type): Set = + setOf(STRING_TYPE) + private val SootClass.valueField: SootField get() = getField("value", CharType.v().arrayType) diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/SymbolicValue.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/SymbolicValue.kt index 808ea96eee..0f8c987719 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/SymbolicValue.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/SymbolicValue.kt @@ -1,5 +1,6 @@ package org.utbot.engine +import java.util.Objects import org.utbot.engine.pc.UtAddrExpression import org.utbot.engine.pc.UtExpression import org.utbot.engine.pc.isConcrete @@ -12,7 +13,6 @@ import org.utbot.engine.pc.mkInt import org.utbot.engine.pc.mkLong import org.utbot.engine.pc.mkShort import org.utbot.engine.pc.toConcrete -import java.util.Objects import soot.ArrayType import soot.BooleanType import soot.ByteType @@ -179,7 +179,10 @@ fun SymbolicValue.toConcrete(): Any = when (this) { // TODO: one more constructor? fun objectValue(type: RefType, addr: UtAddrExpression, implementation: WrapperInterface) = - ObjectValue(TypeStorage(type), addr, Concrete(implementation)) + ObjectValue( + TypeStorage(type, implementation.getPotentialPossibleTypes(type)), + addr, Concrete(implementation) + ) val voidValue get() = PrimitiveValue(VoidType.v(), nullObjectAddr) From edabce1a92694586919dfae9712c8c168c3a3454 Mon Sep 17 00:00:00 2001 From: Rustam Sadykov Date: Mon, 19 Sep 2022 16:36:52 +0300 Subject: [PATCH 2/3] add test --- .../org/utbot/examples/casts/InstanceOfExampleTest.kt | 10 ++++++++++ .../org/utbot/examples/casts/InstanceOfExample.java | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/utbot-framework-test/src/test/kotlin/org/utbot/examples/casts/InstanceOfExampleTest.kt b/utbot-framework-test/src/test/kotlin/org/utbot/examples/casts/InstanceOfExampleTest.kt index 2b4561ecf3..72d6dc932a 100644 --- a/utbot-framework-test/src/test/kotlin/org/utbot/examples/casts/InstanceOfExampleTest.kt +++ b/utbot-framework-test/src/test/kotlin/org/utbot/examples/casts/InstanceOfExampleTest.kt @@ -404,6 +404,16 @@ internal class InstanceOfExampleTest : UtValueTestCaseChecker( ) } + @Test + fun testInstanceOfString() { + check( + InstanceOfExample::instanceOfString, + eq(2), + { cs, r -> cs == null && r == Unit }, + { cs, r -> cs is String && r == null } + ) + } + private inline fun Any?.isInstanceOfArray() = (this as? Array<*>)?.run { T::class.java.isAssignableFrom(this::class.java.componentType) } == true diff --git a/utbot-sample/src/main/java/org/utbot/examples/casts/InstanceOfExample.java b/utbot-sample/src/main/java/org/utbot/examples/casts/InstanceOfExample.java index 0ad14f3a82..ee23d27026 100644 --- a/utbot-sample/src/main/java/org/utbot/examples/casts/InstanceOfExample.java +++ b/utbot-sample/src/main/java/org/utbot/examples/casts/InstanceOfExample.java @@ -322,4 +322,10 @@ public Object[] instanceOfObjectArray(Object[] array) { return array; } + + public void instanceOfString(CharSequence cs) { + if (cs instanceof String) { + throw new IllegalStateException("CharSequence must not be a String"); + } + } } From c390666a202595d32f78069f68c69fb76bf3a142 Mon Sep 17 00:00:00 2001 From: Rustam Sadykov Date: Wed, 21 Sep 2022 18:06:25 +0300 Subject: [PATCH 3/3] fix review --- .../examples/casts/InstanceOfExampleTest.kt | 65 ++++++++++++++++--- .../org/utbot/engine/ArrayObjectWrappers.kt | 13 ++-- .../org/utbot/engine/CollectionWrappers.kt | 23 +------ .../kotlin/org/utbot/engine/Extensions.kt | 26 +++++--- .../src/main/kotlin/org/utbot/engine/Mocks.kt | 2 +- .../kotlin/org/utbot/engine/ObjectWrappers.kt | 39 ++++++----- .../org/utbot/engine/OptionalWrapper.kt | 2 +- .../utbot/engine/SecurityManagerWrapper.kt | 2 +- .../kotlin/org/utbot/engine/StreamWrappers.kt | 4 +- .../main/kotlin/org/utbot/engine/Strings.kt | 8 +-- .../kotlin/org/utbot/engine/SymbolicValue.kt | 2 +- .../examples/casts/InstanceOfExample.java | 56 ++++++++++++++-- 12 files changed, 168 insertions(+), 74 deletions(-) diff --git a/utbot-framework-test/src/test/kotlin/org/utbot/examples/casts/InstanceOfExampleTest.kt b/utbot-framework-test/src/test/kotlin/org/utbot/examples/casts/InstanceOfExampleTest.kt index 72d6dc932a..ad6a8794c0 100644 --- a/utbot-framework-test/src/test/kotlin/org/utbot/examples/casts/InstanceOfExampleTest.kt +++ b/utbot-framework-test/src/test/kotlin/org/utbot/examples/casts/InstanceOfExampleTest.kt @@ -1,14 +1,14 @@ package org.utbot.examples.casts -import org.utbot.tests.infrastructure.UtValueTestCaseChecker -import org.utbot.tests.infrastructure.DoNotCalculate -import org.utbot.tests.infrastructure.ignoreExecutionsNumber -import org.utbot.framework.plugin.api.CodegenLanguage import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test +import org.utbot.framework.plugin.api.CodegenLanguage import org.utbot.testcheckers.eq import org.utbot.testcheckers.ge import org.utbot.tests.infrastructure.CodeGeneration +import org.utbot.tests.infrastructure.DoNotCalculate +import org.utbot.tests.infrastructure.UtValueTestCaseChecker +import org.utbot.tests.infrastructure.ignoreExecutionsNumber // TODO failed Kotlin compilation SAT-1332 internal class InstanceOfExampleTest : UtValueTestCaseChecker( @@ -405,15 +405,64 @@ internal class InstanceOfExampleTest : UtValueTestCaseChecker( } @Test - fun testInstanceOfString() { + fun testStringInstanceOf() { check( - InstanceOfExample::instanceOfString, + InstanceOfExample::charSequenceInstanceOf, eq(2), - { cs, r -> cs == null && r == Unit }, - { cs, r -> cs is String && r == null } + { _, r -> r == null }, + { _, r -> r!!::class == String::class } ) } + @Test + fun testListInstanceOf() { + check( + InstanceOfExample::listInstanceOf, + eq(2), + { _, r -> r == null }, + { _, r -> r!!::class == java.util.ArrayList::class } + ) + } + + @Test + fun testDequeInstanceOf() { + check( + InstanceOfExample::dequeInstanceOf, + eq(2), + { _, r -> r == null }, + { _, r -> r!!::class == java.util.LinkedList::class } + ) + } + + @Test + fun testAbstractSeqListInstanceOf() { + check( + InstanceOfExample::abstractSequentialListInstanceOf, + eq(2), + { _, r -> r == null }, + { _, r -> r!!::class == java.util.LinkedList::class } + ) + } + + @Test + fun testSetInstanceOf() { + check( + InstanceOfExample::setInstanceOf, + eq(2), + { _, r -> r == null }, + { _, r -> r!!::class == java.util.LinkedHashSet::class } + ) + } + + @Test + fun testMapInstanceOf() { + check( + InstanceOfExample::mapInstanceOf, + eq(2), + { _, r -> r == null }, + { _, r -> r!!::class == java.util.LinkedHashMap::class } + ) + } private inline fun Any?.isInstanceOfArray() = (this as? Array<*>)?.run { T::class.java.isAssignableFrom(this::class.java.componentType) } == true diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/ArrayObjectWrappers.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/ArrayObjectWrappers.kt index 4c444f9c9b..ee39b4804d 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/ArrayObjectWrappers.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/ArrayObjectWrappers.kt @@ -264,8 +264,12 @@ class RangeModifiableUnlimitedArrayWrapper : WrapperInterface { return resultModel } - override fun getPotentialPossibleTypes(type: Type): Set = - setOf(ARRAY_OBJECT_TYPE) + override fun getPossibleConcreteTypes(type: Type): Set { + val possibleObjectTypes = Scene.v().classes.map { it.type } + return possibleObjectTypes.mapTo(mutableSetOf()) { + it.arrayType + } + } companion object { internal val rangeModifiableArrayClass: SootClass @@ -280,7 +284,6 @@ class RangeModifiableUnlimitedArrayWrapper : WrapperInterface { } val associativeArrayId: ClassId = AssociativeArray::class.id -val associativeArrayType: Type = Scene.v().getSootClass(AssociativeArray::class.java.canonicalName).type class AssociativeArrayWrapper : WrapperInterface { @@ -419,8 +422,8 @@ class AssociativeArrayWrapper : WrapperInterface { return model } - override fun getPotentialPossibleTypes(type: Type): Set = - setOf(associativeArrayType) + override fun getPossibleConcreteTypes(type: Type): Set = + setOf(associativeArrayClass.type) private fun Traverser.getStorageArrayField(addr: UtAddrExpression) = getArrayField(addr, associativeArrayClass, storageField) diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/CollectionWrappers.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/CollectionWrappers.kt index bbda8a7633..e149bcd96f 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/CollectionWrappers.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/CollectionWrappers.kt @@ -34,7 +34,6 @@ import org.utbot.framework.plugin.api.util.methodId import org.utbot.framework.plugin.api.util.objectClassId import org.utbot.framework.util.graph import org.utbot.framework.util.nextModelName -import soot.ArrayType import soot.IntType import soot.RefType import soot.Scene @@ -132,8 +131,8 @@ abstract class BaseContainerWrapper(containerClassName: String) : BaseOverridden } } - override fun getPotentialPossibleTypes(type: Type): Set = - setOf(Scene.v().getSootClass(chooseClassIdWithConstructor(type.classId).canonicalName).type) + override fun getPossibleConcreteTypes(type: Type): Set = + setOf(chooseClassIdWithConstructor(type.classId).sootType) /** * Method returns list of parameter models that will be passed to [modificationMethodId] @@ -403,24 +402,6 @@ private val UT_GENERIC_ASSOCIATIVE_CLASS private val UT_GENERIC_ASSOCIATIVE_SET_EQUAL_GENERIC_TYPE_SIGNATURE = UT_GENERIC_ASSOCIATIVE_CLASS.getMethodByName(UtGenericAssociative<*, *>::setEqualGenericType.name).signature -val ARRAY_OBJECT_TYPE: Type - get() = ArrayType.v(OBJECT_TYPE, 1) - -val ARRAY_LIST_TYPE: RefType - get() = Scene.v().getSootClass(java.util.ArrayList::class.java.canonicalName).type -val LINKED_LIST_TYPE: RefType - get() = Scene.v().getSootClass(java.util.LinkedList::class.java.canonicalName).type - -val LINKED_HASH_SET_TYPE: RefType - get() = Scene.v().getSootClass(java.util.LinkedHashSet::class.java.canonicalName).type -val HASH_SET_TYPE: RefType - get() = Scene.v().getSootClass(java.util.HashSet::class.java.canonicalName).type - -val LINKED_HASH_MAP_TYPE: RefType - get() = Scene.v().getSootClass(java.util.LinkedHashMap::class.java.canonicalName).type -val HASH_MAP_TYPE: RefType - get() = Scene.v().getSootClass(java.util.HashMap::class.java.canonicalName).type - val STREAM_TYPE: RefType get() = Scene.v().getSootClass(java.util.stream.Stream::class.java.canonicalName).type diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/Extensions.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/Extensions.kt index 1de5fa185a..d3f4a92bb1 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/Extensions.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/Extensions.kt @@ -1,6 +1,14 @@ package org.utbot.engine import com.google.common.collect.BiMap +import java.lang.reflect.ParameterizedType +import java.util.ArrayDeque +import java.util.Deque +import java.util.LinkedList +import java.util.Queue +import java.util.concurrent.ConcurrentHashMap +import kotlinx.collections.immutable.PersistentMap +import kotlinx.collections.immutable.persistentHashMapOf import org.utbot.api.mock.UtMock import org.utbot.engine.pc.UtAddrExpression import org.utbot.engine.pc.UtArraySort @@ -33,8 +41,11 @@ import org.utbot.engine.pc.mkString import org.utbot.engine.pc.toSort import org.utbot.framework.UtSettings.checkNpeInNestedMethods import org.utbot.framework.UtSettings.checkNpeInNestedNotPrivateMethods +import org.utbot.framework.plugin.api.ClassId import org.utbot.framework.plugin.api.FieldId import org.utbot.framework.plugin.api.id +import org.utbot.framework.plugin.api.util.isArray +import org.utbot.framework.plugin.api.util.isPrimitive import soot.ArrayType import soot.PrimType import soot.RefLikeType @@ -60,14 +71,6 @@ import soot.jimple.internal.JStaticInvokeExpr import soot.jimple.internal.JVirtualInvokeExpr import soot.jimple.internal.JimpleLocal import soot.tagkit.ArtificialEntityTag -import java.lang.reflect.ParameterizedType -import java.util.ArrayDeque -import java.util.Deque -import java.util.LinkedList -import java.util.Queue -import java.util.concurrent.ConcurrentHashMap -import kotlinx.collections.immutable.PersistentMap -import kotlinx.collections.immutable.persistentHashMapOf val JIdentityStmt.lines: String get() = tags.joinToString { "$it" } @@ -424,3 +427,10 @@ val SootMethod.isUtMockAssumeOrExecuteConcretely */ val SootMethod.isPreconditionCheckMethod get() = declaringClass.isOverridden && name == "preconditionCheck" + +val ClassId.sootType: Type + get() = when { + isPrimitive -> Scene.v().getType(name) + isArray -> elementClassId!!.sootType.arrayType + else -> Scene.v().getSootClass(canonicalName).type + } diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/Mocks.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/Mocks.kt index 5c26161223..33be279fc4 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/Mocks.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/Mocks.kt @@ -307,7 +307,7 @@ class UtMockWrapper( override fun value(resolver: Resolver, wrapper: ObjectValue): UtModel = TODO("value on mock called: $this") - override fun getPotentialPossibleTypes(type: Type): Set = + override fun getPossibleConcreteTypes(type: Type): Set = setOf(this.type) override fun toString() = "UtMock(type=$type, target=$mockInfo)" diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/ObjectWrappers.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/ObjectWrappers.kt index fa0db83864..b5348201f0 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/ObjectWrappers.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/ObjectWrappers.kt @@ -152,15 +152,15 @@ private val wrappers = mapOf( }, // list wrappers - wrap(java.util.List::class) { _, addr -> objectValue(ARRAY_LIST_TYPE, addr, ListWrapper(UT_ARRAY_LIST)) }, - wrap(java.util.AbstractList::class) { _, addr -> objectValue(ARRAY_LIST_TYPE, addr, ListWrapper(UT_ARRAY_LIST)) }, - wrap(java.util.ArrayList::class) { _, addr -> objectValue(ARRAY_LIST_TYPE, addr, ListWrapper(UT_ARRAY_LIST)) }, + wrap(java.util.List::class) { type, addr -> objectValue(type, addr, ListWrapper(UT_ARRAY_LIST)) }, + wrap(java.util.AbstractList::class) { type, addr -> objectValue(type, addr, ListWrapper(UT_ARRAY_LIST)) }, + wrap(java.util.ArrayList::class) { type, addr -> objectValue(type, addr, ListWrapper(UT_ARRAY_LIST)) }, wrap(CopyOnWriteArrayList::class) { type, addr -> objectValue(type, addr, ListWrapper(UT_ARRAY_LIST)) }, - wrap(java.util.LinkedList::class) { _, addr -> objectValue(LINKED_LIST_TYPE, addr, ListWrapper(UT_LINKED_LIST)) }, - wrap(java.util.AbstractSequentialList::class) { _, addr -> objectValue(LINKED_LIST_TYPE, addr, ListWrapper(UT_LINKED_LIST)) }, + wrap(java.util.LinkedList::class) { type, addr -> objectValue(type, addr, ListWrapper(UT_LINKED_LIST)) }, + wrap(java.util.AbstractSequentialList::class) { type, addr -> objectValue(type, addr, ListWrapper(UT_LINKED_LIST)) }, // queue, deque wrappers wrap(java.util.ArrayDeque::class) { type, addr -> @@ -180,17 +180,17 @@ private val wrappers = mapOf( }, // set wrappers - wrap(java.util.Set::class) { _, addr -> objectValue(LINKED_HASH_SET_TYPE, addr, SetWrapper()) }, - wrap(java.util.AbstractSet::class) { _, addr -> objectValue(LINKED_HASH_SET_TYPE, addr, SetWrapper()) }, - wrap(java.util.HashSet::class) { _, addr -> objectValue(HASH_SET_TYPE, addr, SetWrapper()) }, - wrap(java.util.LinkedHashSet::class) { _, addr -> objectValue(LINKED_HASH_SET_TYPE, addr, SetWrapper()) }, + wrap(java.util.Set::class) { type, addr -> objectValue(type, addr, SetWrapper()) }, + wrap(java.util.AbstractSet::class) { type, addr -> objectValue(type, addr, SetWrapper()) }, + wrap(java.util.HashSet::class) { type, addr -> objectValue(type, addr, SetWrapper()) }, + wrap(java.util.LinkedHashSet::class) { type, addr -> objectValue(type, addr, SetWrapper()) }, // map wrappers - wrap(java.util.Map::class) { _, addr -> objectValue(LINKED_HASH_MAP_TYPE, addr, MapWrapper()) }, - wrap(java.util.AbstractMap::class) { _, addr -> objectValue(LINKED_HASH_MAP_TYPE, addr, MapWrapper()) }, - wrap(java.util.LinkedHashMap::class) { _, addr -> objectValue(LINKED_HASH_MAP_TYPE, addr, MapWrapper()) }, - wrap(java.util.HashMap::class) { _, addr -> objectValue(HASH_MAP_TYPE, addr, MapWrapper()) }, - wrap(java.util.concurrent.ConcurrentHashMap::class) { _, addr -> objectValue(HASH_MAP_TYPE, addr, MapWrapper()) }, + wrap(java.util.Map::class) { type, addr -> objectValue(type, addr, MapWrapper()) }, + wrap(java.util.AbstractMap::class) { type, addr -> objectValue(type, addr, MapWrapper()) }, + wrap(java.util.LinkedHashMap::class) { type, addr -> objectValue(type, addr, MapWrapper()) }, + wrap(java.util.HashMap::class) { type, addr -> objectValue(type, addr, MapWrapper()) }, + wrap(java.util.concurrent.ConcurrentHashMap::class) { type, addr -> objectValue(type, addr, MapWrapper()) }, // stream wrappers wrap(java.util.stream.BaseStream::class) { _, addr -> objectValue(STREAM_TYPE, addr, CommonStreamWrapper()) }, @@ -225,9 +225,12 @@ interface WrapperInterface { fun value(resolver: Resolver, wrapper: ObjectValue): UtModel /** - * Returns list of types that can be produced by [value] method. + * Returns list of possible concrete types that can be produced by [value] method. + * Used for wrapper initialization. + * + * @param type target type to wrap */ - fun getPotentialPossibleTypes(type: Type): Set + fun getPossibleConcreteTypes(type: Type): Set } // TODO: perhaps we have to have wrapper around concrete value here @@ -259,6 +262,6 @@ data class ThrowableWrapper(val throwable: Throwable) : WrapperInterface { return UtAssembleModel(addr, classId, modelName, instantiationCall) } - override fun getPotentialPossibleTypes(type: Type): Set = - setOf(Scene.v().getSootClass(throwable.javaClass.canonicalName).type) + override fun getPossibleConcreteTypes(type: Type): Set = + setOf(throwable.javaClass.id.sootType) } \ No newline at end of file diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/OptionalWrapper.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/OptionalWrapper.kt index ba76eb559a..9d2a3b72d8 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/OptionalWrapper.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/OptionalWrapper.kt @@ -94,7 +94,7 @@ class OptionalWrapper(private val utOptionalClass: UtOptionalClass) : BaseOverri return UtAssembleModel(addr, classId, modelName, instantiationCall) } - override fun getPotentialPossibleTypes(type: Type): Set = + override fun getPossibleConcreteTypes(type: Type): Set = setOf(type) private fun Resolver.instantiationFactoryCallModel(classId: ClassId, wrapper: ObjectValue) : UtExecutableCallModel { diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/SecurityManagerWrapper.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/SecurityManagerWrapper.kt index 728b233f26..04b76a0726 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/SecurityManagerWrapper.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/SecurityManagerWrapper.kt @@ -38,7 +38,7 @@ class SecurityManagerWrapper : BaseOverriddenWrapper(utSecurityManagerClass.name return UtAssembleModel(addr, classId, modelName, instantiationCall) } - override fun getPotentialPossibleTypes(type: Type): Set = + override fun getPossibleConcreteTypes(type: Type): Set = setOf(type) companion object { diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/StreamWrappers.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/StreamWrappers.kt index 922785d57e..fa3abbdb45 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/StreamWrappers.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/StreamWrappers.kt @@ -77,8 +77,8 @@ abstract class StreamWrapper( UtAssembleModel(addr, utStreamClass.overriddenStreamClassId, modelName, instantiationCall) } - override fun getPotentialPossibleTypes(type: Type): Set = - setOf(STREAM_TYPE) + override fun getPossibleConcreteTypes(type: Type): Set = + setOf(utStreamClass.overriddenStreamClassId.sootType) override fun chooseClassIdWithConstructor(classId: ClassId): ClassId = error("No constructor for Stream") diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/Strings.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/Strings.kt index 4eba001fe6..08b74685ce 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/Strings.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/Strings.kt @@ -188,7 +188,7 @@ class StringWrapper : BaseOverriddenWrapper(utStringClass.name) { return UtAssembleModel(addr, classId, modelName, instantiationCall) } - override fun getPotentialPossibleTypes(type: Type): Set = + override fun getPossibleConcreteTypes(type: Type): Set = setOf(STRING_TYPE) } @@ -286,7 +286,7 @@ class UtNativeStringWrapper : WrapperInterface { override fun value(resolver: Resolver, wrapper: ObjectValue): UtModel = UtNullModel(STRING_TYPE.classId) - override fun getPotentialPossibleTypes(type: Type): Set = + override fun getPossibleConcreteTypes(type: Type): Set = setOf(STRING_TYPE) } @@ -344,8 +344,8 @@ sealed class UtAbstractStringBuilderWrapper(className: String) : BaseOverriddenW return UtAssembleModel(addr, wrapper.type.classId, modelName, instantiationCall) } - override fun getPotentialPossibleTypes(type: Type): Set = - setOf(STRING_TYPE) + override fun getPossibleConcreteTypes(type: Type): Set = + setOf(type) private val SootClass.valueField: SootField get() = getField("value", CharType.v().arrayType) diff --git a/utbot-framework/src/main/kotlin/org/utbot/engine/SymbolicValue.kt b/utbot-framework/src/main/kotlin/org/utbot/engine/SymbolicValue.kt index 0f8c987719..0fec0da061 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/engine/SymbolicValue.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/engine/SymbolicValue.kt @@ -180,7 +180,7 @@ fun SymbolicValue.toConcrete(): Any = when (this) { // TODO: one more constructor? fun objectValue(type: RefType, addr: UtAddrExpression, implementation: WrapperInterface) = ObjectValue( - TypeStorage(type, implementation.getPotentialPossibleTypes(type)), + TypeStorage(type, implementation.getPossibleConcreteTypes(type)), addr, Concrete(implementation) ) diff --git a/utbot-sample/src/main/java/org/utbot/examples/casts/InstanceOfExample.java b/utbot-sample/src/main/java/org/utbot/examples/casts/InstanceOfExample.java index ee23d27026..e41af60e0b 100644 --- a/utbot-sample/src/main/java/org/utbot/examples/casts/InstanceOfExample.java +++ b/utbot-sample/src/main/java/org/utbot/examples/casts/InstanceOfExample.java @@ -1,8 +1,7 @@ package org.utbot.examples.casts; +import java.util.*; import org.utbot.api.mock.UtMock; -import java.util.HashMap; -import java.util.Map; public class InstanceOfExample { public CastClassFirstSucc simpleInstanceOf(CastClass objectExample) { @@ -323,9 +322,58 @@ public Object[] instanceOfObjectArray(Object[] array) { return array; } - public void instanceOfString(CharSequence cs) { + public CharSequence charSequenceInstanceOf(CharSequence cs) { if (cs instanceof String) { - throw new IllegalStateException("CharSequence must not be a String"); + return cs; } + return cs; } + + public List listInstanceOf(List list) { + if (list instanceof AbstractList) { + if (list instanceof ArrayList) { + return list; + } + } + return list; + } + + public Deque dequeInstanceOf(Deque deque) { + if (deque instanceof LinkedList) { + return deque; + } + return deque; + } + + public AbstractSequentialList abstractSequentialListInstanceOf(AbstractSequentialList list) { + if (list instanceof LinkedList) { + return list; + } + return list; + } + + public Set setInstanceOf(Set set) { + if (set instanceof AbstractSet) { + if (set instanceof HashSet) { + if (set instanceof LinkedHashSet) { + return set; + } + // TODO: we have wrapper of HashSet and this branch must be covered, but now it's not truth + } + } + return set; + } + + public Map mapInstanceOf(Map map) { + if (map instanceof AbstractMap) { + if (map instanceof HashMap) { + if (map instanceof LinkedHashMap) { + return map; + } + // TODO: we have wrapper of HashMap and this branch must be covered, but now it's not truth + } + } + return map; + } + }